├── test ├── fixtures │ ├── config │ │ ├── malformed │ │ ├── .npmrc │ │ ├── builtin │ │ ├── globalconfig │ │ └── userconfig │ ├── onload.js │ ├── gitignore.tgz │ ├── npmignore.tgz │ ├── forked-underscore-1.5.1.tgz │ ├── gitignore-and-npmignore.tgz │ ├── scoped-underscore-1.3.1.tgz │ ├── github-com-BryanDonovan-npm-git-test.git.tar.gz │ ├── github-com-BryanDonovan-dummy-npm-bar.git.tar.gz │ ├── github-com-BryanDonovan-dummy-npm-buzz.git.tar.gz │ └── github-com-BryanDonovan-dummy-npm-foo.git.tar.gz ├── tap │ ├── zz-cleanup.js │ ├── ls-no-results.js │ ├── config-malformed.js │ ├── 00-verify-bundle-deps.js │ ├── semver-doc.js │ ├── unit-child-path.js │ ├── 00-check-mock-dep.js │ ├── outdated-bad-read-tree.js │ ├── config-certfile.js │ ├── normalize-package-explode.js │ ├── 00-verify-ls-ok.js │ ├── bin.js │ ├── referer.js │ ├── cache-add-unpublished.js │ ├── spawn-enoent-help.js │ ├── global-prefix-set-in-userconfig.js │ ├── unit-package-id.js │ ├── update-path.js │ ├── spawn-enoent.js │ ├── test-run-ls.js │ ├── uninstall-in-reverse.js │ ├── cruft-test.js │ ├── pwd-prefix.js │ ├── node-modules-path-munge.js │ ├── publish-access-unscoped-restricted-fails.js │ ├── install-parse-error.js │ ├── install-into-likenamed-folder.js │ ├── invalid-cmd-exit-code.js │ ├── 00-verify-no-scoped.js │ ├── npm-api-not-loaded-error.js │ ├── config-list.js │ ├── unit-deps-removeObsoleteDep.js │ ├── version-no-package.js │ ├── nerf-dart.js │ ├── unsupported.js │ ├── lifecycle.js │ ├── run-script-filter-private.js │ ├── install-order.js │ ├── nested-extraneous.js │ ├── onload.js │ ├── config-new-cafile.js │ ├── bundled-no-add-to-move.js │ ├── 404-private-registry.js │ ├── install-bad-dep-format.js │ ├── legacy-private.js │ ├── symlink-cycle.js │ ├── 404-private-registry-scoped.js │ ├── local-args-relative-to-cwd.js │ ├── ping.js │ ├── init-interrupt.js │ ├── logout.js │ ├── install-scoped-with-peer-dependency.js │ ├── bundled-dependencies-no-pkgjson.js │ ├── shrinkwrap-lifecycle.js │ ├── legacy-platform.js │ ├── config-project.js │ ├── version-no-git.js │ ├── install-cli-production-nosave.js │ ├── ls-top-errors.js │ └── gently-rm-overeager.js ├── network │ ├── git-cache-locking.js │ ├── legacy-url-dep.js │ └── git-cache-no-hooks.js └── need-npm5-update │ ├── outdated-notarget.js │ └── outdated-include-devdependencies.js ├── lib ├── start.js ├── stop.js ├── restart.js ├── utils │ ├── is-windows.js │ ├── is-windows-bash.js │ ├── is-windows-shell.js │ ├── temp-filename.js │ ├── ansi-trim.js │ ├── output.js │ ├── child-path.js │ ├── read-local-package.js │ ├── umask.js │ ├── save-stack.js │ ├── package-id.js │ ├── deep-sort-object.js │ ├── move.js │ ├── pulse-till-done.js │ ├── depr-check.js │ ├── gunzip-maybe.js │ ├── no-progress-while-running.js │ ├── warn-deprecated.js │ ├── perf.js │ ├── usage.js │ ├── parse-json.js │ ├── completion │ │ ├── file-completion.js │ │ └── installed-deep.js │ ├── escape-arg.js │ ├── escape-exec-path.js │ ├── module-name.js │ ├── pick-manifest-from-registry-metadata.js │ ├── get-publish-config.js │ ├── metrics-launch.js │ ├── unsupported.js │ ├── git.js │ └── spawn.js ├── auth │ ├── oauth.js │ └── saml.js ├── install │ ├── is-dev-dep.js │ ├── is-opt-dep.js │ ├── is-prod-dep.js │ ├── access-error.js │ ├── and-ignore-errors.js │ ├── action │ │ ├── global-link.js │ │ ├── install.js │ │ ├── postinstall.js │ │ ├── preinstall.js │ │ ├── fetch.js │ │ ├── build.js │ │ ├── global-install.js │ │ ├── prepare.js │ │ └── refresh-package-json.js │ ├── module-staging-path.js │ ├── and-add-parent-to-errors.js │ ├── and-finish-tracker.js │ ├── get-requested.js │ ├── realize-shrinkwrap-specifier.js │ ├── inflate-bundled.js │ ├── is-extraneous.js │ ├── is-fs-access-available.js │ ├── exists.js │ ├── copy-tree.js │ ├── writable.js │ ├── report-optional-failure.js │ └── flatten-tree.js ├── get.js ├── set.js ├── doctor │ ├── get-git-path.js │ ├── check-ping.js │ ├── get-latest-npm-version.js │ ├── get-latest-nodejs-version.js │ └── verify-cached-files.js ├── root.js ├── prefix.js ├── config │ ├── load-uid.js │ ├── clear-credentials-by-uri.js │ ├── nerf-dart.js │ ├── load-cafile.js │ ├── set-user.js │ ├── reg-client.js │ ├── set-credentials-by-uri.js │ ├── load-prefix.js │ └── find-prefix.js ├── test.js ├── substack.js ├── bin.js ├── install-test.js ├── ping.js ├── bugs.js ├── edit.js ├── docs.js ├── logout.js ├── stars.js ├── search │ └── package-filter.js ├── star.js ├── init.js ├── adduser.js ├── whoami.js ├── deprecate.js ├── team.js └── repo.js ├── html ├── n-64.png ├── npm.png ├── favicon.ico ├── n-large.png ├── npm-16.png ├── npm-fin.png ├── npm-256w.png ├── npm-large.png ├── npm-256-square.png ├── npm-64-square.png ├── npm-large-trans.png ├── npm-logo-white-trans.png ├── dochead.html └── static │ └── toc.js ├── .npmrc ├── make.bat ├── scripts ├── publish-tag.js ├── dep-update ├── dev-dep-update ├── update-authors.sh ├── gen-changelog ├── relocate.sh └── release.sh ├── bin ├── node-gyp-bin │ ├── node-gyp.cmd │ └── node-gyp ├── npm.cmd ├── read-package-json.js └── npm ├── doc ├── cli │ ├── npm-ping.md │ ├── npm-whoami.md │ ├── npm-stop.md │ ├── npm-root.md │ ├── npm-bin.md │ ├── npm-test.md │ ├── npm-bundle.md │ ├── npm-rebuild.md │ ├── npm-stars.md │ ├── npm-star.md │ ├── npm-prefix.md │ ├── npm-build.md │ ├── npm-start.md │ ├── npm-repo.md │ ├── npm-shrinkwrap.md │ ├── npm-install-test.md │ ├── npm-deprecate.md │ ├── npm-pack.md │ ├── npm-prune.md │ ├── npm-completion.md │ ├── npm-restart.md │ ├── npm-help-search.md │ ├── npm-help.md │ ├── npm-edit.md │ ├── npm-explore.md │ ├── npm-bugs.md │ ├── npm-owner.md │ ├── npm-init.md │ ├── npm-docs.md │ ├── npm-logout.md │ ├── npm-unpublish.md │ ├── npm-uninstall.md │ ├── npm-dedupe.md │ └── npm-config.md └── files │ └── npm-shrinkwrap.json.md ├── configure ├── .npmignore ├── .gitignore └── appveyor.yml /test/fixtures/config/malformed: -------------------------------------------------------------------------------- 1 | email = """ -------------------------------------------------------------------------------- /test/fixtures/config/.npmrc: -------------------------------------------------------------------------------- 1 | just = testing 2 | -------------------------------------------------------------------------------- /test/fixtures/config/builtin: -------------------------------------------------------------------------------- 1 | builtin-config = true 2 | -------------------------------------------------------------------------------- /test/fixtures/onload.js: -------------------------------------------------------------------------------- 1 | console.error('called onload') 2 | -------------------------------------------------------------------------------- /test/fixtures/config/globalconfig: -------------------------------------------------------------------------------- 1 | package-config:foo = boo 2 | -------------------------------------------------------------------------------- /lib/start.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./utils/lifecycle.js').cmd('start') 2 | -------------------------------------------------------------------------------- /lib/stop.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./utils/lifecycle.js').cmd('stop') 2 | -------------------------------------------------------------------------------- /html/n-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/n-64.png -------------------------------------------------------------------------------- /html/npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm.png -------------------------------------------------------------------------------- /lib/restart.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./utils/lifecycle.js').cmd('restart') 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-prefix = ~ 2 | proprietary-attribs = false 3 | legacy-bundling = true 4 | -------------------------------------------------------------------------------- /html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/favicon.ico -------------------------------------------------------------------------------- /html/n-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/n-large.png -------------------------------------------------------------------------------- /html/npm-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-16.png -------------------------------------------------------------------------------- /html/npm-fin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-fin.png -------------------------------------------------------------------------------- /html/npm-256w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-256w.png -------------------------------------------------------------------------------- /html/npm-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-large.png -------------------------------------------------------------------------------- /lib/utils/is-windows.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = process.platform === 'win32' 3 | -------------------------------------------------------------------------------- /html/npm-256-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-256-square.png -------------------------------------------------------------------------------- /html/npm-64-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-64-square.png -------------------------------------------------------------------------------- /html/npm-large-trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-large-trans.png -------------------------------------------------------------------------------- /html/npm-logo-white-trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/html/npm-logo-white-trans.png -------------------------------------------------------------------------------- /test/fixtures/gitignore.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/gitignore.tgz -------------------------------------------------------------------------------- /test/fixtures/npmignore.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/npmignore.tgz -------------------------------------------------------------------------------- /test/fixtures/forked-underscore-1.5.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/forked-underscore-1.5.1.tgz -------------------------------------------------------------------------------- /test/fixtures/gitignore-and-npmignore.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/gitignore-and-npmignore.tgz -------------------------------------------------------------------------------- /test/fixtures/scoped-underscore-1.3.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/scoped-underscore-1.3.1.tgz -------------------------------------------------------------------------------- /lib/utils/is-windows-bash.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var isWindows = require('./is-windows.js') 3 | module.exports = isWindows && /^MINGW(32|64)$/.test(process.env.MSYSTEM) 4 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | :: The tests run "make doc" in the prepublish script, 2 | :: so this file gives windows something that'll exit 3 | :: successfully, without having to install make. 4 | -------------------------------------------------------------------------------- /test/fixtures/github-com-BryanDonovan-npm-git-test.git.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/github-com-BryanDonovan-npm-git-test.git.tar.gz -------------------------------------------------------------------------------- /test/fixtures/github-com-BryanDonovan-dummy-npm-bar.git.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/github-com-BryanDonovan-dummy-npm-bar.git.tar.gz -------------------------------------------------------------------------------- /test/fixtures/github-com-BryanDonovan-dummy-npm-buzz.git.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/github-com-BryanDonovan-dummy-npm-buzz.git.tar.gz -------------------------------------------------------------------------------- /test/fixtures/github-com-BryanDonovan-dummy-npm-foo.git.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephfrazier/npm/latest/test/fixtures/github-com-BryanDonovan-dummy-npm-foo.git.tar.gz -------------------------------------------------------------------------------- /scripts/publish-tag.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver') 2 | var version = semver.parse(require('../package.json').version) 3 | console.log('v%s.%s-next', version.major, version.minor) 4 | -------------------------------------------------------------------------------- /bin/node-gyp-bin/node-gyp.cmd: -------------------------------------------------------------------------------- 1 | if not defined npm_config_node_gyp ( 2 | node "%~dp0\..\..\node_modules\node-gyp\bin\node-gyp.js" %* 3 | ) else ( 4 | node "%npm_config_node_gyp%" %* 5 | ) 6 | -------------------------------------------------------------------------------- /lib/utils/is-windows-shell.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var isWindows = require('./is-windows.js') 3 | var isWindowsBash = require('./is-windows-bash.js') 4 | module.exports = isWindows && !isWindowsBash 5 | -------------------------------------------------------------------------------- /scripts/dep-update: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node . install --save $1@$2 &&\ 3 | git add node_modules/$1/ package.json npm-shrinkwrap.json &&\ 4 | git commit -m"$1@$2" &&\ 5 | node . repo $1 &&\ 6 | git commit --amend 7 | -------------------------------------------------------------------------------- /scripts/dev-dep-update: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | node . install --save --save-dev $1@$2 &&\ 3 | git add package.json npm-shrinkwrap.json &&\ 4 | git commit -m"$1@$2" &&\ 5 | node . repo $1 &&\ 6 | git commit --amend 7 | -------------------------------------------------------------------------------- /bin/node-gyp-bin/node-gyp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | if [ "x$npm_config_node_gyp" = "x" ]; then 3 | node "`dirname "$0"`/../../node_modules/node-gyp/bin/node-gyp.js" "$@" 4 | else 5 | "$npm_config_node_gyp" "$@" 6 | fi 7 | -------------------------------------------------------------------------------- /lib/auth/oauth.js: -------------------------------------------------------------------------------- 1 | var ssoAuth = require('./sso') 2 | var npm = require('../npm') 3 | 4 | module.exports.login = function login () { 5 | npm.config.set('sso-type', 'oauth') 6 | ssoAuth.login.apply(this, arguments) 7 | } 8 | -------------------------------------------------------------------------------- /lib/auth/saml.js: -------------------------------------------------------------------------------- 1 | var ssoAuth = require('./sso') 2 | var npm = require('../npm') 3 | 4 | module.exports.login = function login () { 5 | npm.config.set('sso-type', 'saml') 6 | ssoAuth.login.apply(this, arguments) 7 | } 8 | -------------------------------------------------------------------------------- /lib/utils/temp-filename.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var uniqueFilename = require('unique-filename') 3 | var npm = require('../npm.js') 4 | 5 | module.exports = function (prefix) { 6 | return uniqueFilename(npm.tmp, prefix) 7 | } 8 | -------------------------------------------------------------------------------- /lib/install/is-dev-dep.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = isDevDep 3 | 4 | function isDevDep (node, name) { 5 | return node.package && 6 | node.package.devDependencies && 7 | node.package.devDependencies[name] 8 | } 9 | -------------------------------------------------------------------------------- /test/tap/zz-cleanup.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap') 2 | var test = require('tap').test 3 | var rimraf = require('rimraf') 4 | 5 | test('cleanup', function (t) { 6 | rimraf.sync(common.npm_config_cache) 7 | t.end() 8 | }) 9 | -------------------------------------------------------------------------------- /lib/install/is-opt-dep.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = isOptDep 3 | 4 | function isOptDep (node, name) { 5 | return node.package && 6 | node.package.optionalDependencies && 7 | node.package.optionalDependencies[name] 8 | } 9 | -------------------------------------------------------------------------------- /lib/install/is-prod-dep.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = isProdDep 4 | 5 | function isProdDep (node, name) { 6 | return node.package && 7 | node.package.dependencies && 8 | node.package.dependencies[name] 9 | } 10 | -------------------------------------------------------------------------------- /scripts/update-authors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | git log --reverse --format='%aN <%aE>' | perl -wnE ' 4 | BEGIN { 5 | say "# Authors sorted by whether or not they\x27re me"; 6 | } 7 | 8 | print $seen{$_} = $_ unless $seen{$_} 9 | ' > AUTHORS 10 | -------------------------------------------------------------------------------- /lib/install/access-error.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = function (dir, er) { 3 | if (!er) return 4 | var accessEr = new Error("EACCES, access '" + dir + "'", -13) 5 | accessEr.code = 'EACCES' 6 | accessEr.path = dir 7 | return accessEr 8 | } 9 | -------------------------------------------------------------------------------- /lib/utils/ansi-trim.js: -------------------------------------------------------------------------------- 1 | function ansiTrim (str) { 2 | var r = new RegExp('\x1b(?:\\[(?:\\d+[ABCDEFGJKSTm]|\\d+;\\d+[Hfm]|' + 3 | '\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)', 'g') 4 | return str.replace(r, '') 5 | } 6 | 7 | module.exports = ansiTrim 8 | -------------------------------------------------------------------------------- /lib/utils/output.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var log = require('npmlog') 3 | // output to stdout in a progress bar compatible way 4 | module.exports = function () { 5 | log.clearProgress() 6 | console.log.apply(console, arguments) 7 | log.showProgress() 8 | } 9 | -------------------------------------------------------------------------------- /lib/install/and-ignore-errors.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function (cb) { 4 | return function () { 5 | var args = Array.prototype.slice.call(arguments, 1) 6 | if (args.length) args.unshift(null) 7 | return cb.apply(null, args) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/install/action/global-link.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var npm = require('../../npm.js') 3 | var packageId = require('../../utils/package-id.js') 4 | 5 | module.exports = function (staging, pkg, log, next) { 6 | log.silly('global-link', packageId(pkg)) 7 | npm.link(pkg.package.name, next) 8 | } 9 | -------------------------------------------------------------------------------- /lib/get.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = get 3 | 4 | get.usage = 'npm get (See `npm config`)' 5 | 6 | var npm = require('./npm.js') 7 | 8 | get.completion = npm.commands.config.completion 9 | 10 | function get (args, cb) { 11 | npm.commands.config(['get'].concat(args), cb) 12 | } 13 | -------------------------------------------------------------------------------- /lib/install/module-staging-path.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var uniqueFilename = require('unique-filename') 3 | var moduleName = require('../utils/module-name.js') 4 | 5 | module.exports = moduleStagingPath 6 | function moduleStagingPath (staging, pkg) { 7 | return uniqueFilename(staging, moduleName(pkg), pkg.realpath) 8 | } 9 | -------------------------------------------------------------------------------- /lib/install/action/install.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var lifecycle = require('../../utils/lifecycle.js') 3 | var packageId = require('../../utils/package-id.js') 4 | 5 | module.exports = function (staging, pkg, log, next) { 6 | log.silly('install', packageId(pkg)) 7 | lifecycle(pkg.package, 'install', pkg.path, false, false, next) 8 | } 9 | -------------------------------------------------------------------------------- /lib/install/action/postinstall.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var lifecycle = require('../../utils/lifecycle.js') 3 | var packageId = require('../../utils/package-id.js') 4 | 5 | module.exports = function (staging, pkg, log, next) { 6 | log.silly('postinstall', packageId(pkg)) 7 | lifecycle(pkg.package, 'postinstall', pkg.path, false, false, next) 8 | } 9 | -------------------------------------------------------------------------------- /lib/install/action/preinstall.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var lifecycle = require('../../utils/lifecycle.js') 3 | var packageId = require('../../utils/package-id.js') 4 | 5 | module.exports = function (staging, pkg, log, next) { 6 | log.silly('preinstall', packageId(pkg)) 7 | lifecycle(pkg.package, 'preinstall', pkg.path, false, false, next) 8 | } 9 | -------------------------------------------------------------------------------- /lib/set.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = set 3 | 4 | set.usage = 'npm set (See `npm config`)' 5 | 6 | var npm = require('./npm.js') 7 | 8 | set.completion = npm.commands.config.completion 9 | 10 | function set (args, cb) { 11 | if (!args.length) return cb(set.usage) 12 | npm.commands.config(['set'].concat(args), cb) 13 | } 14 | -------------------------------------------------------------------------------- /doc/cli/npm-ping.md: -------------------------------------------------------------------------------- 1 | npm-ping(1) -- Ping npm registry 2 | ================================ 3 | 4 | ## SYNOPSIS 5 | 6 | npm ping [--registry ] 7 | 8 | ## DESCRIPTION 9 | 10 | Ping the configured or given npm registry and verify authentication. 11 | 12 | ## SEE ALSO 13 | 14 | * npm-config(1) 15 | * npm-config(7) 16 | * npmrc(5) 17 | -------------------------------------------------------------------------------- /html/dochead.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | @NAME@ 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /lib/utils/child-path.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var validate = require('aproba') 4 | var moduleName = require('../utils/module-name.js') 5 | 6 | module.exports = childPath 7 | function childPath (parentPath, child) { 8 | validate('SO', arguments) 9 | return path.join(parentPath, 'node_modules', moduleName(child)) 10 | } 11 | -------------------------------------------------------------------------------- /doc/cli/npm-whoami.md: -------------------------------------------------------------------------------- 1 | npm-whoami(1) -- Display npm username 2 | ===================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm whoami [--registry ] 7 | 8 | ## DESCRIPTION 9 | 10 | Print the `username` config to standard output. 11 | 12 | ## SEE ALSO 13 | 14 | * npm-config(1) 15 | * npm-config(7) 16 | * npmrc(5) 17 | * npm-adduser(1) 18 | -------------------------------------------------------------------------------- /doc/cli/npm-stop.md: -------------------------------------------------------------------------------- 1 | npm-stop(1) -- Stop a package 2 | ============================= 3 | 4 | ## SYNOPSIS 5 | 6 | npm stop [-- ] 7 | 8 | ## DESCRIPTION 9 | 10 | This runs a package's "stop" script, if one was provided. 11 | 12 | ## SEE ALSO 13 | 14 | * npm-run-script(1) 15 | * npm-scripts(7) 16 | * npm-test(1) 17 | * npm-start(1) 18 | * npm-restart(1) 19 | -------------------------------------------------------------------------------- /doc/cli/npm-root.md: -------------------------------------------------------------------------------- 1 | npm-root(1) -- Display npm root 2 | =============================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm root [-g] 7 | 8 | ## DESCRIPTION 9 | 10 | Print the effective `node_modules` folder to standard out. 11 | 12 | ## SEE ALSO 13 | 14 | * npm-prefix(1) 15 | * npm-bin(1) 16 | * npm-folders(5) 17 | * npm-config(1) 18 | * npm-config(7) 19 | * npmrc(5) 20 | -------------------------------------------------------------------------------- /lib/doctor/get-git-path.js: -------------------------------------------------------------------------------- 1 | var log = require('npmlog') 2 | var which = require('which') 3 | 4 | function getGitPath (cb) { 5 | var tracker = log.newItem('getGitPath', 1) 6 | tracker.info('getGitPath', 'Finding git in your PATH') 7 | which('git', function (err, path) { 8 | tracker.finish() 9 | cb(err, path) 10 | }) 11 | } 12 | 13 | module.exports = getGitPath 14 | -------------------------------------------------------------------------------- /lib/doctor/check-ping.js: -------------------------------------------------------------------------------- 1 | var log = require('npmlog') 2 | var ping = require('../ping.js') 3 | 4 | function checkPing (cb) { 5 | var tracker = log.newItem('checkPing', 1) 6 | tracker.info('checkPing', 'Pinging registry') 7 | ping({}, true, (_err, pong, data, res) => { 8 | cb(null, [res.statusCode, res.statusMessage]) 9 | }) 10 | } 11 | 12 | module.exports = checkPing 13 | -------------------------------------------------------------------------------- /doc/cli/npm-bin.md: -------------------------------------------------------------------------------- 1 | npm-bin(1) -- Display npm bin folder 2 | ==================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm bin [-g|--global] 7 | 8 | ## DESCRIPTION 9 | 10 | Print the folder where npm will install executables. 11 | 12 | ## SEE ALSO 13 | 14 | * npm-prefix(1) 15 | * npm-root(1) 16 | * npm-folders(5) 17 | * npm-config(1) 18 | * npm-config(7) 19 | * npmrc(5) 20 | -------------------------------------------------------------------------------- /lib/root.js: -------------------------------------------------------------------------------- 1 | module.exports = root 2 | 3 | var npm = require('./npm.js') 4 | var output = require('./utils/output.js') 5 | 6 | root.usage = 'npm root [-g]' 7 | 8 | function root (args, silent, cb) { 9 | if (typeof cb !== 'function') { 10 | cb = silent 11 | silent = false 12 | } 13 | if (!silent) output(npm.dir) 14 | process.nextTick(cb.bind(this, null, npm.dir)) 15 | } 16 | -------------------------------------------------------------------------------- /doc/cli/npm-test.md: -------------------------------------------------------------------------------- 1 | npm-test(1) -- Test a package 2 | ============================= 3 | 4 | ## SYNOPSIS 5 | 6 | npm test [-- ] 7 | 8 | aliases: t, tst 9 | 10 | ## DESCRIPTION 11 | 12 | This runs a package's "test" script, if one was provided. 13 | 14 | ## SEE ALSO 15 | 16 | * npm-run-script(1) 17 | * npm-scripts(7) 18 | * npm-start(1) 19 | * npm-restart(1) 20 | * npm-stop(1) 21 | -------------------------------------------------------------------------------- /lib/prefix.js: -------------------------------------------------------------------------------- 1 | module.exports = prefix 2 | 3 | var npm = require('./npm.js') 4 | var output = require('./utils/output.js') 5 | 6 | prefix.usage = 'npm prefix [-g]' 7 | 8 | function prefix (args, silent, cb) { 9 | if (typeof cb !== 'function') { 10 | cb = silent 11 | silent = false 12 | } 13 | if (!silent) output(npm.prefix) 14 | process.nextTick(cb.bind(this, null, npm.prefix)) 15 | } 16 | -------------------------------------------------------------------------------- /lib/utils/read-local-package.js: -------------------------------------------------------------------------------- 1 | exports = module.exports = readLocalPkg 2 | 3 | var npm = require('../npm.js') 4 | var readJson = require('read-package-json') 5 | 6 | function readLocalPkg (cb) { 7 | if (npm.config.get('global')) return cb() 8 | var path = require('path') 9 | readJson(path.resolve(npm.prefix, 'package.json'), function (er, d) { 10 | return cb(er, d && d.name) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /doc/cli/npm-bundle.md: -------------------------------------------------------------------------------- 1 | npm-bundle(1) -- REMOVED 2 | ======================== 3 | 4 | ## DESCRIPTION 5 | 6 | The `npm bundle` command has been removed in 1.0, for the simple reason 7 | that it is no longer necessary, as the default behavior is now to 8 | install packages into the local space. 9 | 10 | Just use `npm install` now to do what `npm bundle` used to do. 11 | 12 | ## SEE ALSO 13 | 14 | * npm-install(1) 15 | -------------------------------------------------------------------------------- /lib/install/and-add-parent-to-errors.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var validate = require('aproba') 3 | 4 | module.exports = function (parent, cb) { 5 | validate('F', [cb]) 6 | return function (er) { 7 | if (!er) return cb.apply(null, arguments) 8 | if (er instanceof Error && parent && parent.package && parent.package.name) { 9 | er.parent = parent.package.name 10 | } 11 | cb(er) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/utils/umask.js: -------------------------------------------------------------------------------- 1 | var umask = require('umask') 2 | var npmlog = require('npmlog') 3 | var _fromString = umask.fromString 4 | 5 | module.exports = umask 6 | 7 | // fromString with logging callback 8 | umask.fromString = function (val) { 9 | _fromString(val, function (err, result) { 10 | if (err) { 11 | npmlog.warn('invalid umask', err.message) 12 | } 13 | val = result 14 | }) 15 | 16 | return val 17 | } 18 | -------------------------------------------------------------------------------- /lib/utils/save-stack.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var inherits = require('inherits') 3 | 4 | module.exports = SaveStack 5 | 6 | function SaveStack (fn) { 7 | Error.call(this) 8 | Error.captureStackTrace(this, fn || SaveStack) 9 | } 10 | inherits(SaveStack, Error) 11 | 12 | SaveStack.prototype.completeWith = function (er) { 13 | this['__' + 'proto' + '__'] = er 14 | this.stack = this.stack + '\n\n' + er.stack 15 | return this 16 | } 17 | -------------------------------------------------------------------------------- /test/tap/ls-no-results.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var spawn = require('child_process').spawn 3 | var node = process.execPath 4 | var npm = require.resolve('../../') 5 | var args = [ npm, 'ls', 'ceci n’est pas une package' ] 6 | test('ls exits non-zero when nothing found', function (t) { 7 | var child = spawn(node, args) 8 | child.on('exit', function (code) { 9 | t.notEqual(code, 0) 10 | t.end() 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /scripts/gen-changelog: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Usage: gen-changelog [comittish] 3 | # Reads all the commits since comittish and produces changelog entries in 4 | # our style as best as it can, appendning them to CHANGELOG.md. If it 5 | # encounters a git error it won't modify CHANGELOG.md 6 | # @iarna uses this as the first step in producing changelogs for a release. 7 | (node $(npm prefix)/scripts/changelog.js "$@"; cat CHANGELOG.md) > new.md && mv new.md CHANGELOG.md 8 | -------------------------------------------------------------------------------- /lib/install/and-finish-tracker.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var validate = require('aproba') 3 | 4 | module.exports = function (tracker, cb) { 5 | validate('OF', [tracker, cb]) 6 | return function () { 7 | tracker.finish() 8 | cb.apply(null, arguments) 9 | } 10 | } 11 | 12 | module.exports.now = function (tracker, cb) { 13 | validate('OF', [tracker, cb]) 14 | tracker.finish() 15 | cb.apply(null, Array.prototype.slice.call(arguments, 2)) 16 | } 17 | -------------------------------------------------------------------------------- /test/tap/config-malformed.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | 3 | var npmconf = require('../../lib/config/core.js') 4 | var common = require('./00-config-setup.js') 5 | 6 | test('with malformed', function (t) { 7 | npmconf.load({}, common.malformed, function (er, conf) { 8 | t.ok(er, 'Expected parse error') 9 | if (!(er && /Failed parsing JSON config key email/.test(er.message))) { 10 | throw er 11 | } 12 | t.end() 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /lib/install/action/fetch.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const packageId = require('../../utils/package-id.js') 4 | const pacote = require('pacote') 5 | const pacoteOpts = require('../../config/pacote') 6 | 7 | module.exports = fetch 8 | function fetch (staging, pkg, log, next) { 9 | log.silly('fetch', packageId(pkg)) 10 | const opts = pacoteOpts({integrity: pkg.package._integrity}) 11 | pacote.prefetch(pkg.package._requested, opts).then(() => next(), next) 12 | } 13 | -------------------------------------------------------------------------------- /lib/config/load-uid.js: -------------------------------------------------------------------------------- 1 | module.exports = loadUid 2 | 3 | var getUid = require('uid-number') 4 | 5 | // Call in the context of a npmconf object 6 | 7 | function loadUid (cb) { 8 | // if we're not in unsafe-perm mode, then figure out who 9 | // to run stuff as. Do this first, to support `npm update npm -g` 10 | if (!this.get('unsafe-perm')) { 11 | getUid(this.get('user'), this.get('group'), cb) 12 | } else { 13 | process.nextTick(cb) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/tap/00-verify-bundle-deps.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | 3 | var manifest = require('../../package.json') 4 | var deps = Object.keys(manifest.dependencies) 5 | var bundled = manifest.bundleDependencies 6 | 7 | test('all deps are bundled deps or dev deps', function (t) { 8 | deps.forEach(function (name) { 9 | t.assert( 10 | bundled.indexOf(name) !== -1, 11 | name + ' is in bundledDependencies' 12 | ) 13 | }) 14 | 15 | t.end() 16 | }) 17 | -------------------------------------------------------------------------------- /lib/utils/package-id.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var moduleName = require('./module-name.js') 3 | 4 | module.exports = function (tree) { 5 | var pkg = tree.package || tree 6 | // FIXME: Excluding the '@' here is cleaning up after the mess that 7 | // read-package-json makes. =( 8 | if (pkg._id && pkg._id !== '@') return pkg._id 9 | var name = moduleName(tree) 10 | if (pkg.version) { 11 | return name + '@' + pkg.version 12 | } else { 13 | return name 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/test.js: -------------------------------------------------------------------------------- 1 | module.exports = test 2 | 3 | const testCmd = require('./utils/lifecycle.js').cmd('test') 4 | const usage = require('./utils/usage') 5 | 6 | test.usage = usage( 7 | 'test', 8 | 'npm test [-- ]' 9 | ) 10 | 11 | function test (args, cb) { 12 | testCmd(args, function (er) { 13 | if (!er) return cb() 14 | if (er.code === 'ELIFECYCLE') { 15 | return cb('Test failed. See above for more details.') 16 | } 17 | return cb(er) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /doc/cli/npm-rebuild.md: -------------------------------------------------------------------------------- 1 | npm-rebuild(1) -- Rebuild a package 2 | =================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm rebuild [[<@scope>/]...] 7 | 8 | alias: npm rb 9 | 10 | ## DESCRIPTION 11 | 12 | This command runs the `npm build` command on the matched folders. This is useful 13 | when you install a new version of node, and must recompile all your C++ addons with 14 | the new binary. 15 | 16 | ## SEE ALSO 17 | 18 | * npm-build(1) 19 | * npm-install(1) 20 | -------------------------------------------------------------------------------- /lib/install/action/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var chain = require('slide').chain 3 | var build = require('../../build.js') 4 | var npm = require('../../npm.js') 5 | var packageId = require('../../utils/package-id.js') 6 | 7 | module.exports = function (staging, pkg, log, next) { 8 | log.silly('build', packageId(pkg)) 9 | chain([ 10 | [build.linkStuff, pkg.package, pkg.path, npm.config.get('global'), true], 11 | [build.writeBuiltinConf, pkg.package, pkg.path] 12 | ], next) 13 | } 14 | -------------------------------------------------------------------------------- /test/tap/semver-doc.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | 3 | test('semver doc is up to date', function (t) { 4 | var path = require('path') 5 | var moddoc = path.join(__dirname, '../../node_modules/semver/README.md') 6 | var mydoc = path.join(__dirname, '../../doc/misc/semver.md') 7 | var fs = require('fs') 8 | var mod = fs.readFileSync(moddoc, 'utf8').replace(/semver\(1\)/, 'semver(7)') 9 | var my = fs.readFileSync(mydoc, 'utf8') 10 | t.equal(my, mod) 11 | t.end() 12 | }) 13 | -------------------------------------------------------------------------------- /lib/install/get-requested.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const npa = require('npm-package-arg') 3 | const moduleName = require('../utils/module-name.js') 4 | 5 | module.exports = function (child) { 6 | if (!child.requiredBy.length) return 7 | const reqBy = child.requiredBy[0] 8 | const deps = reqBy.package.dependencies || {} 9 | const devDeps = reqBy.package.devDependencies || {} 10 | const name = moduleName(child) 11 | return npa.resolve(name, deps[name] || devDeps[name], reqBy.realpath) 12 | } 13 | -------------------------------------------------------------------------------- /lib/utils/deep-sort-object.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var sortedObject = require('sorted-object') 3 | 4 | module.exports = function deepSortObject (obj, sortBy) { 5 | if (obj == null || typeof obj !== 'object') return obj 6 | if (obj instanceof Array) { 7 | return obj.map(function (x) { 8 | return deepSortObject(x, sortBy) 9 | }) 10 | } 11 | obj = sortedObject(obj) 12 | Object.keys(obj).forEach(function (key) { 13 | obj[key] = deepSortObject(obj[key], sortBy) 14 | }) 15 | return obj 16 | } 17 | -------------------------------------------------------------------------------- /lib/config/clear-credentials-by-uri.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | 3 | var toNerfDart = require('./nerf-dart.js') 4 | 5 | module.exports = clearCredentialsByURI 6 | 7 | function clearCredentialsByURI (uri) { 8 | assert(uri && typeof uri === 'string', 'registry URL is required') 9 | 10 | var nerfed = toNerfDart(uri) 11 | 12 | this.del(nerfed + ':_authToken', 'user') 13 | this.del(nerfed + ':_password', 'user') 14 | this.del(nerfed + ':username', 'user') 15 | this.del(nerfed + ':email', 'user') 16 | } 17 | -------------------------------------------------------------------------------- /lib/utils/move.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = wrappedMove 3 | 4 | var fs = require('graceful-fs') 5 | var move = require('move-concurrently') 6 | var Bluebird = require('bluebird') 7 | 8 | function wrappedMove (from, to, cb) { 9 | var movePromise = move(from, to, {fs: fs, Promise: Bluebird, maxConcurrency: 4}) 10 | if (cb) { 11 | return movePromise.then(function (value) { 12 | cb(value) 13 | }, function (err) { 14 | cb(err) 15 | }) 16 | } else { 17 | return movePromise 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/doctor/get-latest-npm-version.js: -------------------------------------------------------------------------------- 1 | var log = require('npmlog') 2 | var fetchPackageMetadata = require('../fetch-package-metadata') 3 | 4 | function getLatestNpmVersion (cb) { 5 | var tracker = log.newItem('getLatestNpmVersion', 1) 6 | tracker.info('getLatestNpmVersion', 'Getting npm package information') 7 | fetchPackageMetadata('npm@latest', '.', {}, function (err, d) { 8 | tracker.finish() 9 | if (err) { return cb(err) } 10 | cb(null, d.version) 11 | }) 12 | } 13 | 14 | module.exports = getLatestNpmVersion 15 | -------------------------------------------------------------------------------- /test/tap/unit-child-path.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var childPath = require('../../lib/utils/child-path.js') 4 | var path = require('path') 5 | 6 | test('childPath', function (t) { 7 | t.is( 8 | path.resolve(childPath('/path/to', {name: 'abc'})), 9 | path.resolve('/path/to/node_modules/abc'), 10 | 'basic use') 11 | t.is( 12 | path.resolve(childPath('/path/to', {package: {name: '@zed/abc'}})), 13 | path.resolve('/path/to/node_modules/@zed/abc'), 14 | 'scoped use') 15 | t.end() 16 | }) 17 | -------------------------------------------------------------------------------- /lib/utils/pulse-till-done.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var validate = require('aproba') 3 | var log = require('npmlog') 4 | 5 | var pulsers = 0 6 | var pulse 7 | 8 | module.exports = function (prefix, cb) { 9 | validate('SF', [prefix, cb]) 10 | if (!prefix) prefix = 'network' 11 | if (!pulsers++) { 12 | pulse = setInterval(function () { 13 | log.gauge.pulse(prefix) 14 | }, 250) 15 | } 16 | return function () { 17 | if (!--pulsers) { 18 | clearInterval(pulse) 19 | } 20 | cb.apply(null, arguments) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /doc/cli/npm-stars.md: -------------------------------------------------------------------------------- 1 | npm-stars(1) -- View packages marked as favorites 2 | ================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | npm stars [] 7 | 8 | ## DESCRIPTION 9 | 10 | If you have starred a lot of neat things and want to find them again 11 | quickly this command lets you do just that. 12 | 13 | You may also want to see your friend's favorite packages, in this case 14 | you will most certainly enjoy this command. 15 | 16 | ## SEE ALSO 17 | 18 | * npm-star(1) 19 | * npm-view(1) 20 | * npm-whoami(1) 21 | * npm-adduser(1) 22 | -------------------------------------------------------------------------------- /bin/npm.cmd: -------------------------------------------------------------------------------- 1 | :: Created by npm, please don't edit manually. 2 | @ECHO OFF 3 | 4 | SETLOCAL 5 | 6 | SET "NODE_EXE=%~dp0\node.exe" 7 | IF NOT EXIST "%NODE_EXE%" ( 8 | SET "NODE_EXE=node" 9 | ) 10 | 11 | SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" 12 | FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( 13 | SET "NPM_PREFIX_NPM_CLI_JS=%%F\node_modules\npm\bin\npm-cli.js" 14 | ) 15 | IF EXIST "%NPM_PREFIX_NPM_CLI_JS%" ( 16 | SET "NPM_CLI_JS=%NPM_PREFIX_NPM_CLI_JS%" 17 | ) 18 | 19 | "%NODE_EXE%" "%NPM_CLI_JS%" %* 20 | -------------------------------------------------------------------------------- /doc/cli/npm-star.md: -------------------------------------------------------------------------------- 1 | npm-star(1) -- Mark your favorite packages 2 | ========================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm star [...] 7 | npm unstar [...] 8 | 9 | ## DESCRIPTION 10 | 11 | "Starring" a package means that you have some interest in it. It's 12 | a vaguely positive way to show that you care. 13 | 14 | "Unstarring" is the same thing, but in reverse. 15 | 16 | It's a boolean thing. Starring repeatedly has no additional effect. 17 | 18 | ## SEE ALSO 19 | 20 | * npm-view(1) 21 | * npm-whoami(1) 22 | * npm-adduser(1) 23 | -------------------------------------------------------------------------------- /lib/utils/depr-check.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const log = require('npmlog') 4 | 5 | const deprecated = {} 6 | const deprWarned = {} 7 | 8 | module.exports = deprCheck 9 | function deprCheck (data) { 10 | if (deprecated[data._id]) { 11 | data.deprecated = deprecated[data._id] 12 | } 13 | 14 | if (data.deprecated) { 15 | deprecated[data._id] = data.deprecated 16 | if (!deprWarned[data._id]) { 17 | deprWarned[data._id] = true 18 | log.warn('deprecated', '%s: %s', data._id, data.deprecated) 19 | } 20 | } 21 | 22 | return data 23 | } 24 | -------------------------------------------------------------------------------- /doc/cli/npm-prefix.md: -------------------------------------------------------------------------------- 1 | npm-prefix(1) -- Display prefix 2 | =============================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm prefix [-g] 7 | 8 | ## DESCRIPTION 9 | 10 | Print the local prefix to standard out. This is the closest parent directory 11 | to contain a package.json file unless `-g` is also specified. 12 | 13 | If `-g` is specified, this will be the value of the global prefix. See 14 | `npm-config(7)` for more detail. 15 | 16 | ## SEE ALSO 17 | 18 | * npm-root(1) 19 | * npm-bin(1) 20 | * npm-folders(5) 21 | * npm-config(1) 22 | * npm-config(7) 23 | * npmrc(5) 24 | -------------------------------------------------------------------------------- /lib/config/nerf-dart.js: -------------------------------------------------------------------------------- 1 | var url = require('url') 2 | 3 | module.exports = toNerfDart 4 | 5 | /** 6 | * Maps a URL to an identifier. 7 | * 8 | * Name courtesy schiffertronix media LLC, a New Jersey corporation 9 | * 10 | * @param {String} uri The URL to be nerfed. 11 | * 12 | * @returns {String} A nerfed URL. 13 | */ 14 | function toNerfDart (uri) { 15 | var parsed = url.parse(uri) 16 | delete parsed.protocol 17 | delete parsed.auth 18 | delete parsed.query 19 | delete parsed.search 20 | delete parsed.hash 21 | 22 | return url.resolve(url.format(parsed), '.') 23 | } 24 | -------------------------------------------------------------------------------- /test/tap/00-check-mock-dep.js: -------------------------------------------------------------------------------- 1 | console.log('TAP Version 13') 2 | 3 | process.on('uncaughtException', function (er) { 4 | if (er) { throw er } 5 | console.log('not ok - Failed checking mock registry dep. Expect much fail!') 6 | console.log('1..1') 7 | process.exit(1) 8 | }) 9 | 10 | var assert = require('assert') 11 | var semver = require('semver') 12 | var mock = require('npm-registry-mock/package.json').version 13 | var req = require('../../package.json').devDependencies['npm-registry-mock'] 14 | 15 | assert(semver.satisfies(mock, req)) 16 | console.log('ok') 17 | console.log('1..1') 18 | -------------------------------------------------------------------------------- /doc/cli/npm-build.md: -------------------------------------------------------------------------------- 1 | npm-build(1) -- Build a package 2 | =============================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm build [] 7 | 8 | * ``: 9 | A folder containing a `package.json` file in its root. 10 | 11 | ## DESCRIPTION 12 | 13 | This is the plumbing command called by `npm link` and `npm install`. 14 | 15 | It should generally be called during installation, but if you need to run it 16 | directly, run: 17 | 18 | npm run-script build 19 | 20 | ## SEE ALSO 21 | 22 | * npm-install(1) 23 | * npm-link(1) 24 | * npm-scripts(7) 25 | * package.json(5) 26 | -------------------------------------------------------------------------------- /test/tap/outdated-bad-read-tree.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var requireInject = require('require-inject') 4 | var npm = require('../../lib/npm.js') 5 | 6 | test('setup', function (t) { 7 | npm.load({progress: false}, t.end) 8 | }) 9 | 10 | test('outdated', function (t) { 11 | var rptError = new Error('read-package-tree') 12 | var outdated = requireInject('../../lib/outdated.js', { 13 | 'read-package-tree': function (dir, cb) { 14 | cb(rptError) 15 | } 16 | }) 17 | outdated([], function (err) { 18 | t.is(err, rptError) 19 | t.end() 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /lib/substack.js: -------------------------------------------------------------------------------- 1 | module.exports = substack 2 | var npm = require('./npm.js') 3 | var output = require('./utils/output.js') 4 | 5 | var isms = [ 6 | '\u001b[32mbeep \u001b[35mboop\u001b[m', 7 | 'Replace your configs with services', 8 | 'SEPARATE ALL THE CONCERNS!', 9 | 'MODULE ALL THE THINGS!', 10 | '\\o/', 11 | 'but first, burritos', 12 | 'full time mad scientist here', 13 | 'c/,,\\' 14 | ] 15 | 16 | function substack (args, cb) { 17 | var i = Math.floor(Math.random() * isms.length) 18 | output(isms[i]) 19 | var c = args.shift() 20 | if (c) npm.commands[c](args, cb) 21 | else cb() 22 | } 23 | -------------------------------------------------------------------------------- /lib/bin.js: -------------------------------------------------------------------------------- 1 | module.exports = bin 2 | 3 | var npm = require('./npm.js') 4 | var osenv = require('osenv') 5 | var output = require('./utils/output.js') 6 | 7 | bin.usage = 'npm bin [--global]' 8 | 9 | function bin (args, silent, cb) { 10 | if (typeof cb !== 'function') { 11 | cb = silent 12 | silent = false 13 | } 14 | var b = npm.bin 15 | var PATH = osenv.path() 16 | 17 | if (!silent) output(b) 18 | process.nextTick(cb.bind(this, null, b)) 19 | 20 | if (npm.config.get('global') && PATH.indexOf(b) === -1) { 21 | npm.config.get('logstream').write('(not in PATH env variable)\n') 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bin/read-package-json.js: -------------------------------------------------------------------------------- 1 | var argv = process.argv 2 | if (argv.length < 3) { 3 | console.error('Usage: read-package.json [ ...]') 4 | process.exit(1) 5 | } 6 | 7 | var file = argv[2] 8 | var readJson = require('read-package-json') 9 | 10 | readJson(file, function (er, data) { 11 | if (er) throw er 12 | if (argv.length === 3) { 13 | console.log(data) 14 | } else { 15 | argv.slice(3).forEach(function (field) { 16 | field = field.split('.') 17 | var val = data 18 | field.forEach(function (f) { 19 | val = val[f] 20 | }) 21 | console.log(val) 22 | }) 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /lib/install-test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // npm install-test 4 | // Runs `npm install` and then runs `npm test` 5 | 6 | module.exports = installTest 7 | var install = require('./install.js') 8 | var test = require('./test.js') 9 | var usage = require('./utils/usage') 10 | 11 | installTest.usage = usage( 12 | 'install-test', 13 | '\nnpm install-test [args]' + 14 | '\nSame args as `npm install`' 15 | ) 16 | 17 | installTest.completion = install.completion 18 | 19 | function installTest (args, cb) { 20 | install(args, function (er) { 21 | if (er) { 22 | return cb(er) 23 | } 24 | test([], cb) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /test/tap/config-certfile.js: -------------------------------------------------------------------------------- 1 | require('./00-config-setup.js') 2 | 3 | var path = require('path') 4 | var fs = require('fs') 5 | var test = require('tap').test 6 | var npmconf = require('../../lib/config/core.js') 7 | 8 | test('cafile loads as ca', function (t) { 9 | var cafile = path.join(__dirname, '..', 'fixtures', 'config', 'multi-ca') 10 | 11 | npmconf.load({cafile: cafile}, function (er, conf) { 12 | if (er) throw er 13 | 14 | t.same(conf.get('cafile'), cafile) 15 | var ca = fs.readFileSync(cafile, 'utf8').trim() 16 | t.same(conf.get('ca').join(ca.match(/\r/g) ? '\r\n' : '\n'), ca) 17 | t.end() 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /lib/utils/gunzip-maybe.js: -------------------------------------------------------------------------------- 1 | var duplex = require('mississippi').duplex 2 | var through = require('mississippi').through 3 | var zlib = require('zlib') 4 | 5 | function hasGzipHeader (c) { 6 | return c[0] === 0x1F && c[1] === 0x8B && c[2] === 0x08 7 | } 8 | 9 | module.exports = gunzip 10 | function gunzip () { 11 | var stream = duplex() 12 | var peeker = through(function (chunk, enc, cb) { 13 | var newStream = hasGzipHeader(chunk) 14 | ? zlib.createGunzip() 15 | : through() 16 | stream.setReadable(newStream) 17 | stream.setWritable(newStream) 18 | stream.write(chunk) 19 | }) 20 | stream.setWritable(peeker) 21 | return stream 22 | } 23 | -------------------------------------------------------------------------------- /test/tap/normalize-package-explode.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var log = require('npmlog') 4 | var npm = require('../../lib/npm.js') 5 | 6 | var idealTree = { 7 | package: { 8 | name: 'a b c', 9 | version: '3.what' 10 | }, 11 | children: [], 12 | warnings: [] 13 | } 14 | 15 | test('setup', function (t) { 16 | npm.load({}, t.end) 17 | }) 18 | 19 | test('validate-tree', function (t) { 20 | log.disableProgress() 21 | var validateTree = require('../../lib/install/validate-tree.js') 22 | validateTree(idealTree, log.newGroup('validate'), function (er) { 23 | t.pass("we didn't crash") 24 | t.end() 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set configurations that will be "sticky" on this system, 4 | # surviving npm self-updates. 5 | 6 | CONFIGS=() 7 | i=0 8 | 9 | # get the location of this file. 10 | unset CDPATH 11 | CONFFILE=$(cd $(dirname "$0"); pwd -P)/npmrc 12 | 13 | while [ $# -gt 0 ]; do 14 | conf="$1" 15 | case $conf in 16 | --help) 17 | echo "./configure --param=value ..." 18 | exit 0 19 | ;; 20 | --*) 21 | CONFIGS[$i]="${conf:2}" 22 | ;; 23 | *) 24 | CONFIGS[$i]="$conf" 25 | ;; 26 | esac 27 | let i++ 28 | shift 29 | done 30 | 31 | for c in "${CONFIGS[@]}"; do 32 | echo "$c" >> "$CONFFILE" 33 | done 34 | -------------------------------------------------------------------------------- /lib/ping.js: -------------------------------------------------------------------------------- 1 | var npm = require('./npm.js') 2 | var output = require('./utils/output.js') 3 | 4 | module.exports = ping 5 | 6 | ping.usage = 'npm ping\nping registry' 7 | 8 | function ping (args, silent, cb) { 9 | if (typeof cb !== 'function') { 10 | cb = silent 11 | silent = false 12 | } 13 | var registry = npm.config.get('registry') 14 | if (!registry) return cb(new Error('no default registry set')) 15 | var auth = npm.config.getCredentialsByURI(registry) 16 | 17 | npm.registry.ping(registry, {auth: auth}, function (er, pong, data, res) { 18 | if (!silent) output(JSON.stringify(pong)) 19 | cb(er, er ? null : pong, data, res) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /lib/utils/no-progress-while-running.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var log = require('npmlog') 3 | var progressEnabled 4 | var running = 0 5 | 6 | var startRunning = exports.startRunning = function () { 7 | if (progressEnabled == null) progressEnabled = log.progressEnabled 8 | if (progressEnabled) log.disableProgress() 9 | ++running 10 | } 11 | 12 | var stopRunning = exports.stopRunning = function () { 13 | --running 14 | if (progressEnabled && running === 0) log.enableProgress() 15 | } 16 | 17 | exports.tillDone = function noProgressTillDone (cb) { 18 | startRunning() 19 | return function () { 20 | stopRunning() 21 | cb.apply(this, arguments) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/utils/warn-deprecated.js: -------------------------------------------------------------------------------- 1 | module.exports = warnDeprecated 2 | 3 | var log = require('npmlog') 4 | 5 | var deprecations = {} 6 | 7 | function warnDeprecated (type) { 8 | return function warn (messages, instance) { 9 | if (!instance) { 10 | if (!deprecations[type]) { 11 | deprecations[type] = {} 12 | messages.forEach(function (m) { log.warn(type, m) }) 13 | } 14 | } else { 15 | if (!deprecations[type]) deprecations[type] = {} 16 | 17 | if (!deprecations[type][instance]) { 18 | deprecations[type][instance] = true 19 | messages.forEach(function (m) { log.warn(type, m) }) 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/config/userconfig: -------------------------------------------------------------------------------- 1 | email = i@izs.me 2 | env-thing = ${random_env_var} 3 | init.author.name = Isaac Z. Schlueter 4 | init.author.email = i@izs.me 5 | init.author.url = http://blog.izs.me/ 6 | init.version = 1.2.3 7 | proprietary-attribs = false 8 | npm:publishtest = true 9 | _npmjs.org:couch = https://admin:password@localhost:5984/registry 10 | npm-www:nocache = 1 11 | nodedir = /Users/isaacs/dev/js/node-v0.8 12 | sign-git-tag = true 13 | message = v%s 14 | strict-ssl = false 15 | tmp = ~/.tmp 16 | _auth = dXNlcm5hbWU6cGFzc3dvcmQ= 17 | 18 | [_token] 19 | AuthSession = yabba-dabba-doodle 20 | version = 1 21 | expires = 1345001053415 22 | path = / 23 | httponly = true 24 | -------------------------------------------------------------------------------- /lib/install/realize-shrinkwrap-specifier.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var npa = require('npm-package-arg') 3 | 4 | module.exports = function (name, sw, where) { 5 | try { 6 | if (sw.version && sw.integrity) { 7 | return npa.resolve(name, sw.version, where) 8 | } else if (sw.from) { 9 | const spec = npa(sw.from, where) 10 | if (spec.registry && sw.version) { 11 | return npa.resolve(name, sw.version, where) 12 | } else if (!sw.resolved) { 13 | return spec 14 | } 15 | } 16 | if (sw.resolved) { 17 | return npa.resolve(name, sw.resolved, where) 18 | } 19 | } catch (_) { } 20 | return npa.resolve(name, sw.version, where) 21 | } 22 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .*.swp 3 | npm-debug.log 4 | /test/bin 5 | /test/output.log 6 | /test/packages/*/node_modules 7 | /test/packages/npm-test-depends-on-spark/which-spark.log 8 | /test/packages/test-package/random-data.txt 9 | /test/root 10 | /test/npm_cache 11 | node_modules/marked 12 | node_modules/ronn 13 | node_modules/tap 14 | node_modules/.bin 15 | node_modules/npm-registry-mock 16 | /npmrc 17 | /release/ 18 | 19 | # don't need these in the npm package. 20 | html/*.png 21 | 22 | # don't ignore .npmignore files 23 | # these are used in some tests. 24 | !.npmignore 25 | 26 | /npm-*.tgz 27 | 28 | *.pyc 29 | 30 | /test/tap/builtin-config 31 | 32 | .nyc_output 33 | 34 | npm-shrinkwrap.json -------------------------------------------------------------------------------- /lib/utils/perf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var log = require('npmlog') 3 | var EventEmitter = require('events').EventEmitter 4 | var perf = new EventEmitter() 5 | module.exports = perf 6 | 7 | var timings = {} 8 | 9 | process.on('time', time) 10 | process.on('timeEnd', timeEnd) 11 | 12 | perf.on('time', time) 13 | perf.on('timeEnd', timeEnd) 14 | 15 | function time (name) { 16 | timings[name] = Date.now() 17 | } 18 | 19 | function timeEnd (name) { 20 | if (name in timings) { 21 | process.emit('timing', name, Date.now() - timings[name]) 22 | delete timings[name] 23 | } else { 24 | log.silly('timing', "Tried to end timer that doesn't exist:", name) 25 | return 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /doc/cli/npm-start.md: -------------------------------------------------------------------------------- 1 | npm-start(1) -- Start a package 2 | =============================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm start [-- ] 7 | 8 | ## DESCRIPTION 9 | 10 | This runs an arbitrary command specified in the package's `"start"` property of 11 | its `"scripts"` object. If no `"start"` property is specified on the 12 | `"scripts"` object, it will run `node server.js`. 13 | 14 | As of [`npm@2.0.0`](http://blog.npmjs.org/post/98131109725/npm-2-0-0), you can 15 | use custom arguments when executing scripts. Refer to npm-run-script(1) for 16 | more details. 17 | 18 | ## SEE ALSO 19 | 20 | * npm-run-script(1) 21 | * npm-scripts(7) 22 | * npm-test(1) 23 | * npm-restart(1) 24 | * npm-stop(1) 25 | -------------------------------------------------------------------------------- /lib/install/action/global-install.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var npm = require('../../npm.js') 4 | var Installer = require('../../install.js').Installer 5 | var packageId = require('../../utils/package-id.js') 6 | 7 | module.exports = function (staging, pkg, log, next) { 8 | log.silly('global-install', packageId(pkg)) 9 | var globalRoot = path.resolve(npm.globalDir, '..') 10 | npm.config.set('global', true) 11 | var install = new Installer(globalRoot, false, [pkg.package.name + '@' + pkg.package._requested.fetchSpec]) 12 | install.link = false 13 | install.run(function () { 14 | npm.config.set('global', false) 15 | next.apply(null, arguments) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /lib/utils/usage.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var aliases = require('../config/cmd-list').aliases 3 | 4 | module.exports = function usage (cmd, txt, opt) { 5 | var post = Object.keys(aliases).reduce(function (p, c) { 6 | var val = aliases[c] 7 | if (val !== cmd) return p 8 | return p.concat(c) 9 | }, []) 10 | 11 | if (opt || post.length > 0) txt += '\n\n' 12 | 13 | if (post.length === 1) { 14 | txt += 'alias: ' 15 | txt += post.join(', ') 16 | } else if (post.length > 1) { 17 | txt += 'aliases: ' 18 | txt += post.join(', ') 19 | } 20 | 21 | if (opt) { 22 | if (post.length > 0) txt += '\n' 23 | txt += 'common options: ' + opt 24 | } 25 | 26 | return txt 27 | } 28 | -------------------------------------------------------------------------------- /lib/utils/parse-json.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var parseJSON = module.exports = function (content) { 3 | return JSON.parse(stripBOM(content)) 4 | } 5 | 6 | parseJSON.noExceptions = function (content) { 7 | try { 8 | return parseJSON(content) 9 | } catch (ex) { 10 | return 11 | } 12 | } 13 | 14 | // from read-package-json 15 | function stripBOM (content) { 16 | content = content.toString() 17 | // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) 18 | // because the buffer-to-string conversion in `fs.readFileSync()` 19 | // translates it to FEFF, the UTF-16 BOM. 20 | if (content.charCodeAt(0) === 0xFEFF) { 21 | content = content.slice(1) 22 | } 23 | return content 24 | } 25 | -------------------------------------------------------------------------------- /test/tap/00-verify-ls-ok.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap') 2 | var test = require('tap').test 3 | var path = require('path') 4 | var cwd = path.resolve(__dirname, '..', '..') 5 | var fs = require('fs') 6 | 7 | test('npm ls in npm', function (t) { 8 | t.ok(fs.existsSync(cwd), 'ensure that the path we are calling ls within exists') 9 | var files = fs.readdirSync(cwd) 10 | t.notEqual(files.length, 0, 'ensure there are files in the directory we are to ls') 11 | 12 | var opt = { cwd: cwd, stdio: [ 'ignore', 'ignore', 2 ] } 13 | common.npm(['ls'], opt, function (err, code) { 14 | t.ifError(err, 'error should not exist') 15 | t.equal(code, 0, 'npm ls exited with code') 16 | t.end() 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /lib/install/inflate-bundled.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var childPath = require('../utils/child-path.js') 4 | var reset = require('./node.js').reset 5 | 6 | module.exports = function inflateBundled (bundler, parent, children) { 7 | children.forEach(function (child) { 8 | if (child.fromBundle === bundler) return 9 | reset(child) 10 | child.fromBundle = bundler 11 | child.isInLink = bundler.isLink 12 | child.parent = parent 13 | child.path = childPath(parent.path, child) 14 | child.realpath = bundler.isLink ? child.realpath : childPath(parent.realpath, child) 15 | child.isLink = child.isLink || parent.isLink || parent.target 16 | inflateBundled(bundler, child, child.children) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /lib/install/is-extraneous.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = isExtraneous 3 | 4 | function isExtraneous (tree) { 5 | var result = !isNotExtraneous(tree) 6 | return result 7 | } 8 | 9 | function topHasNoPjson (tree) { 10 | var top = tree 11 | while (!top.isTop) top = top.parent 12 | return top.error 13 | } 14 | 15 | function isNotExtraneous (tree, isCycle) { 16 | if (!isCycle) isCycle = {} 17 | if (tree.isTop || tree.userRequired) { 18 | return true 19 | } else if (isCycle[tree.path]) { 20 | return topHasNoPjson(tree) 21 | } else { 22 | isCycle[tree.path] = true 23 | return tree.requiredBy && tree.requiredBy.some(function (node) { 24 | return isNotExtraneous(node, Object.create(isCycle)) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/tap/bin.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var test = require('tap').test 3 | var rimraf = require('rimraf') 4 | var common = require('../common-tap.js') 5 | var opts = { cwd: __dirname } 6 | var binDir = '../../node_modules/.bin' 7 | var fixture = path.resolve(__dirname, binDir) 8 | 9 | test('setup', function (t) { 10 | rimraf.sync(path.join(__dirname, 'node_modules')) 11 | t.end() 12 | }) 13 | 14 | test('npm bin', function (t) { 15 | common.npm(['bin'], opts, function (err, code, stdout, stderr) { 16 | t.ifError(err, 'bin ran without issue') 17 | t.notOk(stderr, 'should have no stderr') 18 | t.equal(code, 0, 'exit ok') 19 | var res = path.resolve(stdout) 20 | t.equal(res, fixture + '\n') 21 | t.end() 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /test/tap/referer.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | var http = require('http') 4 | 5 | test('should send referer http header', function (t) { 6 | http.createServer(function (q, s) { 7 | t.equal(q.headers.referer, 'install foo') 8 | s.statusCode = 404 9 | s.end(JSON.stringify({error: 'whatever'})) 10 | this.close() 11 | }).listen(common.port, function () { 12 | var reg = 'http://localhost:' + common.port 13 | var args = [ 'install', 'foo', '--registry', reg ] 14 | common.npm(args, {}, function (er, code) { 15 | if (er) { 16 | throw er 17 | } 18 | // should not have ended nicely, since we returned an error 19 | t.ok(code) 20 | t.end() 21 | }) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /doc/cli/npm-repo.md: -------------------------------------------------------------------------------- 1 | npm-repo(1) -- Open package repository page in the browser 2 | ======================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm repo [] 7 | 8 | ## DESCRIPTION 9 | 10 | This command tries to guess at the likely location of a package's 11 | repository URL, and then tries to open it using the `--browser` 12 | config param. If no package name is provided, it will search for 13 | a `package.json` in the current folder and use the `name` property. 14 | 15 | ## CONFIGURATION 16 | 17 | ### browser 18 | 19 | * Default: OS X: `"open"`, Windows: `"start"`, Others: `"xdg-open"` 20 | * Type: String 21 | 22 | The browser that is called by the `npm repo` command to open websites. 23 | 24 | ## SEE ALSO 25 | 26 | * npm-docs(1) 27 | * npm-config(1) 28 | -------------------------------------------------------------------------------- /scripts/relocate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Change the cli shebang to point at the specified node 4 | # Useful for when the program is moved around after install. 5 | # Also used by the default 'make install' in node to point 6 | # npm at the newly installed node, rather than the first one 7 | # in the PATH, which would be the default otherwise. 8 | 9 | # bash /path/to/npm/scripts/relocate.sh $nodepath 10 | # If $nodepath is blank, then it'll use /usr/bin/env 11 | 12 | dir="$(dirname "$(dirname "$0")")" 13 | cli="$dir"/bin/npm-cli.js 14 | tmp="$cli".tmp 15 | 16 | node="$1" 17 | if [ "x$node" = "x" ]; then 18 | node="/usr/bin/env node" 19 | fi 20 | node="#!$node" 21 | 22 | sed -e 1d "$cli" > "$tmp" 23 | echo "$node" > "$cli" 24 | cat "$tmp" >> "$cli" 25 | rm "$tmp" 26 | chmod ogu+x $cli 27 | -------------------------------------------------------------------------------- /lib/utils/completion/file-completion.js: -------------------------------------------------------------------------------- 1 | module.exports = fileCompletion 2 | 3 | var mkdir = require('mkdirp') 4 | var glob = require('glob') 5 | 6 | function fileCompletion (root, req, depth, cb) { 7 | if (typeof cb !== 'function') { 8 | cb = depth 9 | depth = Infinity 10 | } 11 | mkdir(root, function (er) { 12 | if (er) return cb(er) 13 | 14 | // can be either exactly the req, or a descendent 15 | var pattern = root + '/{' + req + ',' + req + '/**/*}' 16 | var opts = { mark: true, dot: true, maxDepth: depth } 17 | glob(pattern, opts, function (er, files) { 18 | if (er) return cb(er) 19 | return cb(null, (files || []).map(function (f) { 20 | return f.substr(root.length + 1).replace(/^\/|\/$/g, '') 21 | })) 22 | }) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /lib/utils/escape-arg.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var isWindowsShell = require('./is-windows-shell.js') 4 | 5 | /* 6 | Escape the name of an executable suitable for passing to the system shell. 7 | 8 | Windows is easy, wrap in double quotes and you're done, as there's no 9 | facility to create files with quotes in their names. 10 | 11 | Unix-likes are a little more complicated, wrap in single quotes and escape 12 | any single quotes in the filename. 13 | */ 14 | 15 | module.exports = escapify 16 | 17 | function escapify (str) { 18 | if (isWindowsShell) { 19 | return '"' + path.normalize(str) + '"' 20 | } else { 21 | if (/[^-_.~/\w]/.test(str)) { 22 | return "'" + str.replace(/'/g, "'\"'\"'") + "'" 23 | } else { 24 | return str 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /doc/cli/npm-shrinkwrap.md: -------------------------------------------------------------------------------- 1 | npm-shrinkwrap(1) -- Lock down dependency versions for publication 2 | ===================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm shrinkwrap 7 | 8 | ## DESCRIPTION 9 | 10 | This command repurposes `package-lock.json` into a publishable 11 | `npm-shrinkwrap.json` or simply creates a new one. The file created and updated 12 | by this command will then take precedence over any other existing or future 13 | `package-lock.json` files. For a detailed explanation of the design and purpose 14 | of package locks in npm, see npm-package-locks(5). 15 | 16 | ## SEE ALSO 17 | 18 | * npm-install(1) 19 | * npm-run-script(1) 20 | * npm-scripts(7) 21 | * package.json(5) 22 | * npm-package-locks(5) 23 | * package-lock.json(5) 24 | * npm-shrinkwrap.json(5) 25 | * npm-ls(1) 26 | -------------------------------------------------------------------------------- /doc/cli/npm-install-test.md: -------------------------------------------------------------------------------- 1 | # npm install-test(1) -- Install package(s) and run tests 2 | 3 | ## SYNOPSIS 4 | 5 | npm install-test (with no args, in package dir) 6 | npm install-test [<@scope>/] 7 | npm install-test [<@scope>/]@ 8 | npm install-test [<@scope>/]@ 9 | npm install-test [<@scope>/]@ 10 | npm install-test 11 | npm install-test 12 | npm install-test 13 | 14 | alias: npm it 15 | common options: [--save|--save-dev|--save-optional] [--save-exact] [--dry-run] 16 | 17 | ## DESCRIPTION 18 | 19 | This command runs an `npm install` followed immediately by an `npm test`. It 20 | takes exactly the same arguments as `npm install`. 21 | 22 | ## SEE ALSO 23 | 24 | - npm-install(1) 25 | - npm-test(1) 26 | -------------------------------------------------------------------------------- /lib/config/load-cafile.js: -------------------------------------------------------------------------------- 1 | module.exports = loadCAFile 2 | 3 | var fs = require('fs') 4 | 5 | function loadCAFile (cafilePath, cb) { 6 | if (!cafilePath) return process.nextTick(cb) 7 | 8 | fs.readFile(cafilePath, 'utf8', afterCARead.bind(this)) 9 | 10 | function afterCARead (er, cadata) { 11 | if (er) { 12 | // previous cafile no longer exists, so just continue on gracefully 13 | if (er.code === 'ENOENT') return cb() 14 | return cb(er) 15 | } 16 | 17 | var delim = '-----END CERTIFICATE-----' 18 | var output 19 | 20 | output = cadata 21 | .split(delim) 22 | .filter(function (xs) { 23 | return !!xs.trim() 24 | }) 25 | .map(function (xs) { 26 | return xs.trimLeft() + delim 27 | }) 28 | 29 | this.set('ca', output) 30 | cb(null) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /doc/cli/npm-deprecate.md: -------------------------------------------------------------------------------- 1 | npm-deprecate(1) -- Deprecate a version of a package 2 | ==================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm deprecate [@] 7 | 8 | ## DESCRIPTION 9 | 10 | This command will update the npm registry entry for a package, providing 11 | a deprecation warning to all who attempt to install it. 12 | 13 | It works on version ranges as well as specific versions, so you can do 14 | something like this: 15 | 16 | npm deprecate my-thing@"< 0.2.3" "critical bug fixed in v0.2.3" 17 | 18 | Note that you must be the package owner to deprecate something. See the 19 | `owner` and `adduser` help topics. 20 | 21 | To un-deprecate a package, specify an empty string (`""`) for the `message` argument. 22 | 23 | ## SEE ALSO 24 | 25 | * npm-publish(1) 26 | * npm-registry(7) 27 | -------------------------------------------------------------------------------- /doc/cli/npm-pack.md: -------------------------------------------------------------------------------- 1 | npm-pack(1) -- Create a tarball from a package 2 | ============================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm pack [[<@scope>/]...] 7 | 8 | ## DESCRIPTION 9 | 10 | For anything that's installable (that is, a package folder, tarball, 11 | tarball url, name@tag, name@version, name, or scoped name), this 12 | command will fetch it to the cache, and then copy the tarball to the 13 | current working directory as `-.tgz`, and then write 14 | the filenames out to stdout. 15 | 16 | If the same package is specified multiple times, then the file will be 17 | overwritten the second time. 18 | 19 | If no arguments are supplied, then npm packs the current package folder. 20 | 21 | ## SEE ALSO 22 | 23 | * npm-cache(1) 24 | * npm-publish(1) 25 | * npm-config(1) 26 | * npm-config(7) 27 | * npmrc(5) 28 | -------------------------------------------------------------------------------- /doc/cli/npm-prune.md: -------------------------------------------------------------------------------- 1 | npm-prune(1) -- Remove extraneous packages 2 | ========================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm prune [[<@scope>/]...] [--production] 7 | 8 | ## DESCRIPTION 9 | 10 | This command removes "extraneous" packages. If a package name is 11 | provided, then only packages matching one of the supplied names are 12 | removed. 13 | 14 | Extraneous packages are packages that are not listed on the parent 15 | package's dependencies list. 16 | 17 | If the `--production` flag is specified or the `NODE_ENV` environment 18 | variable is set to `production`, this command will remove the packages 19 | specified in your `devDependencies`. Setting `--production=false` will 20 | negate `NODE_ENV` being set to `production`. 21 | 22 | ## SEE ALSO 23 | 24 | * npm-uninstall(1) 25 | * npm-folders(5) 26 | * npm-ls(1) 27 | -------------------------------------------------------------------------------- /scripts/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # script for creating a zip and tarball for inclusion in node 4 | 5 | unset CDPATH 6 | 7 | set -e 8 | 9 | rm -rf release *.tgz || true 10 | mkdir release 11 | node ./bin/npm-cli.js pack --loglevel error >/dev/null 12 | mv *.tgz release 13 | cd release 14 | tar xzf *.tgz 15 | 16 | mkdir node_modules 17 | mv package node_modules/npm 18 | 19 | # make the zip for windows users 20 | cp node_modules/npm/bin/*.cmd . 21 | zipname=npm-$(node ../bin/npm-cli.js -v).zip 22 | zip -q -9 -r -X "$zipname" *.cmd node_modules 23 | 24 | # make the tar for node's deps 25 | cd node_modules 26 | tarname=npm-$(node ../../bin/npm-cli.js -v).tgz 27 | tar czf "$tarname" npm 28 | 29 | cd .. 30 | mv "node_modules/$tarname" . 31 | 32 | rm -rf *.cmd 33 | rm -rf node_modules 34 | 35 | echo "release/$tarname" 36 | echo "release/$zipname" 37 | -------------------------------------------------------------------------------- /html/static/toc.js: -------------------------------------------------------------------------------- 1 | ;(function () { 2 | var wrapper = document.getElementById('wrapper') 3 | var els = Array.prototype.slice.call(wrapper.getElementsByTagName('*'), 0) 4 | .filter(function (el) { 5 | return el.parentNode === wrapper && 6 | el.tagName.match(/H[1-6]/) && 7 | el.id 8 | }) 9 | var l = 2 10 | var toc = document.createElement('ul') 11 | toc.innerHTML = els.map(function (el) { 12 | var i = el.tagName.charAt(1) 13 | var out = '' 14 | while (i > l) { 15 | out += '
    ' 16 | l++ 17 | } 18 | while (i < l) { 19 | out += '
' 20 | l-- 21 | } 22 | out += '
  • ' + 23 | (el.innerText || el.text || el.innerHTML) + 24 | '' 25 | return out 26 | }).join('\n') 27 | toc.id = 'toc' 28 | document.body.appendChild(toc) 29 | })() 30 | -------------------------------------------------------------------------------- /lib/install/is-fs-access-available.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var fs = require('fs') 3 | var semver = require('semver') 4 | var isWindows = process.platform === 'win32' 5 | 6 | // fs.access first introduced in node 0.12 / io.js 7 | if (!fs.access) { 8 | module.exports = false 9 | } else if (!isWindows) { 10 | // fs.access always works on non-Windows OSes 11 | module.exports = true 12 | } else { 13 | // The Windows implementation of `fs.access` has a bug where it will 14 | // sometimes return access errors all the time for directories, even 15 | // when access is available. As all we actually test ARE directories, this 16 | // is a bit of a problem. 17 | // This was fixed in io.js version 1.5.0 18 | // As of 2015-07-20, it is still unfixed in node: 19 | // https://github.com/joyent/node/issues/25657 20 | 21 | module.exports = semver.gte(process.version, '1.5.0') 22 | } 23 | -------------------------------------------------------------------------------- /lib/config/set-user.js: -------------------------------------------------------------------------------- 1 | module.exports = setUser 2 | 3 | var assert = require('assert') 4 | var path = require('path') 5 | var fs = require('fs') 6 | var mkdirp = require('mkdirp') 7 | 8 | function setUser (cb) { 9 | var defaultConf = this.root 10 | assert(defaultConf !== Object.prototype) 11 | 12 | // If global, leave it as-is. 13 | // If not global, then set the user to the owner of the prefix folder. 14 | // Just set the default, so it can be overridden. 15 | if (this.get('global')) return cb() 16 | if (process.env.SUDO_UID) { 17 | defaultConf.user = +(process.env.SUDO_UID) 18 | return cb() 19 | } 20 | 21 | var prefix = path.resolve(this.get('prefix')) 22 | mkdirp(prefix, function (er) { 23 | if (er) return cb(er) 24 | fs.stat(prefix, function (er, st) { 25 | defaultConf.user = st && st.uid 26 | return cb(er) 27 | }) 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /lib/doctor/get-latest-nodejs-version.js: -------------------------------------------------------------------------------- 1 | var log = require('npmlog') 2 | var request = require('request') 3 | 4 | function getLatestNodejsVersion (url, cb) { 5 | var tracker = log.newItem('getLatestNodejsVersion', 1) 6 | tracker.info('getLatestNodejsVersion', 'Getting Node.js release information') 7 | var version = '' 8 | url = url || 'https://nodejs.org/dist/index.json' 9 | request(url, function (e, res, index) { 10 | tracker.finish() 11 | if (e) return cb(e) 12 | if (res.statusCode !== 200) { 13 | return cb(new Error('Status not 200, ' + res.statusCode)) 14 | } 15 | try { 16 | JSON.parse(index).forEach(function (item) { 17 | if (item.lts && item.version > version) version = item.version 18 | }) 19 | cb(null, version) 20 | } catch (e) { 21 | cb(e) 22 | } 23 | }) 24 | } 25 | 26 | module.exports = getLatestNodejsVersion 27 | -------------------------------------------------------------------------------- /lib/install/exists.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var fs = require('fs') 3 | var inflight = require('inflight') 4 | var accessError = require('./access-error.js') 5 | var isFsAccessAvailable = require('./is-fs-access-available.js') 6 | 7 | if (isFsAccessAvailable) { 8 | module.exports = fsAccessImplementation 9 | } else { 10 | module.exports = fsStatImplementation 11 | } 12 | 13 | // exposed only for testing purposes 14 | module.exports.fsAccessImplementation = fsAccessImplementation 15 | module.exports.fsStatImplementation = fsStatImplementation 16 | 17 | function fsAccessImplementation (dir, done) { 18 | done = inflight('exists:' + dir, done) 19 | if (!done) return 20 | fs.access(dir, fs.F_OK, done) 21 | } 22 | 23 | function fsStatImplementation (dir, done) { 24 | done = inflight('exists:' + dir, done) 25 | if (!done) return 26 | fs.stat(dir, function (er) { done(accessError(dir, er)) }) 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | npm-debug.log 3 | .nyc_output/ 4 | /test/bin 5 | /test/output.log 6 | /test/*/*/node_modules 7 | /test/packages/npm-test-depends-on-spark/which-spark.log 8 | /test/packages/test-package/random-data.txt 9 | /test/root 10 | /node_modules/.bin 11 | /html/doc/ 12 | /man/ 13 | /doc/*/npm-index.md 14 | /npmrc 15 | /release/ 16 | /npm-*.tgz 17 | /node_modules/npm-registry-client/test/fixtures 18 | /test/fixtures/config/userconfig-with-gc 19 | /node_modules/npm-registry-couchapp 20 | *.pyc 21 | .jshintrc 22 | .eslintrc 23 | .nyc_output 24 | 25 | # dev dependencies 26 | /node_modules/deep-equal/ 27 | /node_modules/marked/ 28 | /node_modules/marked-man/ 29 | /node_modules/nock/ 30 | /node_modules/npm-registry-couchapp/ 31 | /node_modules/npm-registry-mock/ 32 | /node_modules/require-inject/ 33 | /node_modules/sprintf-js/ 34 | /node_modules/standard/ 35 | /node_modules/tap/ 36 | /node_modules/tacks/ 37 | -------------------------------------------------------------------------------- /lib/config/reg-client.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = regClientConfig 4 | function regClientConfig (npm, log, config) { 5 | return { 6 | proxy: { 7 | http: config.get('proxy'), 8 | https: config.get('https-proxy'), 9 | localAddress: config.get('local-address') 10 | }, 11 | ssl: { 12 | certificate: config.get('cert'), 13 | key: config.get('key'), 14 | ca: config.get('ca'), 15 | strict: config.get('strict-ssl') 16 | }, 17 | retry: { 18 | retries: config.get('fetch-retries'), 19 | factor: config.get('fetch-retry-factor'), 20 | minTimeout: config.get('fetch-retry-mintimeout'), 21 | maxTimeout: config.get('fetch-retry-maxtimeout') 22 | }, 23 | userAgent: config.get('user-agent'), 24 | log: log, 25 | defaultTag: config.get('tag'), 26 | maxSockets: config.get('maxsockets'), 27 | scope: npm.projectScope 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/utils/escape-exec-path.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var isWindowsShell = require('./is-windows-shell.js') 4 | 5 | /* 6 | Escape the name of an executable suitable for passing to the system shell. 7 | 8 | Windows is easy, wrap in double quotes and you're done, as there's no 9 | facility to create files with quotes in their names. 10 | 11 | Unix-likes are a little more complicated, wrap in single quotes and escape 12 | any single quotes in the filename. 13 | */ 14 | 15 | module.exports = escapify 16 | 17 | function windowsQuotes (str) { 18 | if (!/ /.test(str)) return str 19 | return '"' + str + '"' 20 | } 21 | 22 | function escapify (str) { 23 | if (isWindowsShell) { 24 | return path.normalize(str).split(/\\/).map(windowsQuotes).join('\\') 25 | } else if (/[^-_.~/\w]/.test(str)) { 26 | return "'" + str.replace(/'/g, "'\"'\"'") + "'" 27 | } else { 28 | return str 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /doc/cli/npm-completion.md: -------------------------------------------------------------------------------- 1 | npm-completion(1) -- Tab Completion for npm 2 | =========================================== 3 | 4 | ## SYNOPSIS 5 | 6 | source <(npm completion) 7 | 8 | ## DESCRIPTION 9 | 10 | Enables tab-completion in all npm commands. 11 | 12 | The synopsis above 13 | loads the completions into your current shell. Adding it to 14 | your ~/.bashrc or ~/.zshrc will make the completions available 15 | everywhere: 16 | 17 | npm completion >> ~/.bashrc 18 | npm completion >> ~/.zshrc 19 | 20 | You may of course also pipe the output of npm completion to a file 21 | such as `/usr/local/etc/bash_completion.d/npm` if you have a system 22 | that will read that file for you. 23 | 24 | When `COMP_CWORD`, `COMP_LINE`, and `COMP_POINT` are defined in the 25 | environment, `npm completion` acts in "plumbing mode", and outputs 26 | completions based on the arguments. 27 | 28 | ## SEE ALSO 29 | 30 | * npm-developers(7) 31 | * npm(1) 32 | -------------------------------------------------------------------------------- /doc/cli/npm-restart.md: -------------------------------------------------------------------------------- 1 | npm-restart(1) -- Restart a package 2 | =================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm restart [-- ] 7 | 8 | ## DESCRIPTION 9 | 10 | This restarts a package. 11 | 12 | This runs a package's "stop", "restart", and "start" scripts, and associated 13 | pre- and post- scripts, in the order given below: 14 | 15 | 1. prerestart 16 | 2. prestop 17 | 3. stop 18 | 4. poststop 19 | 5. restart 20 | 6. prestart 21 | 7. start 22 | 8. poststart 23 | 9. postrestart 24 | 25 | ## NOTE 26 | 27 | Note that the "restart" script is run **in addition to** the "stop" 28 | and "start" scripts, not instead of them. 29 | 30 | This is the behavior as of `npm` major version 2. A change in this 31 | behavior will be accompanied by an increase in major version number 32 | 33 | ## SEE ALSO 34 | 35 | * npm-run-script(1) 36 | * npm-scripts(7) 37 | * npm-test(1) 38 | * npm-start(1) 39 | * npm-stop(1) 40 | * npm-restart(3) -------------------------------------------------------------------------------- /doc/cli/npm-help-search.md: -------------------------------------------------------------------------------- 1 | npm-help-search(1) -- Search npm help documentation 2 | =================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm help-search 7 | 8 | ## DESCRIPTION 9 | 10 | This command will search the npm markdown documentation files for the 11 | terms provided, and then list the results, sorted by relevance. 12 | 13 | If only one result is found, then it will show that help topic. 14 | 15 | If the argument to `npm help` is not a known help topic, then it will 16 | call `help-search`. It is rarely if ever necessary to call this 17 | command directly. 18 | 19 | ## CONFIGURATION 20 | 21 | ### long 22 | 23 | * Type: Boolean 24 | * Default: false 25 | 26 | If true, the "long" flag will cause help-search to output context around 27 | where the terms were found in the documentation. 28 | 29 | If false, then help-search will just list out the help topics found. 30 | 31 | ## SEE ALSO 32 | 33 | * npm(1) 34 | * npm-help(1) 35 | -------------------------------------------------------------------------------- /bin/npm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | (set -o igncr) 2>/dev/null && set -o igncr; # cygwin encoding fix 3 | 4 | basedir=`dirname "$0"` 5 | 6 | case `uname` in 7 | *CYGWIN*) basedir=`cygpath -w "$basedir"`;; 8 | esac 9 | 10 | NODE_EXE="$basedir/node.exe" 11 | if ! [ -x "$NODE_EXE" ]; then 12 | NODE_EXE=node 13 | fi 14 | 15 | NPM_CLI_JS="$basedir/node_modules/npm/bin/npm-cli.js" 16 | 17 | case `uname` in 18 | *MINGW*) 19 | NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` 20 | NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" 21 | if [ -f "$NPM_PREFIX_NPM_CLI_JS" ]; then 22 | NPM_CLI_JS="$NPM_PREFIX_NPM_CLI_JS" 23 | fi 24 | ;; 25 | *CYGWIN*) 26 | NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g` 27 | NPM_PREFIX_NPM_CLI_JS="$NPM_PREFIX/node_modules/npm/bin/npm-cli.js" 28 | if [ -f "$NPM_PREFIX_NPM_CLI_JS" ]; then 29 | NPM_CLI_JS="$NPM_PREFIX_NPM_CLI_JS" 30 | fi 31 | ;; 32 | esac 33 | 34 | "$NODE_EXE" "$NPM_CLI_JS" "$@" 35 | -------------------------------------------------------------------------------- /test/tap/cache-add-unpublished.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | 4 | test('cache add', function (t) { 5 | setup(function (er, s) { 6 | if (er) { 7 | throw er 8 | } 9 | common.npm( 10 | [ 11 | 'cache', 12 | 'add', 13 | 'superfoo', 14 | '--registry=http://localhost:1337/' 15 | ], 16 | {}, 17 | function (er, c, so, se) { 18 | if (er) throw er 19 | t.ok(c, 'got non-zero exit code') 20 | t.equal(so, '', 'nothing printed to stdout') 21 | t.similar(se, /404 Not Found: superfoo/, 'got expected error') 22 | s.close() 23 | t.end() 24 | } 25 | ) 26 | }) 27 | }) 28 | 29 | function setup (cb) { 30 | var s = require('http').createServer(function (req, res) { 31 | res.statusCode = 404 32 | res.end('{\"error\":\"not_found\"}\n') 33 | }) 34 | s.listen(1337, function () { 35 | cb(null, s) 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /doc/cli/npm-help.md: -------------------------------------------------------------------------------- 1 | npm-help(1) -- Get help on npm 2 | ============================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm help [] 7 | 8 | ## DESCRIPTION 9 | 10 | If supplied a topic, then show the appropriate documentation page. 11 | 12 | If the topic does not exist, or if multiple terms are provided, then run 13 | the `help-search` command to find a match. Note that, if `help-search` 14 | finds a single subject, then it will run `help` on that topic, so unique 15 | matches are equivalent to specifying a topic name. 16 | 17 | ## CONFIGURATION 18 | 19 | ### viewer 20 | 21 | * Default: "man" on Posix, "browser" on Windows 22 | * Type: path 23 | 24 | The program to use to view help content. 25 | 26 | Set to `"browser"` to view html help content in the default web browser. 27 | 28 | ## SEE ALSO 29 | 30 | * npm(1) 31 | * README 32 | * npm-folders(5) 33 | * npm-config(1) 34 | * npm-config(7) 35 | * npmrc(5) 36 | * package.json(5) 37 | * npm-help-search(1) 38 | * npm-index(7) 39 | -------------------------------------------------------------------------------- /test/tap/spawn-enoent-help.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var test = require('tap').test 3 | var rimraf = require('rimraf') 4 | var mkdirp = require('mkdirp') 5 | var common = require('../common-tap.js') 6 | 7 | var pkg = path.resolve(__dirname, 'spawn-enoent-help') 8 | 9 | common.pendIfWindows('man pages are not built on Windows') 10 | 11 | test('setup', function (t) { 12 | rimraf.sync(pkg) 13 | mkdirp.sync(pkg) 14 | t.end() 15 | }) 16 | 17 | test('enoent help', function (t) { 18 | common.npm(['help', 'config'], { 19 | cwd: pkg, 20 | env: { 21 | PATH: '', 22 | Path: '', 23 | 'npm_config_loglevel': 'warn', 24 | 'npm_config_viewer': 'woman' 25 | } 26 | }, function (er, code, sout, serr) { 27 | t.similar(serr, /Check if the file 'emacsclient' is present./) 28 | t.equal(global.cooked, undefined, "Don't leak into global scope") 29 | t.end() 30 | }) 31 | }) 32 | 33 | test('clean', function (t) { 34 | rimraf.sync(pkg) 35 | t.end() 36 | }) 37 | -------------------------------------------------------------------------------- /lib/bugs.js: -------------------------------------------------------------------------------- 1 | module.exports = bugs 2 | 3 | var npm = require('./npm.js') 4 | var log = require('npmlog') 5 | var opener = require('opener') 6 | var fetchPackageMetadata = require('./fetch-package-metadata.js') 7 | var usage = require('./utils/usage') 8 | 9 | bugs.usage = usage( 10 | 'bugs', 11 | 'npm bugs []' 12 | ) 13 | 14 | bugs.completion = function (opts, cb) { 15 | // FIXME: there used to be registry completion here, but it stopped making 16 | // sense somewhere around 50,000 packages on the registry 17 | cb() 18 | } 19 | 20 | function bugs (args, cb) { 21 | var n = args.length ? args[0] : '.' 22 | fetchPackageMetadata(n, '.', {fullMetadata: true}, function (er, d) { 23 | if (er) return cb(er) 24 | 25 | var url = d.bugs && ((typeof d.bugs === 'string') ? d.bugs : d.bugs.url) 26 | if (!url) { 27 | url = 'https://www.npmjs.org/package/' + d.name 28 | } 29 | log.silly('bugs', 'url', url) 30 | opener(url, { command: npm.config.get('browser') }, cb) 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /doc/cli/npm-edit.md: -------------------------------------------------------------------------------- 1 | npm-edit(1) -- Edit an installed package 2 | ======================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm edit [@] 7 | 8 | ## DESCRIPTION 9 | 10 | Opens the package folder in the default editor (or whatever you've 11 | configured as the npm `editor` config -- see `npm-config(7)`.) 12 | 13 | After it has been edited, the package is rebuilt so as to pick up any 14 | changes in compiled packages. 15 | 16 | For instance, you can do `npm install connect` to install connect 17 | into your package, and then `npm edit connect` to make a few 18 | changes to your locally installed copy. 19 | 20 | ## CONFIGURATION 21 | 22 | ### editor 23 | 24 | * Default: `EDITOR` environment variable if set, or `"vi"` on Posix, 25 | or `"notepad"` on Windows. 26 | * Type: path 27 | 28 | The command to run for `npm edit` or `npm config edit`. 29 | 30 | ## SEE ALSO 31 | 32 | * npm-folders(5) 33 | * npm-explore(1) 34 | * npm-install(1) 35 | * npm-config(1) 36 | * npm-config(7) 37 | * npmrc(5) 38 | -------------------------------------------------------------------------------- /lib/doctor/verify-cached-files.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const cacache = require('cacache') 4 | const log = require('npmlog') 5 | 6 | module.exports = verifyCachedFiles 7 | function verifyCachedFiles (cache, cb) { 8 | log.info('verifyCachedFiles', `Verifying cache at ${cache}`) 9 | cacache.verify(cache).then((stats) => { 10 | log.info('verifyCachedFiles', `Verification complete. Stats: ${JSON.stringify(stats, 2)}`) 11 | if (stats.reclaimedCount || stats.badContentCount || stats.missingContent) { 12 | stats.badContentCount && log.warn('verifyCachedFiles', `Corrupted content removed: ${stats.badContentCount}`) 13 | stats.reclaimedCount && log.warn('verifyCachedFiles', `Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) 14 | stats.missingContent && log.warn('verifyCachedFiles', `Missing content: ${stats.missingContent}`) 15 | log.warn('verifyCachedFiles', 'Cache issues have been fixed') 16 | } 17 | return stats 18 | }).then((s) => cb(null, s), cb) 19 | } 20 | -------------------------------------------------------------------------------- /lib/install/copy-tree.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var createNode = require('./node.js').create 3 | module.exports = function (tree, filter) { 4 | return copyTree(tree, {}, filter) 5 | } 6 | 7 | function copyTree (tree, cache, filter) { 8 | if (filter && !filter(tree)) { return null } 9 | if (cache[tree.path]) { return cache[tree.path] } 10 | var newTree = cache[tree.path] = createNode(Object.assign({}, tree)) 11 | copyModuleList(newTree, 'children', cache, filter) 12 | newTree.children.forEach(function (child) { 13 | child.parent = newTree 14 | }) 15 | copyModuleList(newTree, 'requires', cache, filter) 16 | copyModuleList(newTree, 'requiredBy', cache, filter) 17 | return newTree 18 | } 19 | 20 | function copyModuleList (tree, key, cache, filter) { 21 | var newList = [] 22 | if (tree[key]) { 23 | tree[key].forEach(function (child) { 24 | const copy = copyTree(child, cache, filter) 25 | if (copy) { 26 | newList.push(copy) 27 | } 28 | }) 29 | } 30 | tree[key] = newList 31 | } 32 | -------------------------------------------------------------------------------- /test/tap/global-prefix-set-in-userconfig.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | var rimraf = require('rimraf') 4 | var prefix = __filename.replace(/\.js$/, '') 5 | var rcfile = __filename.replace(/\.js$/, '.npmrc') 6 | var fs = require('fs') 7 | var conf = 'prefix = ' + prefix + '\n' 8 | 9 | test('setup', function (t) { 10 | rimraf.sync(prefix) 11 | fs.writeFileSync(rcfile, conf) 12 | t.pass('ready') 13 | t.end() 14 | }) 15 | 16 | test('run command', function (t) { 17 | var args = ['prefix', '-g', '--userconfig=' + rcfile] 18 | common.npm(args, {env: {}}, function (er, code, so) { 19 | if (er) throw er 20 | t.notOk(code, 'npm prefix exited with code 0') 21 | t.equal(so.trim(), prefix) 22 | t.end() 23 | }) 24 | }) 25 | 26 | test('made dir', function (t) { 27 | t.ok(fs.statSync(prefix).isDirectory()) 28 | t.end() 29 | }) 30 | 31 | test('cleanup', function (t) { 32 | rimraf.sync(prefix) 33 | rimraf.sync(rcfile) 34 | t.pass('clean') 35 | t.end() 36 | }) 37 | -------------------------------------------------------------------------------- /lib/utils/module-name.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | 4 | module.exports = moduleName 5 | module.exports.test = {} 6 | 7 | module.exports.test.pathToPackageName = pathToPackageName 8 | function pathToPackageName (dir) { 9 | if (dir == null) return '' 10 | if (dir === '') return '' 11 | var name = path.relative(path.resolve(dir, '..'), dir) 12 | var scoped = path.relative(path.resolve(dir, '../..'), dir) 13 | if (scoped[0] === '@') return scoped.replace(/\\/g, '/') 14 | return name 15 | } 16 | 17 | module.exports.test.isNotEmpty = isNotEmpty 18 | function isNotEmpty (str) { 19 | return str != null && str !== '' 20 | } 21 | 22 | var unknown = 0 23 | function moduleName (tree) { 24 | var pkg = tree.package || tree 25 | if (isNotEmpty(pkg.name)) return pkg.name 26 | var pkgName = pathToPackageName(tree.path) 27 | if (pkgName !== '') return pkgName 28 | if (tree._invalidName != null) return tree._invalidName 29 | tree._invalidName = '!invalid#' + (++unknown) 30 | return tree._invalidName 31 | } 32 | -------------------------------------------------------------------------------- /test/tap/unit-package-id.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var packageId = require('../../lib/utils/package-id.js') 4 | 5 | test('packageId', function (t) { 6 | t.is(packageId({package: {_id: 'abc@123'}}), 'abc@123', 'basic') 7 | t.is(packageId({_id: 'abc@123'}), 'abc@123', 'basic no tree') 8 | t.is(packageId({package: {name: 'abc', version: '123'}}), 'abc@123', 'computed') 9 | t.is(packageId({package: {_id: '@', name: 'abc', version: '123'}}), 'abc@123', 'computed, ignore invalid id') 10 | t.is(packageId({package: {name: 'abc'}}), 'abc', 'no version') 11 | t.is(packageId({package: {version: '123'}}), '!invalid#1@123', 'version, no name') 12 | t.is(packageId({package: {version: '123'}, path: '/path/to/abc'}), 'abc@123', 'version path-name') 13 | t.is(packageId({package: {version: '123'}, path: '/path/@to/abc'}), '@to/abc@123', 'version scoped-path-name') 14 | t.is(packageId({path: '/path/to/abc'}), 'abc', 'path name, no version') 15 | t.is(packageId({}), '!invalid#2', 'nothing') 16 | t.done() 17 | }) 18 | -------------------------------------------------------------------------------- /test/tap/update-path.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var requireInject = require('require-inject') 4 | 5 | var mockNpm = { 6 | config: { 7 | get: function (key) { 8 | return false 9 | } 10 | }, 11 | commands: { 12 | outdated: function (args, silent, cb) { 13 | cb(null, [ 14 | [{path: '/incorrect', parent: {path: '/correct'}}, 'abc', '1.0.0', '1.1.0', '1.1.0', '^1.1.0'] 15 | ]) 16 | } 17 | } 18 | } 19 | 20 | // What we're testing here is that updates use the parent module's path to 21 | // install from. 22 | test('update', function (t) { 23 | var update = requireInject('../../lib/update.js', { 24 | '../../lib/npm.js': mockNpm, 25 | '../../lib/install.js': { 26 | 'Installer': function (where, dryrun, args) { 27 | t.is(where, '/correct', 'We should be installing to the parent of the modules being updated') 28 | this.run = function (cb) { cb() } 29 | } 30 | } 31 | }) 32 | update(['abc'], function () { 33 | t.end() 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /doc/cli/npm-explore.md: -------------------------------------------------------------------------------- 1 | npm-explore(1) -- Browse an installed package 2 | ============================================= 3 | 4 | ## SYNOPSIS 5 | 6 | npm explore [ -- ] 7 | 8 | ## DESCRIPTION 9 | 10 | Spawn a subshell in the directory of the installed package specified. 11 | 12 | If a command is specified, then it is run in the subshell, which then 13 | immediately terminates. 14 | 15 | This is particularly handy in the case of git submodules in the 16 | `node_modules` folder: 17 | 18 | npm explore some-dependency -- git pull origin master 19 | 20 | Note that the package is *not* automatically rebuilt afterwards, so be 21 | sure to use `npm rebuild ` if you make any changes. 22 | 23 | ## CONFIGURATION 24 | 25 | ### shell 26 | 27 | * Default: SHELL environment variable, or "bash" on Posix, or "cmd" on 28 | Windows 29 | * Type: path 30 | 31 | The shell to run for the `npm explore` command. 32 | 33 | ## SEE ALSO 34 | 35 | * npm-folders(5) 36 | * npm-edit(1) 37 | * npm-rebuild(1) 38 | * npm-build(1) 39 | * npm-install(1) 40 | -------------------------------------------------------------------------------- /lib/utils/pick-manifest-from-registry-metadata.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = pickManifestFromRegistryMetadata 3 | 4 | var log = require('npmlog') 5 | var semver = require('semver') 6 | 7 | function pickManifestFromRegistryMetadata (spec, tag, versions, metadata) { 8 | log.silly('pickManifestFromRegistryMetadata', 'spec', spec, 'tag', tag, 'versions', versions) 9 | 10 | // if the tagged version satisfies, then use that. 11 | var tagged = metadata['dist-tags'][tag] 12 | if (tagged && 13 | metadata.versions[tagged] && 14 | semver.satisfies(tagged, spec, true)) { 15 | return {resolvedTo: tag, manifest: metadata.versions[tagged]} 16 | } 17 | // find the max satisfying version. 18 | var ms = semver.maxSatisfying(versions, spec, true) 19 | if (ms) { 20 | return {resolvedTo: ms, manifest: metadata.versions[ms]} 21 | } else if (spec === '*' && versions.length && tagged && metadata.versions[tagged]) { 22 | return {resolvedTo: tag, manifest: metadata.versions[tagged]} 23 | } else { 24 | return 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/tap/spawn-enoent.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var test = require('tap').test 3 | var fs = require('fs') 4 | var rimraf = require('rimraf') 5 | var mkdirp = require('mkdirp') 6 | var common = require('../common-tap.js') 7 | 8 | var pkg = path.resolve(__dirname, 'spawn-enoent') 9 | var pj = JSON.stringify({ 10 | name: 'x', 11 | version: '1.2.3', 12 | scripts: { start: 'wharble-garble-blorst' } 13 | }, null, 2) + '\n' 14 | 15 | test('setup', function (t) { 16 | rimraf.sync(pkg) 17 | mkdirp.sync(pkg) 18 | fs.writeFileSync(pkg + '/package.json', pj) 19 | t.end() 20 | }) 21 | 22 | test('enoent script', function (t) { 23 | common.npm(['start'], { 24 | cwd: pkg, 25 | env: { 26 | PATH: process.env.PATH, 27 | Path: process.env.Path, 28 | 'npm_config_loglevel': 'warn' 29 | } 30 | }, function (er, code, sout, serr) { 31 | t.similar(serr, /npm ERR! Failed at the x@1\.2\.3 start script\./) 32 | t.end() 33 | }) 34 | }) 35 | 36 | test('clean', function (t) { 37 | rimraf.sync(pkg) 38 | t.end() 39 | }) 40 | -------------------------------------------------------------------------------- /lib/utils/get-publish-config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const clientConfig = require('../config/reg-client.js') 4 | const Conf = require('../config/core.js').Conf 5 | const log = require('npmlog') 6 | const npm = require('../npm.js') 7 | const RegClient = require('npm-registry-client') 8 | 9 | module.exports = getPublishConfig 10 | 11 | function getPublishConfig (publishConfig, defaultConfig, defaultClient) { 12 | let config = defaultConfig 13 | let client = defaultClient 14 | log.verbose('getPublishConfig', publishConfig) 15 | if (publishConfig) { 16 | config = new Conf(defaultConfig) 17 | config.save = defaultConfig.save.bind(defaultConfig) 18 | 19 | // don't modify the actual publishConfig object, in case we have 20 | // to set a login token or some other data. 21 | config.unshift(Object.keys(publishConfig).reduce(function (s, k) { 22 | s[k] = publishConfig[k] 23 | return s 24 | }, {})) 25 | client = new RegClient(clientConfig(npm, log, config)) 26 | } 27 | 28 | return { config: config, client: client } 29 | } 30 | -------------------------------------------------------------------------------- /test/tap/test-run-ls.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | var path = require('path') 4 | var cwd = path.resolve(__dirname, '..', '..') 5 | var testscript = require('../../package.json').scripts.test 6 | var tsregexp = testscript.replace(/([\[\.\*\]])/g, '\\$1') 7 | 8 | test('default', function (t) { 9 | common.npm(['run'], { cwd: cwd }, function (er, code, so) { 10 | if (er) throw er 11 | t.notOk(code) 12 | t.similar(so, new RegExp('\\n test\\n ' + tsregexp + '\\n')) 13 | t.end() 14 | }) 15 | }) 16 | 17 | test('parseable', function (t) { 18 | common.npm(['run', '-p'], { cwd: cwd }, function (er, code, so) { 19 | if (er) throw er 20 | t.notOk(code) 21 | t.similar(so, new RegExp('\\ntest:' + tsregexp + '\\n')) 22 | t.end() 23 | }) 24 | }) 25 | 26 | test('parseable', function (t) { 27 | common.npm(['run', '--json'], { cwd: cwd }, function (er, code, so) { 28 | if (er) throw er 29 | t.notOk(code) 30 | t.equal(JSON.parse(so).test, testscript) 31 | t.end() 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /doc/cli/npm-bugs.md: -------------------------------------------------------------------------------- 1 | npm-bugs(1) -- Bugs for a package in a web browser maybe 2 | ======================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm bugs [] 7 | 8 | aliases: issues 9 | 10 | ## DESCRIPTION 11 | 12 | This command tries to guess at the likely location of a package's 13 | bug tracker URL, and then tries to open it using the `--browser` 14 | config param. If no package name is provided, it will search for 15 | a `package.json` in the current folder and use the `name` property. 16 | 17 | ## CONFIGURATION 18 | 19 | ### browser 20 | 21 | * Default: OS X: `"open"`, Windows: `"start"`, Others: `"xdg-open"` 22 | * Type: String 23 | 24 | The browser that is called by the `npm bugs` command to open websites. 25 | 26 | ### registry 27 | 28 | * Default: https://registry.npmjs.org/ 29 | * Type: url 30 | 31 | The base URL of the npm package registry. 32 | 33 | 34 | ## SEE ALSO 35 | 36 | * npm-docs(1) 37 | * npm-view(1) 38 | * npm-publish(1) 39 | * npm-registry(7) 40 | * npm-config(1) 41 | * npm-config(7) 42 | * npmrc(5) 43 | * package.json(5) 44 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | # LTS is our most important target 4 | - nodejs_version: "6" 5 | # previous LTS is next most important 6 | - nodejs_version: "4" 7 | - nodejs_version: "7" 8 | # then master 9 | - nodejs_version: "8" 10 | COVERALLS_REPO_TOKEN: 11 | secure: XdC0aySefK0HLh1GNk6aKrzZPbCfPQLyA4mYtFGEp4DrTuZA/iuCUS0LDqFYO8JQ 12 | platform: 13 | - x86 14 | - x64 15 | install: 16 | - ps: Install-Product node $env:nodejs_version $env:platform 17 | - npm config set spin false 18 | - npm rebuild 19 | - node . install -g . 20 | - set "PATH=%APPDATA%\npm;C:\Program Files\Git\mingw64\libexec;%PATH%" 21 | - npm install --loglevel=http 22 | test_script: 23 | - node --version 24 | - npm --version 25 | - npm run test -- --reporter=classic 26 | notifications: 27 | - provider: Slack 28 | incoming_webhook: 29 | secure: vXiG5AgpqxJsXZ0N0CTYDuVrX6RMjBybZKtOx6IbRxCyjgd+DAx6Z9/0XgYQjuof7QFJY3M/U6HxaREQVYbNVHA+C5N5dNALRbKzAC8QNbA= 30 | # GO_FAST 31 | matrix: 32 | fast_finish: true 33 | # we don't need the builds, we just need tests 34 | build: off 35 | -------------------------------------------------------------------------------- /doc/cli/npm-owner.md: -------------------------------------------------------------------------------- 1 | npm-owner(1) -- Manage package owners 2 | ===================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm owner add [<@scope>/] 7 | npm owner rm [<@scope>/] 8 | npm owner ls [<@scope>/] 9 | 10 | aliases: author 11 | 12 | ## DESCRIPTION 13 | 14 | Manage ownership of published packages. 15 | 16 | * ls: 17 | List all the users who have access to modify a package and push new versions. 18 | Handy when you need to know who to bug for help. 19 | * add: 20 | Add a new user as a maintainer of a package. This user is enabled to modify 21 | metadata, publish new versions, and add other owners. 22 | * rm: 23 | Remove a user from the package owner list. This immediately revokes their 24 | privileges. 25 | 26 | Note that there is only one level of access. Either you can modify a package, 27 | or you can't. Future versions may contain more fine-grained access levels, but 28 | that is not implemented at this time. 29 | 30 | ## SEE ALSO 31 | 32 | * npm-publish(1) 33 | * npm-registry(7) 34 | * npm-adduser(1) 35 | * npm-disputes(7) 36 | -------------------------------------------------------------------------------- /lib/edit.js: -------------------------------------------------------------------------------- 1 | // npm edit 2 | // open the package folder in the $EDITOR 3 | 4 | module.exports = edit 5 | edit.usage = 'npm edit [@]' 6 | 7 | edit.completion = require('./utils/completion/installed-shallow.js') 8 | 9 | var npm = require('./npm.js') 10 | var path = require('path') 11 | var fs = require('graceful-fs') 12 | var editor = require('editor') 13 | var noProgressTillDone = require('./utils/no-progress-while-running').tillDone 14 | 15 | function edit (args, cb) { 16 | var p = args[0] 17 | if (args.length !== 1 || !p) return cb(edit.usage) 18 | var e = npm.config.get('editor') 19 | if (!e) { 20 | return cb(new Error( 21 | "No editor set. Set the 'editor' config, or $EDITOR environ." 22 | )) 23 | } 24 | p = p.split('/') 25 | .join('/node_modules/') 26 | .replace(/(\/node_modules)+/, '/node_modules') 27 | var f = path.resolve(npm.dir, p) 28 | fs.lstat(f, function (er) { 29 | if (er) return cb(er) 30 | editor(f, { editor: e }, noProgressTillDone(function (er) { 31 | if (er) return cb(er) 32 | npm.commands.rebuild(args, cb) 33 | })) 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /test/tap/uninstall-in-reverse.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var requireInject = require('require-inject') 4 | var log = require('npmlog') 5 | 6 | /* 7 | The remove actions need to happen in the opposite of their normally defined 8 | order. That is, they need to go shallow -> deep. 9 | */ 10 | 11 | var removed = [] 12 | var npm = requireInject.installGlobally('../../lib/npm.js', { 13 | '../../lib/install/action/remove.js': function (staging, pkg, log, next) { 14 | removed.push(pkg.package.name) 15 | next() 16 | } 17 | }) 18 | 19 | test('setup', function (t) { 20 | npm.load(function () { 21 | t.pass('npm loaded') 22 | t.end() 23 | }) 24 | }) 25 | 26 | test('abc', function (t) { 27 | var Installer = require('../../lib/install.js').Installer 28 | var inst = new Installer(__dirname, false, []) 29 | inst.progress = {executeActions: log} 30 | inst.todo = [ 31 | ['remove', {package: {name: 'first'}}], 32 | ['remove', {package: {name: 'second'}}] 33 | ] 34 | inst.executeActions(function () { 35 | t.isDeeply(removed, ['second', 'first']) 36 | t.end() 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /test/tap/cruft-test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var fs = require('graceful-fs') 3 | var path = require('path') 4 | var mkdirpSync = require('mkdirp').sync 5 | var rimraf = require('rimraf') 6 | var test = require('tap').test 7 | var common = require('../common-tap.js') 8 | 9 | var base = path.join(__dirname, path.basename(__filename, '.js')) 10 | var cruft = path.join(base, 'node_modules', 'cruuuft') 11 | var pkg = { 12 | name: 'example', 13 | version: '1.0.0', 14 | dependencies: {} 15 | } 16 | 17 | function setup () { 18 | mkdirpSync(path.dirname(cruft)) 19 | fs.writeFileSync(cruft, 'this is some cruft for sure') 20 | fs.writeFileSync(path.join(base, 'package.json'), JSON.stringify(pkg)) 21 | } 22 | 23 | function cleanup () { 24 | rimraf.sync(base) 25 | } 26 | 27 | test('setup', function (t) { 28 | cleanup() 29 | setup() 30 | t.done() 31 | }) 32 | 33 | test('cruft', function (t) { 34 | common.npm(['ls'], {cwd: base}, function (er, code, stdout, stderr) { 35 | t.is(stderr, '', 'no warnings or errors from ls') 36 | t.done() 37 | }) 38 | }) 39 | 40 | test('cleanup', function (t) { 41 | cleanup() 42 | t.done() 43 | }) 44 | -------------------------------------------------------------------------------- /test/tap/pwd-prefix.js: -------------------------------------------------------------------------------- 1 | // This test ensures that a few commands do the same 2 | // thing when the cwd is where package.json is, and when 3 | // the package.json is one level up. 4 | 5 | var test = require('tap').test 6 | var common = require('../common-tap.js') 7 | var path = require('path') 8 | var root = path.resolve(__dirname, '../..') 9 | var lib = path.resolve(root, 'lib') 10 | var commands = ['run', 'version'] 11 | 12 | commands.forEach(function (cmd) { 13 | // Should get the same stdout and stderr each time 14 | var stdout, stderr 15 | 16 | test(cmd + ' in root', function (t) { 17 | common.npm([cmd], {cwd: root}, function (er, code, so, se) { 18 | if (er) throw er 19 | t.notOk(code, 'npm ' + cmd + ' exited with code 0') 20 | stdout = so 21 | stderr = se 22 | t.end() 23 | }) 24 | }) 25 | 26 | test(cmd + ' in lib', function (t) { 27 | common.npm([cmd], {cwd: lib}, function (er, code, so, se) { 28 | if (er) throw er 29 | t.notOk(code, 'npm ' + cmd + ' exited with code 0') 30 | t.equal(so, stdout) 31 | t.equal(se, stderr) 32 | t.end() 33 | }) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /doc/cli/npm-init.md: -------------------------------------------------------------------------------- 1 | npm-init(1) -- Interactively create a package.json file 2 | ======================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | npm init [-f|--force|-y|--yes] 7 | 8 | ## DESCRIPTION 9 | 10 | This will ask you a bunch of questions, and then write a package.json for you. 11 | 12 | It attempts to make reasonable guesses about what you want things to be set to, 13 | and then writes a package.json file with the options you've selected. 14 | 15 | If you already have a package.json file, it'll read that first, and default to 16 | the options in there. 17 | 18 | It is strictly additive, so it does not delete options from your package.json 19 | without a really good reason to do so. 20 | 21 | If you invoke it with `-f`, `--force`, `-y`, or `--yes`, it will use only 22 | defaults and not prompt you for any options. 23 | 24 | ## CONFIGURATION 25 | 26 | ### scope 27 | 28 | * Default: none 29 | * Type: String 30 | 31 | The scope under which the new module should be created. 32 | 33 | ## SEE ALSO 34 | 35 | * 36 | * package.json(5) 37 | * npm-version(1) 38 | * npm-scope(7) 39 | -------------------------------------------------------------------------------- /test/tap/node-modules-path-munge.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var t = require('tap') 3 | var fs = require('fs') 4 | var rimraf = require('rimraf') 5 | var mkdirp = require('mkdirp') 6 | var path = require('path') 7 | var dir = path.join(__dirname, 'my_node_modules') 8 | var script = process.platform === 'win32' ? 'echo %PATH%' : 'echo $PATH' 9 | 10 | t.test('setup', function (t) { 11 | rimraf.sync(dir) 12 | mkdirp.sync(dir) 13 | fs.writeFileSync(dir + '/package.json', JSON.stringify({ 14 | name: 'my_node_modules', 15 | version: '1.2.3', 16 | scripts: { 17 | test: script 18 | } 19 | })) 20 | t.end() 21 | }) 22 | 23 | t.test('verify PATH is munged right', function (t) { 24 | common.npm(['test'], { cwd: dir }, function (err, code, stdout, stderr) { 25 | if (err) { 26 | throw err 27 | } 28 | t.equal(code, 0, 'exit ok') 29 | t.notOk(stderr, 'should have no stderr') 30 | var expect = path.resolve(dir, 'node_modules', '.bin').toLowerCase() 31 | t.contains(stdout.toLowerCase(), expect) 32 | t.end() 33 | }) 34 | }) 35 | 36 | t.test('cleanup', function (t) { 37 | rimraf.sync(dir) 38 | t.end() 39 | }) 40 | -------------------------------------------------------------------------------- /test/tap/publish-access-unscoped-restricted-fails.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | 4 | var test = require('tap').test 5 | var mkdirp = require('mkdirp') 6 | var rimraf = require('rimraf') 7 | var common = require('../common-tap.js') 8 | 9 | var pkg = path.join(__dirname, 'publish-access-unscoped') 10 | 11 | test('setup', function (t) { 12 | mkdirp.sync(pkg) 13 | fs.writeFileSync( 14 | path.join(pkg, 'package.json'), 15 | JSON.stringify({ 16 | name: 'publish-access', 17 | version: '1.2.5' 18 | })) 19 | t.pass('setup done') 20 | t.end() 21 | }) 22 | 23 | test('unscoped packages cannot be restricted', function (t) { 24 | var args = ['--access=restricted', '--loglevel=warn', '--registry=' + common.registry] 25 | var opts = {stdio: [0, 1, 'pipe'], cwd: pkg} 26 | common.npm(['publish'].concat(args), opts, function (err, code, stdout, stderr) { 27 | if (err) throw err 28 | t.notEqual(code, 0, 'publish not successful') 29 | t.match(stderr, "Can't restrict access to unscoped packages.") 30 | 31 | t.end() 32 | }) 33 | }) 34 | 35 | test('cleanup', function (t) { 36 | rimraf.sync(pkg) 37 | t.end() 38 | }) 39 | -------------------------------------------------------------------------------- /lib/install/writable.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var fs = require('fs') 4 | var inflight = require('inflight') 5 | var accessError = require('./access-error.js') 6 | var andIgnoreErrors = require('./and-ignore-errors.js') 7 | var isFsAccessAvailable = require('./is-fs-access-available.js') 8 | 9 | if (isFsAccessAvailable) { 10 | module.exports = fsAccessImplementation 11 | } else { 12 | module.exports = fsOpenImplementation 13 | } 14 | 15 | // exposed only for testing purposes 16 | module.exports.fsAccessImplementation = fsAccessImplementation 17 | module.exports.fsOpenImplementation = fsOpenImplementation 18 | 19 | function fsAccessImplementation (dir, done) { 20 | done = inflight('writable:' + dir, done) 21 | if (!done) return 22 | fs.access(dir, fs.W_OK, done) 23 | } 24 | 25 | function fsOpenImplementation (dir, done) { 26 | done = inflight('writable:' + dir, done) 27 | if (!done) return 28 | var tmp = path.join(dir, '.npm.check.permissions') 29 | fs.open(tmp, 'w', function (er, fd) { 30 | if (er) return done(accessError(dir, er)) 31 | fs.close(fd, function () { 32 | fs.unlink(tmp, andIgnoreErrors(done)) 33 | }) 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /doc/cli/npm-docs.md: -------------------------------------------------------------------------------- 1 | npm-docs(1) -- Docs for a package in a web browser maybe 2 | ======================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm docs [ [ ...]] 7 | npm docs . 8 | npm home [ [ ...]] 9 | npm home . 10 | 11 | ## DESCRIPTION 12 | 13 | This command tries to guess at the likely location of a package's 14 | documentation URL, and then tries to open it using the `--browser` 15 | config param. You can pass multiple package names at once. If no 16 | package name is provided, it will search for a `package.json` in 17 | the current folder and use the `name` property. 18 | 19 | ## CONFIGURATION 20 | 21 | ### browser 22 | 23 | * Default: OS X: `"open"`, Windows: `"start"`, Others: `"xdg-open"` 24 | * Type: String 25 | 26 | The browser that is called by the `npm docs` command to open websites. 27 | 28 | ### registry 29 | 30 | * Default: https://registry.npmjs.org/ 31 | * Type: url 32 | 33 | The base URL of the npm package registry. 34 | 35 | 36 | ## SEE ALSO 37 | 38 | * npm-view(1) 39 | * npm-publish(1) 40 | * npm-registry(7) 41 | * npm-config(1) 42 | * npm-config(7) 43 | * npmrc(5) 44 | * package.json(5) 45 | -------------------------------------------------------------------------------- /lib/install/report-optional-failure.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var moduleName = require('../utils/module-name.js') 4 | 5 | module.exports = reportOptionalFailure 6 | 7 | function top (tree) { 8 | if (tree.parent) return top(tree.parent) 9 | return tree 10 | } 11 | 12 | function reportOptionalFailure (tree, what, error) { 13 | var topTree = top(tree) 14 | if (!topTree.warnings) topTree.warnings = [] 15 | var id 16 | if (what) { 17 | var depVer = tree.package.dependencies && tree.package.dependencies[what] 18 | var optDepVer = tree.package.optionalDependencies && tree.package.optionalDependencies[what] 19 | var devDepVer = tree.package.devDependencies && tree.package.devDependencies[what] 20 | var version = depVer || optDepVer || devDepVer 21 | id = what + (version ? '@' + version : '') 22 | } else { 23 | id = tree._id || moduleName(tree) + (tree.package.version ? '@' + tree.package.version : '') 24 | } 25 | var location = path.relative(topTree.path, tree.path) 26 | if (what) location = path.join(location, 'node_modules', what) 27 | 28 | error.optional = id 29 | error.location = location 30 | topTree.warnings.push(error) 31 | } 32 | -------------------------------------------------------------------------------- /lib/install/action/prepare.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var chain = require('slide').chain 3 | var lifecycle = require('../../utils/lifecycle.js') 4 | var packageId = require('../../utils/package-id.js') 5 | var prepublishWarning = require('../../utils/warn-deprecated.js')('prepublish-on-install') 6 | var moduleStagingPath = require('../module-staging-path.js') 7 | 8 | module.exports = function (staging, pkg, log, next) { 9 | log.silly('prepublish', packageId(pkg)) 10 | // TODO: for `npm@5`, change the behavior and remove this warning. 11 | // see https://github.com/npm/npm/issues/10074 for details 12 | if (pkg.package && pkg.package.scripts && pkg.package.scripts.prepublish) { 13 | prepublishWarning([ 14 | 'As of npm@5, `prepublish` scripts are deprecated.', 15 | 'Use `prepare` for build steps and `prepublishOnly` for upload-only.', 16 | 'See the deprecation note in `npm help scripts` for more information.' 17 | ]) 18 | } 19 | var buildpath = moduleStagingPath(staging, pkg) 20 | chain( 21 | [ 22 | [lifecycle, pkg.package, 'prepublish', buildpath, false, false], 23 | [lifecycle, pkg.package, 'prepare', buildpath, false, false] 24 | ], 25 | next 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /test/tap/install-parse-error.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var test = require('tap').test 4 | var Tacks = require('tacks') 5 | var File = Tacks.File 6 | var Dir = Tacks.Dir 7 | var common = require('../common-tap.js') 8 | 9 | var testdir = path.join(__dirname, path.basename(__filename, '.js')) 10 | 11 | var fixture = new Tacks(Dir({ 12 | 'package.json': File( 13 | '{\n' + 14 | "'name': 'some-name',\n" + 15 | "'dependencies': {}\n" + 16 | '}' 17 | ), 18 | 'node_modules': Dir() 19 | })) 20 | 21 | function setup () { 22 | fixture.create(testdir) 23 | } 24 | 25 | function cleanup () { 26 | fixture.remove(testdir) 27 | } 28 | 29 | test('setup', function (t) { 30 | cleanup() 31 | setup() 32 | t.end() 33 | }) 34 | 35 | test('failing to parse package.json should be error', function (t) { 36 | common.npm( 37 | ['install'], 38 | {cwd: testdir}, 39 | function (err, code, stdout, stderr) { 40 | if (err) throw err 41 | t.equal(code, 1, 'exit not ok') 42 | t.similar(stderr, /npm ERR! Failed to parse json/) 43 | t.end() 44 | } 45 | ) 46 | }) 47 | 48 | test('cleanup', function (t) { 49 | cleanup() 50 | t.end() 51 | }) 52 | 53 | -------------------------------------------------------------------------------- /doc/files/npm-shrinkwrap.json.md: -------------------------------------------------------------------------------- 1 | npm-shrinkwrap.json(5) -- A publishable lockfile 2 | ===================================================== 3 | 4 | ## DESCRIPTION 5 | 6 | `npm-shrinkwrap.json` is a file created by npm-shrinkwrap(1). It is identical to 7 | `package-lock.json`, with one major caveat: Unlike `package-lock.json`, 8 | `npm-shrinwkrap.json` may be included when publishing a package. 9 | 10 | The recommended use-case for `npm-shrinkwrap.json` is applications deployed 11 | through the publishing process on the registry: for example, daemons and 12 | command-line tools intended as global installs or `devDependencies`. It's 13 | strongly discouraged for library authors to publish this file, since that would 14 | prevent end users from having control over transitive dependency updates. 15 | 16 | Additionally, if both `package-lock.json` and `npm-shrinwkrap.json` are present 17 | in a package root, `package-lock.json` will be ignored in favor of this file. 18 | 19 | For full details and description of the `npm-shrinkwrap.json` file format, refer 20 | to the manual page for package-lock.json(5). 21 | 22 | ## SEE ALSO 23 | 24 | * npm-shrinkwrap(1) 25 | * package-lock.json(5) 26 | * package.json(5) 27 | * npm-install(1) 28 | -------------------------------------------------------------------------------- /lib/install/flatten-tree.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var validate = require('aproba') 3 | var moduleName = require('../utils/module-name.js') 4 | 5 | module.exports = flattenTree 6 | module.exports.flatName = flatName 7 | module.exports.flatNameFromTree = flatNameFromTree 8 | 9 | function flattenTree (tree) { 10 | validate('O', arguments) 11 | var seen = {} 12 | var flat = {} 13 | var todo = [[tree, '/']] 14 | while (todo.length) { 15 | var next = todo.shift() 16 | var pkg = next[0] 17 | seen[pkg.path] = true 18 | var path = next[1] 19 | flat[path] = pkg 20 | if (path !== '/') path += '/' 21 | for (var ii = 0; ii < pkg.children.length; ++ii) { 22 | var child = pkg.children[ii] 23 | if (!seen[child.path]) { 24 | todo.push([child, flatName(path, child)]) 25 | } 26 | } 27 | } 28 | return flat 29 | } 30 | 31 | function flatName (path, child) { 32 | validate('SO', arguments) 33 | return path + (moduleName(child) || 'TOP') 34 | } 35 | 36 | function flatNameFromTree (tree) { 37 | validate('O', arguments) 38 | if (tree.isTop) return '/' 39 | var path = flatNameFromTree(tree.parent) 40 | if (path !== '/') path += '/' 41 | return flatName(path, tree) 42 | } 43 | -------------------------------------------------------------------------------- /test/tap/install-into-likenamed-folder.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var path = require('path') 3 | var fs = require('graceful-fs') 4 | var mkdirp = require('mkdirp') 5 | var rimraf = require('rimraf') 6 | var test = require('tap').test 7 | var common = require('../common-tap.js') 8 | 9 | var base = path.join(__dirname, path.basename(__filename, '.js')) 10 | var moduleDir = path.join(base, 'example-src') 11 | var destDir = path.join(base, 'example') 12 | var moduleJson = { 13 | name: 'example', 14 | version: '1.0.0' 15 | } 16 | 17 | function setup () { 18 | cleanup() 19 | mkdirp.sync(moduleDir) 20 | mkdirp.sync(path.join(destDir, 'node_modules')) 21 | fs.writeFileSync(path.join(moduleDir, 'package.json'), JSON.stringify(moduleJson)) 22 | } 23 | 24 | function cleanup () { 25 | rimraf.sync(base) 26 | } 27 | 28 | test('setup', function (t) { 29 | setup() 30 | t.end() 31 | }) 32 | 33 | test('like-named', function (t) { 34 | common.npm(['install', '../example-src'], {cwd: destDir}, function (er, code, stdout, stderr) { 35 | t.is(code, 0, 'no error code') 36 | t.is(stderr, '', 'no error output') 37 | t.end() 38 | }) 39 | }) 40 | 41 | test('cleanup', function (t) { 42 | cleanup() 43 | t.end() 44 | }) 45 | -------------------------------------------------------------------------------- /test/tap/invalid-cmd-exit-code.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var common = require('../common-tap.js') 3 | 4 | var opts = { cwd: process.cwd() } 5 | 6 | test('npm asdf should return exit code 1', function (t) { 7 | common.npm(['asdf'], opts, function (err, code, stdout, stderr) { 8 | if (err) throw err 9 | t.ok(code, 'exit code should not be zero') 10 | if (stdout.trim()) t.comment(stdout.trim()) 11 | if (stderr.trim()) t.comment(stderr.trim()) 12 | t.end() 13 | }) 14 | }) 15 | 16 | test('npm help should return exit code 0', function (t) { 17 | common.npm(['help'], opts, function (err, code, stdout, stderr) { 18 | if (err) throw err 19 | t.equal(code, 0, 'exit code should be 0') 20 | if (stdout.trim()) t.comment(stdout.trim()) 21 | if (stderr.trim()) t.comment(stderr.trim()) 22 | t.end() 23 | }) 24 | }) 25 | 26 | test('npm help fadf should return exit code 0', function (t) { 27 | common.npm(['help', 'fadf'], opts, function (err, code, stdout, stderr) { 28 | if (err) throw err 29 | t.equal(code, 0, 'exit code should be 0') 30 | if (stdout.trim()) t.comment(stdout.trim()) 31 | if (stderr.trim()) t.comment(stderr.trim()) 32 | t.end() 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /lib/docs.js: -------------------------------------------------------------------------------- 1 | module.exports = docs 2 | 3 | var npm = require('./npm.js') 4 | var opener = require('opener') 5 | var log = require('npmlog') 6 | var fetchPackageMetadata = require('./fetch-package-metadata.js') 7 | var usage = require('./utils/usage') 8 | 9 | docs.usage = usage( 10 | 'docs', 11 | 'npm docs ' + 12 | '\nnpm docs .' 13 | ) 14 | docs.completion = function (opts, cb) { 15 | // FIXME: there used to be registry completion here, but it stopped making 16 | // sense somewhere around 50,000 packages on the registry 17 | cb() 18 | } 19 | 20 | function docs (args, cb) { 21 | if (!args || !args.length) args = ['.'] 22 | var pending = args.length 23 | log.silly('docs', args) 24 | args.forEach(function (proj) { 25 | getDoc(proj, function (err) { 26 | if (err) { 27 | return cb(err) 28 | } 29 | --pending || cb() 30 | }) 31 | }) 32 | } 33 | 34 | function getDoc (project, cb) { 35 | log.silly('getDoc', project) 36 | fetchPackageMetadata(project, '.', {fullMetadata: true}, function (er, d) { 37 | if (er) return cb(er) 38 | var url = d.homepage 39 | if (!url) url = 'https://www.npmjs.org/package/' + d.name 40 | return opener(url, {command: npm.config.get('browser')}, cb) 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /lib/utils/metrics-launch.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = launchSendMetrics 3 | var fs = require('graceful-fs') 4 | var child_process = require('child_process') 5 | 6 | if (require.main === module) main() 7 | 8 | function launchSendMetrics () { 9 | var path = require('path') 10 | var npm = require('../npm.js') 11 | try { 12 | if (!npm.config.get('send-metrics')) return 13 | var cliMetrics = path.join(npm.config.get('cache'), 'anonymous-cli-metrics.json') 14 | var targetRegistry = npm.config.get('metrics-registry') 15 | fs.statSync(cliMetrics) 16 | return runInBackground(__filename, [cliMetrics, targetRegistry]) 17 | } catch (ex) { 18 | // if the metrics file doesn't exist, don't run 19 | } 20 | } 21 | 22 | function runInBackground (js, args, opts) { 23 | if (!args) args = [] 24 | args.unshift(js) 25 | if (!opts) opts = {} 26 | opts.stdio = 'ignore' 27 | opts.detached = true 28 | var child = child_process.spawn(process.execPath, args, opts) 29 | child.unref() 30 | return child 31 | } 32 | 33 | function main () { 34 | var sendMetrics = require('./metrics.js').send 35 | var metricsFile = process.argv[2] 36 | var metricsRegistry = process.argv[3] 37 | 38 | sendMetrics(metricsFile, metricsRegistry) 39 | } 40 | -------------------------------------------------------------------------------- /test/tap/00-verify-no-scoped.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var common = require('../common-tap') 3 | var test = require('tap').test 4 | var path = require('path') 5 | var cwd = path.resolve(__dirname, '..', '..') 6 | var fs = require('fs') 7 | 8 | /* 9 | We can't include any scoped modules in bundled dependencies due to a bug in 10 | npm@<4.4.3 that made any module that bundled scoped dependencies 11 | uninstallable. While this is fixed, we can't have them in ourselves without 12 | making it impossible to upgrade, thus this test. 13 | */ 14 | 15 | test('no scoped transitive deps', function (t) { 16 | t.ok(fs.existsSync(cwd), 'ensure that the path we are calling ls within exists') 17 | 18 | var opt = { cwd: cwd, stdio: [ 'ignore', 'pipe', 2 ] } 19 | common.npm(['ls', '--parseable', '--production'], opt, function (err, code, stdout) { 20 | t.ifError(err, 'error should not exist') 21 | t.equal(code, 0, 'npm ls exited with code') 22 | var matchScoped = new RegExp(path.join(cwd, 'node_modules', '.*@').replace(/\\/g, '\\\\')) 23 | stdout.split(/\n/).forEach(function (line) { 24 | if (matchScoped.test(line)) { 25 | t.notLike(line, matchScoped, 'prod deps do not contain scoped modules') 26 | } 27 | }) 28 | t.end() 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /test/tap/npm-api-not-loaded-error.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var npm = require('../..') 3 | var path = require('path') 4 | var rimraf = require('rimraf') 5 | var npmrc = path.join(__dirname, 'npmrc') 6 | var fs = require('fs') 7 | 8 | test('setup', function (t) { 9 | fs.writeFileSync(npmrc, 'foo = bar\n', 'ascii') 10 | t.end() 11 | }) 12 | 13 | test('calling set/get on config pre-load should throw', function (t) { 14 | var threw = true 15 | try { 16 | npm.config.get('foo') 17 | threw = false 18 | } catch (er) { 19 | t.equal(er.message, 'npm.load() required') 20 | } finally { 21 | t.ok(threw, 'get before load should throw') 22 | } 23 | 24 | threw = true 25 | try { 26 | npm.config.set('foo', 'bar') 27 | threw = false 28 | } catch (er) { 29 | t.equal(er.message, 'npm.load() required') 30 | } finally { 31 | t.ok(threw, 'set before load should throw') 32 | } 33 | 34 | npm.load({ userconfig: npmrc }, function (er) { 35 | if (er) throw er 36 | 37 | t.equal(npm.config.get('foo'), 'bar') 38 | npm.config.set('foo', 'baz') 39 | t.equal(npm.config.get('foo'), 'baz') 40 | t.end() 41 | }) 42 | }) 43 | 44 | test('cleanup', function (t) { 45 | rimraf.sync(npmrc) 46 | t.end() 47 | }) 48 | -------------------------------------------------------------------------------- /test/tap/config-list.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var test = require('tap').test 4 | var rimraf = require('rimraf') 5 | var mkdirp = require('mkdirp') 6 | var common = require('../common-tap.js') 7 | 8 | var pkg = path.resolve(__dirname, 'config-list') 9 | var opts = { cwd: pkg } 10 | var npmrc = path.resolve(pkg, '.npmrc') 11 | 12 | test('setup', function (t) { 13 | rimraf.sync(pkg) 14 | mkdirp.sync(pkg) 15 | t.end() 16 | }) 17 | 18 | test('config list includes project config', function (t) { 19 | // Write per-project conf file 20 | fs.writeFileSync(npmrc, 'foo=1234', 'utf8') 21 | 22 | // Create empty package.json to indicate project root 23 | fs.writeFileSync(path.resolve(pkg, 'package.json'), '{}', 'utf8') 24 | 25 | common.npm( 26 | ['config', 'list'], 27 | opts, 28 | function (err, code, stdout, stderr) { 29 | t.ifError(err) 30 | t.equal(stderr, '', 'stderr is empty') 31 | var expected = '; project config ' + npmrc + '\nfoo = "1234"' 32 | t.match(stdout, expected, 'contains project config') 33 | t.end() 34 | } 35 | ) 36 | }) 37 | 38 | // TODO: test cases for other configuration types (cli, env, user, global) 39 | 40 | test('clean', function (t) { 41 | rimraf.sync(pkg) 42 | t.end() 43 | }) 44 | -------------------------------------------------------------------------------- /test/tap/unit-deps-removeObsoleteDep.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var requireInject = require('require-inject') 4 | 5 | // we're just mocking to avoid having to call `npm.load` 6 | var deps = requireInject('../../lib/install/deps.js', { 7 | '../../lib/npm.js': { 8 | config: { 9 | get: function () { return 'mock' } 10 | }, 11 | limit: { 12 | fetch: 10 13 | } 14 | } 15 | }) 16 | 17 | var removeObsoleteDep = deps.removeObsoleteDep 18 | 19 | test('removeObsoleteDep', function (t) { 20 | var child1 = {requiredBy: []} 21 | var test1 = { 22 | removed: true, 23 | requires: [ child1 ] 24 | } 25 | removeObsoleteDep(test1) 26 | t.is(child1.removed, undefined, 'no recursion on deps flagged as removed already') 27 | 28 | var child2 = {requiredBy: []} 29 | var test2 = { 30 | requires: [ child2 ] 31 | } 32 | child2.requiredBy.push(test2) 33 | removeObsoleteDep(test2) 34 | t.is(child2.removed, true, 'required by no other modules, removing') 35 | 36 | var child3 = {requiredBy: ['NOTEMPTY']} 37 | var test3 = { 38 | requires: [ child3 ] 39 | } 40 | child3.requiredBy.push(test3) 41 | removeObsoleteDep(test3) 42 | t.is(child3.removed, undefined, 'required by other modules, keeping') 43 | t.done() 44 | }) 45 | -------------------------------------------------------------------------------- /lib/logout.js: -------------------------------------------------------------------------------- 1 | module.exports = logout 2 | 3 | var dezalgo = require('dezalgo') 4 | var log = require('npmlog') 5 | 6 | var npm = require('./npm.js') 7 | var mapToRegistry = require('./utils/map-to-registry.js') 8 | 9 | logout.usage = 'npm logout [--registry=] [--scope=<@scope>]' 10 | 11 | function afterLogout (normalized, cb) { 12 | var scope = npm.config.get('scope') 13 | 14 | if (scope) npm.config.del(scope + ':registry') 15 | 16 | npm.config.clearCredentialsByURI(normalized) 17 | npm.config.save('user', cb) 18 | } 19 | 20 | function logout (args, cb) { 21 | cb = dezalgo(cb) 22 | 23 | mapToRegistry('/', npm.config, function (err, uri, auth, normalized) { 24 | if (err) return cb(err) 25 | 26 | if (auth.token) { 27 | log.verbose('logout', 'clearing session token for', normalized) 28 | npm.registry.logout(normalized, { auth: auth }, function (err) { 29 | if (err) return cb(err) 30 | 31 | afterLogout(normalized, cb) 32 | }) 33 | } else if (auth.username || auth.password) { 34 | log.verbose('logout', 'clearing user credentials for', normalized) 35 | 36 | afterLogout(normalized, cb) 37 | } else { 38 | cb(new Error( 39 | 'Not logged in to', normalized + ',', "so can't log out." 40 | )) 41 | } 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /test/tap/version-no-package.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | var osenv = require('osenv') 4 | var path = require('path') 5 | var mkdirp = require('mkdirp') 6 | var rimraf = require('rimraf') 7 | 8 | var pkg = path.resolve(__dirname, 'version-no-package') 9 | 10 | test('setup', function (t) { 11 | setup() 12 | t.end() 13 | }) 14 | 15 | test('npm version in a prefix with no package.json', function (t) { 16 | setup() 17 | common.npm( 18 | ['version', '--json', '--prefix', pkg], 19 | { cwd: pkg }, 20 | function (er, code, stdout, stderr) { 21 | t.ifError(er, "npm version doesn't care that there's no package.json") 22 | t.notOk(code, 'npm version ran without barfing') 23 | t.ok(stdout, 'got version output') 24 | t.notOk(stderr, 'no error output') 25 | t.doesNotThrow(function () { 26 | var metadata = JSON.parse(stdout) 27 | t.equal(metadata.node, process.versions.node, 'node versions match') 28 | }, 'able to reconstitute version object from stdout') 29 | t.end() 30 | } 31 | ) 32 | }) 33 | 34 | test('cleanup', function (t) { 35 | process.chdir(osenv.tmpdir()) 36 | 37 | rimraf.sync(pkg) 38 | t.end() 39 | }) 40 | 41 | function setup () { 42 | mkdirp.sync(pkg) 43 | process.chdir(pkg) 44 | } 45 | -------------------------------------------------------------------------------- /lib/stars.js: -------------------------------------------------------------------------------- 1 | module.exports = stars 2 | 3 | stars.usage = 'npm stars []' 4 | 5 | var npm = require('./npm.js') 6 | var log = require('npmlog') 7 | var mapToRegistry = require('./utils/map-to-registry.js') 8 | var output = require('./utils/output.js') 9 | 10 | function stars (args, cb) { 11 | npm.commands.whoami([], true, function (er, username) { 12 | var name = args.length === 1 ? args[0] : username 13 | 14 | if (er) { 15 | if (er.code === 'ENEEDAUTH' && !name) { 16 | var needAuth = new Error("'npm stars' on your own user account requires auth") 17 | needAuth.code = 'ENEEDAUTH' 18 | return cb(needAuth) 19 | } 20 | 21 | if (er.code !== 'ENEEDAUTH') return cb(er) 22 | } 23 | 24 | mapToRegistry('', npm.config, function (er, uri, auth) { 25 | if (er) return cb(er) 26 | 27 | var params = { 28 | username: name, 29 | auth: auth 30 | } 31 | npm.registry.stars(uri, params, showstars) 32 | }) 33 | }) 34 | 35 | function showstars (er, data) { 36 | if (er) return cb(er) 37 | 38 | if (data.rows.length === 0) { 39 | log.warn('stars', 'user has not starred any packages.') 40 | } else { 41 | data.rows.forEach(function (a) { 42 | output(a.value) 43 | }) 44 | } 45 | cb() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /doc/cli/npm-logout.md: -------------------------------------------------------------------------------- 1 | npm-logout(1) -- Log out of the registry 2 | ======================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm logout [--registry=] [--scope=<@scope>] 7 | 8 | ## DESCRIPTION 9 | 10 | When logged into a registry that supports token-based authentication, tell the 11 | server to end this token's session. This will invalidate the token everywhere 12 | you're using it, not just for the current environment. 13 | 14 | When logged into a legacy registry that uses username and password authentication, this will 15 | clear the credentials in your user configuration. In this case, it will _only_ affect 16 | the current environment. 17 | 18 | If `--scope` is provided, this will find the credentials for the registry 19 | connected to that scope, if set. 20 | 21 | ## CONFIGURATION 22 | 23 | ### registry 24 | 25 | Default: https://registry.npmjs.org/ 26 | 27 | The base URL of the npm package registry. If `scope` is also specified, 28 | it takes precedence. 29 | 30 | ### scope 31 | 32 | Default: The scope of your current project, if any, otherwise none. 33 | 34 | If specified, you will be logged out of the specified scope. See `npm-scope(7)`. 35 | 36 | npm logout --scope=@myco 37 | 38 | ## SEE ALSO 39 | 40 | * npm-adduser(1) 41 | * npm-registry(7) 42 | * npm-config(1) 43 | * npm-config(7) 44 | * npmrc(5) 45 | * npm-whoami(1) 46 | -------------------------------------------------------------------------------- /test/tap/nerf-dart.js: -------------------------------------------------------------------------------- 1 | // taken from https://raw.githubusercontent.com/indexzero/npm/bd3cad01fbd3ab481d2f5da441b9eead16029123/test/tap/config-nerf-dart.js 2 | // originally written by Charlie Robbins, https://github.com/indexzero 3 | var test = require('tap').test 4 | var toNerfDart = require('../../lib/config/nerf-dart.js') 5 | 6 | function validNerfDart (uri, valid) { 7 | if (!valid) valid = '//registry.npmjs.org/' 8 | test(uri, function (t) { 9 | t.equal(toNerfDart(uri), valid) 10 | t.end() 11 | }) 12 | } 13 | 14 | validNerfDart('http://registry.npmjs.org') 15 | validNerfDart('http://registry.npmjs.org/some-package') 16 | validNerfDart('http://registry.npmjs.org/some-package?write=true') 17 | validNerfDart('http://user:pass@registry.npmjs.org/some-package?write=true') 18 | validNerfDart('http://registry.npmjs.org/#random-hash') 19 | validNerfDart('http://registry.npmjs.org/some-package#random-hash') 20 | 21 | validNerfDart( 22 | 'http://relative.couchapp.npm/design/-/rewrite/', 23 | '//relative.couchapp.npm/design/-/rewrite/' 24 | ) 25 | validNerfDart( 26 | 'http://relative.couchapp.npm:8080/design/-/rewrite/', 27 | '//relative.couchapp.npm:8080/design/-/rewrite/' 28 | ) 29 | validNerfDart( 30 | 'http://relative.couchapp.npm:8080/design/-/rewrite/some-package', 31 | '//relative.couchapp.npm:8080/design/-/rewrite/' 32 | ) 33 | -------------------------------------------------------------------------------- /test/tap/unsupported.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var unsupported = require('../../lib/utils/unsupported.js') 4 | 5 | var versions = [ 6 | // broken unsupported 7 | ['v0.1.103', true, true], 8 | ['v0.2.0', true, true], 9 | ['v0.3.5', true, true], 10 | ['v0.4.7', true, true], 11 | ['v0.5.3', true, true], 12 | ['v0.6.17', true, true], 13 | ['v0.7.8', true, true], 14 | ['v0.8.28', false, true], 15 | ['v0.9.6', false, true], 16 | ['v0.10.48', false, true], 17 | ['v0.11.16', false, true], 18 | ['v0.12.9', false, true], 19 | ['v1.0.1', false, true], 20 | ['v1.6.0', false, true], 21 | ['v2.3.1', false, true], 22 | ['v3.0.0', false, true], 23 | ['v4.5.0', false, false], 24 | ['v5.7.1', false, false], 25 | ['v6.8.1', false, false], 26 | ['v7.0.0-beta23', false, false], 27 | ['v7.2.3', false, false] 28 | ] 29 | 30 | test('versions', function (t) { 31 | t.plan(versions.length * 2) 32 | versions.forEach(function (verinfo) { 33 | var version = verinfo[0] 34 | var broken = verinfo[1] 35 | var unsupp = verinfo[2] 36 | var nodejs = unsupported.checkVersion(version) 37 | t.is(nodejs.broken, broken, version + ' ' + (broken ? '' : 'not ') + 'broken') 38 | t.is(nodejs.unsupported, unsupp, version + ' ' + (unsupp ? 'unsupported' : 'supported')) 39 | }) 40 | t.done() 41 | }) 42 | -------------------------------------------------------------------------------- /test/tap/lifecycle.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var npm = require('../../') 3 | var lifecycle = require('../../lib/utils/lifecycle') 4 | 5 | test('lifecycle: make env correctly', function (t) { 6 | npm.load({enteente: Infinity}, function () { 7 | var env = lifecycle.makeEnv({}, null, process.env) 8 | 9 | t.equal('Infinity', env.npm_config_enteente) 10 | t.end() 11 | }) 12 | }) 13 | 14 | test('lifecycle : accepts wd for package that matches project\'s name', function (t) { 15 | npm.load({}, function () { 16 | var wd = '/opt/my-time/node_modules/time' 17 | var pkg = {name: 'time'} 18 | 19 | t.equal(lifecycle._incorrectWorkingDirectory(wd, pkg), false) 20 | t.end() 21 | }) 22 | }) 23 | 24 | test('lifecycle : accepts wd for package that doesn\'t match project\'s name', function (t) { 25 | npm.load({}, function () { 26 | var wd = '/opt/my-project/node_modules/time' 27 | var pkg = {name: 'time'} 28 | 29 | t.equal(lifecycle._incorrectWorkingDirectory(wd, pkg), false) 30 | t.end() 31 | }) 32 | }) 33 | 34 | test('lifecycle : rejects wd for ', function (t) { 35 | npm.load({}, function () { 36 | var wd = '/opt/my-time/node_modules/time/invalid' 37 | var pkg = { 38 | name: 'time' 39 | } 40 | 41 | t.equal(lifecycle._incorrectWorkingDirectory(wd, pkg), true) 42 | t.end() 43 | }) 44 | }) 45 | -------------------------------------------------------------------------------- /lib/search/package-filter.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = filter 4 | function filter (data, include, exclude, opts) { 5 | return typeof data === 'object' && 6 | filterWords(data, include, exclude, opts) 7 | } 8 | 9 | function getWords (data, opts) { 10 | return [ data.name ] 11 | .concat((opts && opts.description) ? data.description : []) 12 | .concat((data.maintainers || []).map(function (m) { 13 | return '=' + m.name 14 | })) 15 | .concat(data.versions && data.versions.length && data.url && ('<' + data.url + '>')) 16 | .concat(data.keywords || []) 17 | .map(function (f) { return f && f.trim && f.trim() }) 18 | .filter(function (f) { return f }) 19 | .join(' ') 20 | .toLowerCase() 21 | } 22 | 23 | function filterWords (data, include, exclude, opts) { 24 | var words = getWords(data, opts) 25 | for (var i = 0, l = include.length; i < l; i++) { 26 | if (!match(words, include[i])) return false 27 | } 28 | for (i = 0, l = exclude.length; i < l; i++) { 29 | if (match(words, exclude[i])) return false 30 | } 31 | return true 32 | } 33 | 34 | function match (words, pattern) { 35 | if (pattern.charAt(0) === '/') { 36 | pattern = pattern.replace(/\/$/, '') 37 | pattern = new RegExp(pattern.substr(1, pattern.length - 1)) 38 | return words.match(pattern) 39 | } 40 | return words.indexOf(pattern) !== -1 41 | } 42 | -------------------------------------------------------------------------------- /test/tap/run-script-filter-private.js: -------------------------------------------------------------------------------- 1 | var fs = require('graceful-fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var rimraf = require('rimraf') 6 | var test = require('tap').test 7 | 8 | var common = require('../common-tap') 9 | 10 | var pkg = path.resolve(__dirname, 'run-script-filter-private') 11 | 12 | var opts = { cwd: pkg } 13 | 14 | var json = { 15 | name: 'run-script-filter-private', 16 | version: '1.2.3' 17 | } 18 | 19 | var npmrc = '//blah.com:_harsh=realms\n' 20 | 21 | test('setup', function (t) { 22 | cleanup() 23 | mkdirp.sync(pkg) 24 | fs.writeFileSync( 25 | path.resolve(pkg, 'package.json'), 26 | JSON.stringify(json, null, 2) + '\n' 27 | ) 28 | fs.writeFileSync( 29 | path.resolve(pkg, '.npmrc'), 30 | npmrc 31 | ) 32 | t.end() 33 | }) 34 | 35 | test('npm run-script env', function (t) { 36 | common.npm(['run-script', 'env'], opts, function (er, code, stdout, stderr) { 37 | t.ifError(er, 'using default env script') 38 | t.notOk(stderr, 'should not generate errors') 39 | t.ok(stdout.indexOf('npm_config_init_version') > 0, 'expected values in var list') 40 | t.notMatch(stdout, /harsh/, 'unexpected config not there') 41 | t.end() 42 | }) 43 | }) 44 | 45 | test('cleanup', function (t) { 46 | cleanup() 47 | t.end() 48 | }) 49 | 50 | function cleanup () { 51 | rimraf.sync(pkg) 52 | } 53 | -------------------------------------------------------------------------------- /lib/star.js: -------------------------------------------------------------------------------- 1 | module.exports = star 2 | 3 | var npm = require('./npm.js') 4 | var log = require('npmlog') 5 | var asyncMap = require('slide').asyncMap 6 | var mapToRegistry = require('./utils/map-to-registry.js') 7 | var usage = require('./utils/usage') 8 | var output = require('./utils/output.js') 9 | 10 | star.usage = usage( 11 | 'star', 12 | 'npm star [...]\n' + 13 | 'npm unstar [...]' 14 | ) 15 | 16 | star.completion = function (opts, cb) { 17 | // FIXME: there used to be registry completion here, but it stopped making 18 | // sense somewhere around 50,000 packages on the registry 19 | cb() 20 | } 21 | 22 | function star (args, cb) { 23 | if (!args.length) return cb(star.usage) 24 | var s = npm.config.get('unicode') ? '\u2605 ' : '(*)' 25 | var u = npm.config.get('unicode') ? '\u2606 ' : '( )' 26 | var using = !(npm.command.match(/^un/)) 27 | if (!using) s = u 28 | asyncMap(args, function (pkg, cb) { 29 | mapToRegistry(pkg, npm.config, function (er, uri, auth) { 30 | if (er) return cb(er) 31 | 32 | var params = { 33 | starred: using, 34 | auth: auth 35 | } 36 | npm.registry.star(uri, params, function (er, data, raw, req) { 37 | if (!er) { 38 | output(s + ' ' + pkg) 39 | log.verbose('star', data) 40 | } 41 | cb(er, data, raw, req) 42 | }) 43 | }) 44 | }, cb) 45 | } 46 | -------------------------------------------------------------------------------- /lib/utils/completion/installed-deep.js: -------------------------------------------------------------------------------- 1 | module.exports = installedDeep 2 | 3 | var npm = require('../../npm.js') 4 | var readInstalled = require('read-installed') 5 | 6 | function installedDeep (opts, cb) { 7 | var local 8 | var global 9 | var depth = npm.config.get('depth') 10 | var opt = { depth: depth, dev: true } 11 | 12 | if (npm.config.get('global')) { 13 | local = [] 14 | next() 15 | } else { 16 | readInstalled(npm.prefix, opt, function (er, data) { 17 | local = getNames(data || {}) 18 | next() 19 | }) 20 | } 21 | 22 | readInstalled(npm.config.get('prefix'), opt, function (er, data) { 23 | global = getNames(data || {}) 24 | next() 25 | }) 26 | 27 | function getNames_ (d, n) { 28 | if (d.realName && n) { 29 | if (n[d.realName]) return n 30 | n[d.realName] = true 31 | } 32 | if (!n) n = {} 33 | Object.keys(d.dependencies || {}).forEach(function (dep) { 34 | getNames_(d.dependencies[dep], n) 35 | }) 36 | return n 37 | } 38 | function getNames (d) { 39 | return Object.keys(getNames_(d)) 40 | } 41 | 42 | function next () { 43 | if (!local || !global) return 44 | if (!npm.config.get('global')) { 45 | global = global.map(function (g) { 46 | return [g, '-g'] 47 | }) 48 | } 49 | var names = local.concat(global) 50 | return cb(null, names) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/utils/unsupported.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var semver = require('semver') 3 | var supportedNode = '>= 4' 4 | var knownBroken = '>=0.1 <=0.7' 5 | 6 | var checkVersion = exports.checkVersion = function (version) { 7 | var versionNoPrerelease = version.replace(/-.*$/, '') 8 | return { 9 | broken: semver.satisfies(versionNoPrerelease, knownBroken), 10 | unsupported: !semver.satisfies(versionNoPrerelease, supportedNode) 11 | } 12 | } 13 | 14 | exports.checkForBrokenNode = function () { 15 | var nodejs = checkVersion(process.version) 16 | if (nodejs.broken) { 17 | console.error('ERROR: npm is known not to run on Node.js ' + process.version) 18 | console.error("You'll need to upgrade to a newer version in order to use this") 19 | console.error('version of npm. You can find the latest version at https://nodejs.org/') 20 | process.exit(1) 21 | } 22 | } 23 | 24 | exports.checkForUnsupportedNode = function () { 25 | var nodejs = checkVersion(process.version) 26 | if (nodejs.unsupported) { 27 | var log = require('npmlog') 28 | log.warn('npm', 'npm does not support Node.js ' + process.version) 29 | log.warn('npm', 'You should probably upgrade to a newer version of node as we') 30 | log.warn('npm', "can't make any promises that npm will work with this version.") 31 | log.warn('npm', 'You can find the latest version at https://nodejs.org/') 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/network/git-cache-locking.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var common = require('../common-tap') 3 | var path = require('path') 4 | var rimraf = require('rimraf') 5 | var mkdirp = require('mkdirp') 6 | var pkg = path.resolve(__dirname, 'git-cache-locking') 7 | var tmp = path.join(pkg, 'tmp') 8 | var cache = path.join(pkg, 'cache') 9 | var shallowClone = Object.assign || require('util')._extend 10 | 11 | test('setup', function (t) { 12 | rimraf.sync(pkg) 13 | mkdirp.sync(path.resolve(pkg, 'node_modules')) 14 | t.end() 15 | }) 16 | 17 | test('git-cache-locking: install a git dependency', function (t) { 18 | // disable git integration tests on Travis. 19 | if (process.env.TRAVIS) return t.end() 20 | 21 | var gitEnv = shallowClone({}, process.env) 22 | gitEnv.npm_config_cache = cache 23 | gitEnv.npm_config_tmp = tmp 24 | gitEnv.npm_config_prefix = pkg 25 | gitEnv.npm_config_global = 'false' 26 | 27 | // package c depends on a.git#master and b.git#master 28 | // package b depends on a.git#master 29 | common.npm([ 30 | 'install', 31 | 'git://github.com/nigelzor/npm-4503-c.git' 32 | ], { 33 | cwd: pkg, 34 | env: gitEnv 35 | }, function (err, code, stdout, stderr) { 36 | if (err) throw err 37 | t.equal(0, code, 'npm install should succeed') 38 | t.end() 39 | }) 40 | }) 41 | 42 | test('cleanup', function (t) { 43 | rimraf.sync(pkg) 44 | t.end() 45 | }) 46 | -------------------------------------------------------------------------------- /test/need-npm5-update/outdated-notarget.js: -------------------------------------------------------------------------------- 1 | // Fixes Issue #1770 2 | var common = require('../common-tap.js') 3 | var test = require('tap').test 4 | var npm = require('../../') 5 | var osenv = require('osenv') 6 | var path = require('path') 7 | var fs = require('fs') 8 | var rimraf = require('rimraf') 9 | var mkdirp = require('mkdirp') 10 | var pkg = path.resolve(__dirname, 'outdated-notarget') 11 | var cache = path.resolve(pkg, 'cache') 12 | var mr = require('npm-registry-mock') 13 | 14 | test('outdated-target: if no viable version is found, show error', function (t) { 15 | t.plan(1) 16 | setup() 17 | mr({ port: common.port }, function (er, s) { 18 | npm.load({ cache: cache, registry: common.registry }, function () { 19 | npm.commands.update(function (er) { 20 | t.equal(er.code, 'ETARGET') 21 | s.close() 22 | t.end() 23 | }) 24 | }) 25 | }) 26 | }) 27 | 28 | test('cleanup', function (t) { 29 | process.chdir(osenv.tmpdir()) 30 | rimraf.sync(pkg) 31 | t.end() 32 | }) 33 | 34 | function setup () { 35 | mkdirp.sync(pkg) 36 | mkdirp.sync(cache) 37 | fs.writeFileSync(path.resolve(pkg, 'package.json'), JSON.stringify({ 38 | author: 'Evan Lucas', 39 | name: 'outdated-notarget', 40 | version: '0.0.0', 41 | description: 'Test for outdated-target', 42 | dependencies: { 43 | underscore: '~199.7.1' 44 | } 45 | }), 'utf8') 46 | process.chdir(pkg) 47 | } 48 | -------------------------------------------------------------------------------- /test/tap/install-order.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var sortActions = require('../../lib/install/diff-trees.js').sortActions 4 | var top = { 5 | location: '/', 6 | package: {}, 7 | requiredBy: [], 8 | requires: [a, b], 9 | isTop: true 10 | } 11 | var a = { 12 | location: '/a', 13 | package: {}, 14 | requiredBy: [], 15 | requires: [c], 16 | isTop: false, 17 | userRequired: false, 18 | existing: false, 19 | parent: top 20 | } 21 | var b = { 22 | location: '/b', 23 | package: {}, 24 | requiredBy: [], 25 | requires: [c], 26 | isTop: false, 27 | userRequired: false, 28 | existing: false, 29 | parent: top 30 | } 31 | var c = { 32 | location: '/c', 33 | package: {}, 34 | requiredBy: [a, b], 35 | requires: [], 36 | isTop: false, 37 | userRequired: false, 38 | existing: false, 39 | parent: top 40 | } 41 | 42 | test('install-order when installing deps', function (t) { 43 | var plain = [ 44 | ['add', a], 45 | ['add', b], 46 | ['add', c]] 47 | var sorted = [ 48 | ['add', c], 49 | ['add', a], 50 | ['add', b]] 51 | t.isDeeply(sortActions(plain), sorted) 52 | t.end() 53 | }) 54 | 55 | test('install-order when not installing deps', function (t) { 56 | var plain = [ 57 | ['add', a], 58 | ['add', b]] 59 | var sorted = [ 60 | ['add', a], 61 | ['add', b]] 62 | t.isDeeply(sortActions(plain), sorted) 63 | t.end() 64 | }) 65 | -------------------------------------------------------------------------------- /doc/cli/npm-unpublish.md: -------------------------------------------------------------------------------- 1 | npm-unpublish(1) -- Remove a package from the registry 2 | ====================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm unpublish [<@scope>/][@] 7 | 8 | ## WARNING 9 | 10 | **It is generally considered bad behavior to remove versions of a library 11 | that others are depending on!** 12 | 13 | Consider using the `deprecate` command 14 | instead, if your intent is to encourage users to upgrade. 15 | 16 | There is plenty of room on the registry. 17 | 18 | ## DESCRIPTION 19 | 20 | This removes a package version from the registry, deleting its 21 | entry and removing the tarball. 22 | 23 | If no version is specified, or if all versions are removed then 24 | the root package entry is removed from the registry entirely. 25 | 26 | Even if a package version is unpublished, that specific name and 27 | version combination can never be reused. In order to publish the 28 | package again, a new version number must be used. 29 | 30 | With the default registry (`registry.npmjs.org`), unpublish is 31 | only allowed with versions published in the last 24 hours. If you 32 | are trying to unpublish a version published longer ago than that, 33 | contact support@npmjs.com. 34 | 35 | The scope is optional and follows the usual rules for `npm-scope(7)`. 36 | 37 | ## SEE ALSO 38 | 39 | * npm-deprecate(1) 40 | * npm-publish(1) 41 | * npm-registry(7) 42 | * npm-adduser(1) 43 | * npm-owner(1) 44 | -------------------------------------------------------------------------------- /lib/install/action/refresh-package-json.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const Bluebird = require('bluebird') 4 | const readJson = Bluebird.promisify(require('read-package-json')) 5 | const updatePackageJson = Bluebird.promisify(require('../update-package-json')) 6 | const getRequested = require('../get-requested.js') 7 | 8 | module.exports = function (staging, pkg, log) { 9 | log.silly('refresh-package-json', pkg.realpath) 10 | 11 | return readJson(path.join(pkg.path, 'package.json'), false).then((metadata) => { 12 | Object.keys(pkg.package).forEach(function (key) { 13 | if (!isEmpty(pkg.package[key])) { 14 | metadata[key] = pkg.package[key] 15 | } 16 | }) 17 | if (metadata._resolved == null && pkg.fakeChild) { 18 | metadata._resolved = pkg.fakeChild.resolved 19 | } 20 | // These two sneak in and it's awful 21 | delete metadata.readme 22 | delete metadata.readmeFilename 23 | 24 | pkg.package = metadata 25 | }).catch(() => 'ignore').then(() => { 26 | const requested = pkg.package._requested || getRequested(pkg) 27 | if (requested.type !== 'directory') { 28 | return updatePackageJson(pkg, pkg.path) 29 | } 30 | }) 31 | } 32 | 33 | function isEmpty (value) { 34 | if (value == null) return true 35 | if (Array.isArray(value)) return !value.length 36 | if (typeof value === 'object') return !Object.keys(value).length 37 | return false 38 | } 39 | 40 | -------------------------------------------------------------------------------- /lib/utils/git.js: -------------------------------------------------------------------------------- 1 | // handle some git configuration for windows 2 | 3 | exports.spawn = spawnGit 4 | exports.chainableExec = chainableExec 5 | exports.whichAndExec = whichAndExec 6 | 7 | var exec = require('child_process').execFile 8 | var spawn = require('./spawn') 9 | var npm = require('../npm.js') 10 | var which = require('which') 11 | var git = npm.config.get('git') 12 | var assert = require('assert') 13 | var log = require('npmlog') 14 | var noProgressTillDone = require('./no-progress-while-running.js').tillDone 15 | 16 | function prefixGitArgs () { 17 | return process.platform === 'win32' ? ['-c', 'core.longpaths=true'] : [] 18 | } 19 | 20 | function execGit (args, options, cb) { 21 | log.info('git', args) 22 | var fullArgs = prefixGitArgs().concat(args || []) 23 | return exec(git, fullArgs, options, noProgressTillDone(cb)) 24 | } 25 | 26 | function spawnGit (args, options) { 27 | log.info('git', args) 28 | return spawn(git, prefixGitArgs().concat(args || []), options) 29 | } 30 | 31 | function chainableExec () { 32 | var args = Array.prototype.slice.call(arguments) 33 | return [execGit].concat(args) 34 | } 35 | 36 | function whichAndExec (args, options, cb) { 37 | assert.equal(typeof cb, 'function', 'no callback provided') 38 | // check for git 39 | which(git, function (err) { 40 | if (err) { 41 | err.code = 'ENOGIT' 42 | return cb(err) 43 | } 44 | 45 | execGit(args, options, cb) 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /lib/config/set-credentials-by-uri.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | 3 | var toNerfDart = require('./nerf-dart.js') 4 | 5 | module.exports = setCredentialsByURI 6 | 7 | function setCredentialsByURI (uri, c) { 8 | assert(uri && typeof uri === 'string', 'registry URL is required') 9 | assert(c && typeof c === 'object', 'credentials are required') 10 | 11 | var nerfed = toNerfDart(uri) 12 | 13 | if (c.token) { 14 | this.set(nerfed + ':_authToken', c.token, 'user') 15 | this.del(nerfed + ':_password', 'user') 16 | this.del(nerfed + ':username', 'user') 17 | this.del(nerfed + ':email', 'user') 18 | this.del(nerfed + ':always-auth', 'user') 19 | } else if (c.username || c.password || c.email) { 20 | assert(c.username, 'must include username') 21 | assert(c.password, 'must include password') 22 | assert(c.email, 'must include email address') 23 | 24 | this.del(nerfed + ':_authToken', 'user') 25 | 26 | var encoded = new Buffer(c.password, 'utf8').toString('base64') 27 | this.set(nerfed + ':_password', encoded, 'user') 28 | this.set(nerfed + ':username', c.username, 'user') 29 | this.set(nerfed + ':email', c.email, 'user') 30 | 31 | if (c.alwaysAuth !== undefined) { 32 | this.set(nerfed + ':always-auth', c.alwaysAuth, 'user') 33 | } else { 34 | this.del(nerfed + ':always-auth', 'user') 35 | } 36 | } else { 37 | throw new Error('No credentials to set.') 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/init.js: -------------------------------------------------------------------------------- 1 | // initialize a package.json file 2 | 3 | module.exports = init 4 | 5 | var log = require('npmlog') 6 | var npm = require('./npm.js') 7 | var initJson = require('init-package-json') 8 | var output = require('./utils/output.js') 9 | var noProgressTillDone = require('./utils/no-progress-while-running').tillDone 10 | 11 | init.usage = 'npm init [--force|-f|--yes|-y]' 12 | 13 | function init (args, cb) { 14 | var dir = process.cwd() 15 | log.pause() 16 | var initFile = npm.config.get('init-module') 17 | if (!initJson.yes(npm.config)) { 18 | output([ 19 | 'This utility will walk you through creating a package.json file.', 20 | 'It only covers the most common items, and tries to guess sensible defaults.', 21 | '', 22 | 'See `npm help json` for definitive documentation on these fields', 23 | 'and exactly what they do.', 24 | '', 25 | 'Use `npm install ` afterwards to install a package and', 26 | 'save it as a dependency in the package.json file.', 27 | '', 28 | 'Press ^C at any time to quit.' 29 | ].join('\n')) 30 | } 31 | initJson(dir, initFile, npm.config, noProgressTillDone(function (er, data) { 32 | log.resume() 33 | log.silly('package data', data) 34 | if (er && er.message === 'canceled') { 35 | log.warn('init', 'canceled') 36 | return cb(null, data) 37 | } 38 | log.info('init', 'written successfully') 39 | cb(er, data) 40 | })) 41 | } 42 | -------------------------------------------------------------------------------- /test/tap/nested-extraneous.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | var mkdirp = require('mkdirp') 4 | var fs = require('fs') 5 | var rimraf = require('rimraf') 6 | var path = require('path') 7 | 8 | var pkg = path.resolve(__dirname, 'nested-extraneous') 9 | var pj = { 10 | name: 'nested-extraneous', 11 | version: '1.2.3' 12 | } 13 | 14 | var dep = path.resolve(pkg, 'node_modules', 'dep') 15 | var deppj = { 16 | name: 'nested-extraneous-dep', 17 | version: '1.2.3', 18 | dependencies: { 19 | 'nested-extra-depdep': '*' 20 | } 21 | } 22 | 23 | var depdep = path.resolve(dep, 'node_modules', 'depdep') 24 | var depdeppj = { 25 | name: 'nested-extra-depdep', 26 | version: '1.2.3' 27 | } 28 | 29 | test('setup', function (t) { 30 | rimraf.sync(pkg) 31 | mkdirp.sync(depdep) 32 | fs.writeFileSync(path.resolve(pkg, 'package.json'), JSON.stringify(pj)) 33 | fs.writeFileSync(path.resolve(dep, 'package.json'), JSON.stringify(deppj)) 34 | fs.writeFileSync(path.resolve(depdep, 'package.json'), JSON.stringify(depdeppj)) 35 | t.end() 36 | }) 37 | 38 | test('test', function (t) { 39 | common.npm(['ls'], { 40 | cwd: pkg 41 | }, function (er, code, sto, ste) { 42 | if (er) throw er 43 | t.notEqual(code, 0) 44 | t.notSimilar(ste, /depdep/) 45 | t.notSimilar(sto, /depdep/) 46 | t.end() 47 | }) 48 | }) 49 | 50 | test('clean', function (t) { 51 | rimraf.sync(pkg) 52 | t.end() 53 | }) 54 | -------------------------------------------------------------------------------- /test/tap/onload.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var test = require('tap').test 3 | var rimraf = require('rimraf') 4 | var common = require('../common-tap.js') 5 | var opts = { cwd: __dirname } 6 | var binDir = '../../node_modules/.bin' 7 | var fixture = path.resolve(__dirname, binDir) 8 | var onload = path.resolve(__dirname, '../fixtures/onload.js') 9 | 10 | test('setup', function (t) { 11 | rimraf.sync(path.join(__dirname, 'node_modules')) 12 | t.end() 13 | }) 14 | 15 | test('npm bin with valid onload script', function (t) { 16 | var args = ['--onload', onload, 'bin'] 17 | common.npm(args, opts, function (err, code, stdout, stderr) { 18 | t.ifError(err, 'bin ran without issue') 19 | t.equal(stderr.trim(), 'called onload') 20 | t.equal(code, 0, 'exit ok') 21 | t.equal(stdout, fixture + '\n') 22 | t.end() 23 | }) 24 | }) 25 | 26 | test('npm bin with invalid onload script', function (t) { 27 | var onloadScript = onload + 'jsfd' 28 | var args = ['--onload', onloadScript, '--loglevel=warn', 'bin'] 29 | common.npm(args, opts, function (err, code, stdout, stderr) { 30 | t.ifError(err, 'bin ran without issue') 31 | t.match(stderr, /npm WARN onload-script failed to require onload script/) 32 | t.match(stderr, /MODULE_NOT_FOUND/) 33 | t.notEqual(stderr.indexOf(onloadScript), -1) 34 | t.equal(code, 0, 'exit ok') 35 | var res = path.resolve(stdout) 36 | t.equal(res, fixture + '\n') 37 | t.end() 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /doc/cli/npm-uninstall.md: -------------------------------------------------------------------------------- 1 | npm-uninstall(1) -- Remove a package 2 | ============================= 3 | 4 | ## SYNOPSIS 5 | 6 | npm uninstall [<@scope>/][@]... [-S|--save|-D|--save-dev|-O|--save-optional] 7 | 8 | aliases: remove, rm, r, un, unlink 9 | 10 | ## DESCRIPTION 11 | 12 | This uninstalls a package, completely removing everything npm installed 13 | on its behalf. 14 | 15 | Example: 16 | 17 | npm uninstall sax 18 | 19 | In global mode (ie, with `-g` or `--global` appended to the command), 20 | it uninstalls the current package context as a global package. 21 | 22 | `npm uninstall` takes 3 exclusive, optional flags which save or update 23 | the package version in your main package.json: 24 | 25 | * `-S, --save`: Package will be removed from your `dependencies`. 26 | 27 | * `-D, --save-dev`: Package will be removed from your `devDependencies`. 28 | 29 | * `-O, --save-optional`: Package will be removed from your `optionalDependencies`. 30 | 31 | Further, if you have an `npm-shrinkwrap.json` then it will be updated as 32 | well. 33 | 34 | Scope is optional and follows the usual rules for `npm-scope(7)`. 35 | 36 | Examples: 37 | 38 | npm uninstall sax --save 39 | npm uninstall @myorg/privatepackage --save 40 | npm uninstall node-tap --save-dev 41 | npm uninstall dtrace-provider --save-optional 42 | 43 | ## SEE ALSO 44 | 45 | * npm-prune(1) 46 | * npm-install(1) 47 | * npm-folders(5) 48 | * npm-config(1) 49 | * npm-config(7) 50 | * npmrc(5) 51 | -------------------------------------------------------------------------------- /test/tap/config-new-cafile.js: -------------------------------------------------------------------------------- 1 | require('./00-config-setup.js') 2 | 3 | var path = require('path') 4 | var fs = require('graceful-fs') 5 | var test = require('tap').test 6 | var mkdirp = require('mkdirp') 7 | var rimraf = require('rimraf') 8 | var osenv = require('osenv') 9 | var npmconf = require('../../lib/config/core.js') 10 | 11 | var dir = path.resolve(__dirname, 'config-new-cafile') 12 | var beep = path.resolve(dir, 'beep.pem') 13 | 14 | test('setup', function (t) { 15 | bootstrap() 16 | t.end() 17 | }) 18 | 19 | test('can set new cafile when old is gone', function (t) { 20 | t.plan(5) 21 | npmconf.load(function (error, conf) { 22 | npmconf.loaded = false 23 | t.ifError(error) 24 | conf.set('cafile', beep, 'user') 25 | conf.save('user', function (error) { 26 | t.ifError(error) 27 | t.equal(conf.get('cafile'), beep) 28 | rimraf.sync(beep) 29 | npmconf.load(function (error, conf) { 30 | if (error) { 31 | throw error 32 | } 33 | t.equal(conf.get('cafile'), beep) 34 | conf.del('cafile') 35 | conf.save('user', function (error) { 36 | t.ifError(error) 37 | }) 38 | }) 39 | }) 40 | }) 41 | }) 42 | 43 | test('cleanup', function (t) { 44 | cleanup() 45 | t.end() 46 | }) 47 | 48 | function bootstrap () { 49 | mkdirp.sync(dir) 50 | fs.writeFileSync(beep, '') 51 | } 52 | 53 | function cleanup () { 54 | process.chdir(osenv.tmpdir()) 55 | rimraf.sync(dir) 56 | } 57 | -------------------------------------------------------------------------------- /test/tap/bundled-no-add-to-move.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var Node = require('../../lib/install/node.js').create 4 | var diffTrees = require('../../lib/install/diff-trees.js')._diffTrees 5 | var sortActions = require('../../lib/install/diff-trees.js').sortActions 6 | 7 | var oldTree = Node({ 8 | path: '/', 9 | location: '/', 10 | children: [ 11 | Node({ 12 | package: {name: 'one', version: '1.0.0'}, 13 | path: '/node_modules/one', 14 | location: '/one' 15 | }) 16 | ] 17 | }) 18 | oldTree.children[0].requiredBy.push(oldTree) 19 | 20 | var newTree = Node({ 21 | path: '/', 22 | location: '/', 23 | children: [ 24 | Node({ 25 | package: {name: 'abc', version: '1.0.0'}, 26 | path: '/node_modules/abc', 27 | location: '/abc', 28 | children: [ 29 | Node({ 30 | package: {name: 'one', version: '1.0.0'}, 31 | fromBundle: true, 32 | path: '/node_modules/abc/node_modules/one', 33 | location: '/abc/one' 34 | }) 35 | ] 36 | }) 37 | ] 38 | }) 39 | newTree.children[0].requiredBy.push(newTree) 40 | newTree.children[0].children[0].requiredBy.push(newTree.children[0]) 41 | 42 | test('test', function (t) { 43 | var differences = sortActions(diffTrees(oldTree, newTree)).map(function (diff) { return diff[0] + diff[1].location }) 44 | t.isDeeply(differences, ['add/abc/one', 'remove/one', 'add/abc'], 'bundled add/remove stays add/remove') 45 | t.end() 46 | }) 47 | -------------------------------------------------------------------------------- /test/tap/404-private-registry.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var path = require('path') 3 | var mkdirp = require('mkdirp') 4 | var rimraf = require('rimraf') 5 | var common = require('../common-tap.js') 6 | var mr = require('npm-registry-mock') 7 | var server 8 | 9 | var packageName = path.basename(__filename, '.js') 10 | var testdir = path.join(__dirname, packageName) 11 | 12 | function setup () { 13 | cleanup() 14 | mkdirp.sync(testdir) 15 | } 16 | 17 | function cleanup () { 18 | rimraf.sync(testdir) 19 | } 20 | 21 | test('setup', function (t) { 22 | setup() 23 | mr({port: common.port, throwOnUnmatched: true}, function (err, s) { 24 | t.ifError(err, 'registry mocked successfully') 25 | server = s 26 | t.end() 27 | }) 28 | }) 29 | 30 | test('package names not mangled on error with non-root registry', function (t) { 31 | server.get('/' + packageName).reply(404, {}) 32 | common.npm( 33 | [ 34 | '--registry=' + common.registry, 35 | '--cache=' + testdir, 36 | 'cache', 37 | 'add', 38 | packageName + '@*' 39 | ], 40 | {}, 41 | function (er, code, stdout, stderr) { 42 | t.ifError(er, 'correctly handled 404') 43 | t.equal(code, 1, 'exited with error') 44 | t.match(stderr, packageName, 'should have package name in error') 45 | server.done() 46 | t.end() 47 | } 48 | ) 49 | }) 50 | 51 | test('cleanup', function (t) { 52 | server.close() 53 | cleanup() 54 | t.pass('cleaned up') 55 | t.end() 56 | }) 57 | -------------------------------------------------------------------------------- /lib/adduser.js: -------------------------------------------------------------------------------- 1 | module.exports = adduser 2 | 3 | var log = require('npmlog') 4 | var npm = require('./npm.js') 5 | var usage = require('./utils/usage') 6 | var crypto 7 | 8 | try { 9 | crypto = require('crypto') 10 | } catch (ex) {} 11 | 12 | adduser.usage = usage( 13 | 'adduser', 14 | 'npm adduser [--registry=url] [--scope=@orgname] [--auth-type=legacy] [--always-auth]' 15 | ) 16 | 17 | function adduser (args, cb) { 18 | if (!crypto) { 19 | return cb(new Error( 20 | 'You must compile node with ssl support to use the adduser feature' 21 | )) 22 | } 23 | 24 | var registry = npm.config.get('registry') 25 | var scope = npm.config.get('scope') 26 | var creds = npm.config.getCredentialsByURI(npm.config.get('registry')) 27 | 28 | if (scope) { 29 | var scopedRegistry = npm.config.get(scope + ':registry') 30 | var cliRegistry = npm.config.get('registry', 'cli') 31 | if (scopedRegistry && !cliRegistry) registry = scopedRegistry 32 | } 33 | 34 | log.disableProgress() 35 | 36 | try { 37 | var auth = require('./auth/' + npm.config.get('auth-type')) 38 | } catch (e) { 39 | return cb(new Error('no such auth module')) 40 | } 41 | auth.login(creds, registry, scope, function (err, newCreds) { 42 | if (err) return cb(err) 43 | 44 | npm.config.del('_token', 'user') // prevent legacy pollution 45 | if (scope) npm.config.set(scope + ':registry', registry, 'user') 46 | npm.config.setCredentialsByURI(registry, newCreds) 47 | npm.config.save('user', cb) 48 | }) 49 | } 50 | -------------------------------------------------------------------------------- /test/tap/install-bad-dep-format.js: -------------------------------------------------------------------------------- 1 | var fs = require('graceful-fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var osenv = require('osenv') 6 | var rimraf = require('rimraf') 7 | var test = require('tap').test 8 | 9 | var common = require('../common-tap.js') 10 | 11 | var json = { 12 | author: 'John Foo', 13 | name: 'bad-dep-format', 14 | version: '0.0.0', 15 | dependencies: { 16 | 'not-legit': 'npm:not-legit@1.0' 17 | } 18 | } 19 | 20 | test('invalid url format returns appropriate error', function (t) { 21 | setup(json) 22 | common.npm(['install'], {}, function (err, code, stdout, stderr) { 23 | t.ifError(err, 'install ran without error') 24 | t.equals(code, 1, 'inall exited with code 1') 25 | t.match(stderr, 26 | /ERR.*Unsupported URL Type/, 27 | 'Error should report that invalid url-style formats are used') 28 | t.end() 29 | }) 30 | }) 31 | 32 | test('cleanup', function (t) { 33 | cleanup() 34 | t.end() 35 | }) 36 | 37 | function setup (json) { 38 | cleanup() 39 | process.chdir(mkPkg(json)) 40 | } 41 | 42 | function cleanup () { 43 | process.chdir(osenv.tmpdir()) 44 | var pkgs = [json] 45 | pkgs.forEach(function (json) { 46 | rimraf.sync(path.resolve(__dirname, json.name)) 47 | }) 48 | } 49 | 50 | function mkPkg (json) { 51 | var pkgPath = path.resolve(__dirname, json.name) 52 | mkdirp.sync(pkgPath) 53 | fs.writeFileSync( 54 | path.join(pkgPath, 'package.json'), 55 | JSON.stringify(json, null, 2) 56 | ) 57 | return pkgPath 58 | } 59 | -------------------------------------------------------------------------------- /test/tap/legacy-private.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var common = require('../common-tap.js') 4 | var path = require('path') 5 | var rimraf = require('rimraf') 6 | var mkdirp = require('mkdirp') 7 | var basepath = path.resolve(__dirname, path.basename(__filename, '.js')) 8 | var fixturepath = path.resolve(basepath, 'npm-test-private') 9 | var modulepath = path.resolve(basepath, 'node_modules') 10 | var Tacks = require('tacks') 11 | var File = Tacks.File 12 | var Dir = Tacks.Dir 13 | 14 | var fixture = new Tacks( 15 | Dir({ 16 | README: File( 17 | 'just an npm test\n' 18 | ), 19 | 'package.json': File({ 20 | name: 'npm-test-private', 21 | version: '9.9.9-9', 22 | homepage: 'http://www.youtube.com/watch?v=1MLry6Cn_D4', 23 | private: 'true' 24 | }) 25 | }) 26 | ) 27 | 28 | test('setup', function (t) { 29 | setup() 30 | t.done() 31 | }) 32 | 33 | test('private', function (t) { 34 | common.npm(['install', fixturepath], {cwd: basepath}, installCheckAndTest) 35 | function installCheckAndTest (err, code, stdout, stderr) { 36 | if (err) throw err 37 | console.error(stderr) 38 | console.log(stdout) 39 | t.is(code, 0, 'install went ok') 40 | t.done() 41 | } 42 | }) 43 | 44 | test('cleanup', function (t) { 45 | cleanup() 46 | t.done() 47 | }) 48 | 49 | function setup () { 50 | cleanup() 51 | fixture.create(fixturepath) 52 | mkdirp.sync(modulepath) 53 | } 54 | 55 | function cleanup () { 56 | fixture.remove(fixturepath) 57 | rimraf.sync(basepath) 58 | } 59 | -------------------------------------------------------------------------------- /lib/config/load-prefix.js: -------------------------------------------------------------------------------- 1 | module.exports = loadPrefix 2 | 3 | var findPrefix = require('./find-prefix.js') 4 | var path = require('path') 5 | 6 | function loadPrefix (cb) { 7 | var cli = this.list[0] 8 | 9 | Object.defineProperty(this, 'prefix', 10 | { 11 | set: function (prefix) { 12 | var g = this.get('global') 13 | this[g ? 'globalPrefix' : 'localPrefix'] = prefix 14 | }.bind(this), 15 | get: function () { 16 | var g = this.get('global') 17 | return g ? this.globalPrefix : this.localPrefix 18 | }.bind(this), 19 | enumerable: true 20 | }) 21 | 22 | Object.defineProperty(this, 'globalPrefix', 23 | { 24 | set: function (prefix) { 25 | this.set('prefix', prefix) 26 | }.bind(this), 27 | get: function () { 28 | return path.resolve(this.get('prefix')) 29 | }.bind(this), 30 | enumerable: true 31 | }) 32 | 33 | var p 34 | Object.defineProperty(this, 'localPrefix', 35 | { set: function (prefix) { p = prefix }, 36 | get: function () { return p }, 37 | enumerable: true }) 38 | 39 | // try to guess at a good node_modules location. 40 | // If we are *explicitly* given a prefix on the cli, then 41 | // always use that. otherwise, infer local prefix from cwd. 42 | if (Object.prototype.hasOwnProperty.call(cli, 'prefix')) { 43 | p = path.resolve(cli.prefix) 44 | process.nextTick(cb) 45 | } else { 46 | findPrefix(process.cwd(), function (er, found) { 47 | p = found 48 | cb(er) 49 | }) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/need-npm5-update/outdated-include-devdependencies.js: -------------------------------------------------------------------------------- 1 | var fs = require('graceful-fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var mr = require('npm-registry-mock') 6 | var rimraf = require('rimraf') 7 | var test = require('tap').test 8 | 9 | var npm = require('../../') 10 | var common = require('../common-tap.js') 11 | 12 | // config 13 | var pkg = path.resolve(__dirname, 'outdated-include-devdependencies') 14 | var cache = path.resolve(pkg, 'cache') 15 | 16 | var json = { 17 | author: 'Rocko Artischocko', 18 | name: 'ignore-shrinkwrap', 19 | version: '0.0.0', 20 | devDependencies: { 21 | underscore: '>=1.3.1' 22 | } 23 | } 24 | 25 | test('setup', function (t) { 26 | cleanup() 27 | mkdirp.sync(cache) 28 | fs.writeFileSync( 29 | path.join(pkg, 'package.json'), 30 | JSON.stringify(json, null, 2) 31 | ) 32 | t.end() 33 | }) 34 | 35 | test('includes devDependencies in outdated', function (t) { 36 | process.chdir(pkg) 37 | mr({ port: common.port }, function (er, s) { 38 | npm.load({ cache: cache, registry: common.registry }, function () { 39 | npm.outdated(function (er, d) { 40 | t.ifError(er, 'npm outdated completed successfully') 41 | t.is(process.exitCode, 1, 'exitCode set to 1') 42 | process.exitCode = 0 43 | t.equal('1.5.1', d[0][3]) 44 | s.close() 45 | t.end() 46 | }) 47 | }) 48 | }) 49 | }) 50 | 51 | test('cleanup', function (t) { 52 | cleanup() 53 | t.end() 54 | }) 55 | 56 | function cleanup () { 57 | rimraf.sync(pkg) 58 | } 59 | -------------------------------------------------------------------------------- /test/tap/symlink-cycle.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var fs = require('fs') 3 | var path = require('path') 4 | var test = require('tap').test 5 | var mkdirp = require('mkdirp') 6 | var osenv = require('osenv') 7 | var rimraf = require('rimraf') 8 | var writeFileSync = require('fs').writeFileSync 9 | var common = require('../common-tap.js') 10 | 11 | var base = path.join(__dirname, path.basename(__filename, '.js')) 12 | var cycle = path.join(base, 'cycle') 13 | 14 | var cycleJSON = { 15 | name: 'cycle', 16 | version: '1.0.0', 17 | description: '', 18 | main: 'index.js', 19 | scripts: { 20 | test: 'echo \"Error: no test specified\" && exit 1' 21 | }, 22 | dependencies: { 23 | 'cycle': '*' 24 | }, 25 | author: '', 26 | license: 'ISC' 27 | } 28 | 29 | test('setup', function (t) { 30 | setup() 31 | t.end() 32 | }) 33 | 34 | test('ls', function (t) { 35 | process.chdir(cycle) 36 | common.npm(['ls'], {}, function (err, code, stdout, stderr) { 37 | t.ifError(err, 'installed w/o error') 38 | t.is(stderr, '', 'no warnings printed to stderr') 39 | t.end() 40 | }) 41 | }) 42 | 43 | test('cleanup', function (t) { 44 | process.chdir(osenv.tmpdir()) 45 | cleanup() 46 | t.end() 47 | }) 48 | 49 | function cleanup () { 50 | rimraf.sync(base) 51 | } 52 | 53 | function setup () { 54 | cleanup() 55 | mkdirp.sync(path.join(cycle, 'node_modules')) 56 | writeFileSync( 57 | path.join(cycle, 'package.json'), 58 | JSON.stringify(cycleJSON, null, 2) 59 | ) 60 | fs.symlinkSync(cycle, path.join(cycle, 'node_modules', 'cycle'), 'junction') 61 | } 62 | -------------------------------------------------------------------------------- /test/tap/404-private-registry-scoped.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var path = require('path') 3 | var mkdirp = require('mkdirp') 4 | var rimraf = require('rimraf') 5 | var common = require('../common-tap.js') 6 | var mr = require('npm-registry-mock') 7 | var server 8 | 9 | var testdir = path.join(__dirname, path.basename(__filename, '.js')) 10 | 11 | function setup () { 12 | cleanup() 13 | mkdirp.sync(testdir) 14 | } 15 | 16 | function cleanup () { 17 | rimraf.sync(testdir) 18 | } 19 | 20 | test('setup', function (t) { 21 | setup() 22 | mr({port: common.port, throwOnUnmatched: true}, function (err, s) { 23 | t.ifError(err, 'registry mocked successfully') 24 | server = s 25 | t.end() 26 | }) 27 | }) 28 | 29 | test('scoped package names not mangled on error with non-root registry', function (t) { 30 | server.get('/@scope%2ffoo').reply(404, {}) 31 | common.npm( 32 | [ 33 | '--registry=' + common.registry, 34 | '--cache=' + testdir, 35 | 'cache', 36 | 'add', 37 | '@scope/foo@*', 38 | '--force' 39 | ], 40 | {}, 41 | function (er, code, stdout, stderr) { 42 | t.ifError(er, 'correctly handled 404') 43 | t.equal(code, 1, 'exited with error') 44 | t.match(stderr, /E404/, 'should notify the sort of error as a 404') 45 | t.match(stderr, /@scope(?:%2f|\/)foo/, 'should have package name in error') 46 | server.done() 47 | t.end() 48 | } 49 | ) 50 | }) 51 | 52 | test('cleanup', function (t) { 53 | server.close() 54 | cleanup() 55 | t.pass('cleaned up') 56 | t.end() 57 | }) 58 | -------------------------------------------------------------------------------- /lib/config/find-prefix.js: -------------------------------------------------------------------------------- 1 | // try to find the most reasonable prefix to use 2 | 3 | module.exports = findPrefix 4 | 5 | var fs = require('fs') 6 | var path = require('path') 7 | 8 | function findPrefix (p, cb_) { 9 | function cb (er, p) { 10 | process.nextTick(function () { 11 | cb_(er, p) 12 | }) 13 | } 14 | 15 | p = path.resolve(p) 16 | // if there's no node_modules folder, then 17 | // walk up until we hopefully find one. 18 | // if none anywhere, then use cwd. 19 | var walkedUp = false 20 | while (path.basename(p) === 'node_modules') { 21 | p = path.dirname(p) 22 | walkedUp = true 23 | } 24 | if (walkedUp) return cb(null, p) 25 | 26 | findPrefix_(p, p, cb) 27 | } 28 | 29 | function findPrefix_ (p, original, cb) { 30 | if (p === '/' || 31 | (process.platform === 'win32' && p.match(/^[a-zA-Z]:(\\|\/)?$/))) { 32 | return cb(null, original) 33 | } 34 | fs.readdir(p, function (er, files) { 35 | // an error right away is a bad sign. 36 | // unless the prefix was simply a non 37 | // existent directory. 38 | if (er && p === original) { 39 | if (er.code === 'ENOENT') return cb(null, original) 40 | return cb(er) 41 | } 42 | 43 | // walked up too high or something. 44 | if (er) return cb(null, original) 45 | 46 | if (files.indexOf('node_modules') !== -1 || 47 | files.indexOf('package.json') !== -1) { 48 | return cb(null, p) 49 | } 50 | 51 | var d = path.dirname(p) 52 | if (d === p) return cb(null, original) 53 | 54 | return findPrefix_(d, original, cb) 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /test/tap/local-args-relative-to-cwd.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var fs = require('graceful-fs') 3 | var path = require('path') 4 | var test = require('tap').test 5 | var Tacks = require('tacks') 6 | var File = Tacks.File 7 | var Dir = Tacks.Dir 8 | var common = require('../common-tap.js') 9 | var testdir = path.join(__dirname, path.basename(__filename, '.js')) 10 | 11 | var fixture = new Tacks( 12 | Dir({ 13 | example: Dir({ 14 | }), 15 | mod1: Dir({ 16 | 'package.json': File({ 17 | name: 'mod1', 18 | version: '1.0.0' 19 | }) 20 | }), 21 | node_modules: Dir({ 22 | }) 23 | }) 24 | ) 25 | 26 | function setup () { 27 | fixture.create(testdir) 28 | } 29 | 30 | function cleanup () { 31 | fixture.remove(testdir) 32 | } 33 | 34 | test('setup', function (t) { 35 | cleanup() 36 | setup() 37 | t.end() 38 | }) 39 | 40 | function exists (file) { 41 | try { 42 | fs.statSync(file) 43 | return true 44 | } catch (ex) { 45 | return false 46 | } 47 | } 48 | 49 | test('local-args-relative-to-cwd', function (t) { 50 | var instdir = path.join(testdir, 'example') 51 | var config = ['--loglevel=error'] 52 | common.npm(config.concat(['install', '../mod1']), {cwd: instdir}, function (err, code, stdout, stderr) { 53 | if (err) throw err 54 | t.comment(stdout.trim()) 55 | t.comment(stderr.trim()) 56 | t.is(code, 0, 'install ran ok') 57 | t.ok(exists(path.join(testdir, 'node_modules', 'mod1')), 'mod1 installed') 58 | t.end() 59 | }) 60 | }) 61 | 62 | test('cleanup', function (t) { 63 | cleanup() 64 | t.end() 65 | }) 66 | -------------------------------------------------------------------------------- /doc/cli/npm-dedupe.md: -------------------------------------------------------------------------------- 1 | npm-dedupe(1) -- Reduce duplication 2 | =================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm dedupe 7 | npm ddp 8 | 9 | aliases: find-dupes, ddp 10 | 11 | ## DESCRIPTION 12 | 13 | Searches the local package tree and attempts to simplify the overall 14 | structure by moving dependencies further up the tree, where they can 15 | be more effectively shared by multiple dependent packages. 16 | 17 | For example, consider this dependency graph: 18 | 19 | a 20 | +-- b <-- depends on c@1.0.x 21 | | `-- c@1.0.3 22 | `-- d <-- depends on c@~1.0.9 23 | `-- c@1.0.10 24 | 25 | In this case, `npm-dedupe(1)` will transform the tree to: 26 | 27 | a 28 | +-- b 29 | +-- d 30 | `-- c@1.0.10 31 | 32 | Because of the hierarchical nature of node's module lookup, b and d 33 | will both get their dependency met by the single c package at the root 34 | level of the tree. 35 | 36 | The deduplication algorithm walks the tree, moving each dependency as far 37 | up in the tree as possible, even if duplicates are not found. This will 38 | result in both a flat and deduplicated tree. 39 | 40 | If a suitable version exists at the target location in the tree 41 | already, then it will be left untouched, but the other duplicates will 42 | be deleted. 43 | 44 | Arguments are ignored. Dedupe always acts on the entire tree. 45 | 46 | Modules 47 | 48 | Note that this operation transforms the dependency tree, but will never 49 | result in new modules being installed. 50 | 51 | ## SEE ALSO 52 | 53 | * npm-ls(1) 54 | * npm-update(1) 55 | * npm-install(1) 56 | -------------------------------------------------------------------------------- /test/network/legacy-url-dep.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var common = require('../common-tap.js') 4 | var path = require('path') 5 | var rimraf = require('rimraf') 6 | var mkdirp = require('mkdirp') 7 | var basepath = path.resolve(__dirname, path.basename(__filename, '.js')) 8 | var fixturepath = path.resolve(basepath, 'npm-test-url-dep') 9 | var modulepath = path.resolve(basepath, 'node_modules') 10 | var Tacks = require('tacks') 11 | var File = Tacks.File 12 | var Dir = Tacks.Dir 13 | 14 | var fixture = new Tacks( 15 | Dir({ 16 | README: File( 17 | 'just an npm test\n' 18 | ), 19 | 'package.json': File({ 20 | name: 'npm-test-url-dep', 21 | version: '1.2.3', 22 | dependencies: { 23 | jsonify: 'https://github.com/substack/jsonify/tarball/master', 24 | sax: 'isaacs/sax-js', 25 | 'canonical-host': 'git://github.com/isaacs/canonical-host' 26 | } 27 | }) 28 | }) 29 | ) 30 | 31 | test('setup', function (t) { 32 | setup() 33 | t.done() 34 | }) 35 | 36 | test('url-dep', function (t) { 37 | common.npm(['install', fixturepath], {cwd: basepath}, installCheckAndTest) 38 | function installCheckAndTest (err, code, stdout, stderr) { 39 | if (err) throw err 40 | t.is(code, 0, 'install went ok') 41 | t.done() 42 | } 43 | }) 44 | 45 | test('cleanup', function (t) { 46 | cleanup() 47 | t.done() 48 | }) 49 | 50 | function setup () { 51 | cleanup() 52 | fixture.create(fixturepath) 53 | mkdirp.sync(modulepath) 54 | } 55 | 56 | function cleanup () { 57 | fixture.remove(fixturepath) 58 | rimraf.sync(basepath) 59 | } 60 | -------------------------------------------------------------------------------- /lib/utils/spawn.js: -------------------------------------------------------------------------------- 1 | module.exports = spawn 2 | 3 | var _spawn = require('child_process').spawn 4 | var EventEmitter = require('events').EventEmitter 5 | var npwr = require('./no-progress-while-running.js') 6 | 7 | function willCmdOutput (stdio) { 8 | if (stdio === 'inherit') return true 9 | if (!Array.isArray(stdio)) return false 10 | for (var fh = 1; fh <= 2; ++fh) { 11 | if (stdio[fh] === 'inherit') return true 12 | if (stdio[fh] === 1 || stdio[fh] === 2) return true 13 | } 14 | return false 15 | } 16 | 17 | function spawn (cmd, args, options) { 18 | var cmdWillOutput = willCmdOutput(options && options.stdio) 19 | 20 | if (cmdWillOutput) npwr.startRunning() 21 | var raw = _spawn(cmd, args, options) 22 | var cooked = new EventEmitter() 23 | 24 | raw.on('error', function (er) { 25 | if (cmdWillOutput) npwr.stopRunning() 26 | er.file = cmd 27 | cooked.emit('error', er) 28 | }).on('close', function (code, signal) { 29 | if (cmdWillOutput) npwr.stopRunning() 30 | // Create ENOENT error because Node.js v0.8 will not emit 31 | // an `error` event if the command could not be found. 32 | if (code === 127) { 33 | var er = new Error('spawn ENOENT') 34 | er.code = 'ENOENT' 35 | er.errno = 'ENOENT' 36 | er.syscall = 'spawn' 37 | er.file = cmd 38 | cooked.emit('error', er) 39 | } else { 40 | cooked.emit('close', code, signal) 41 | } 42 | }) 43 | 44 | cooked.stdin = raw.stdin 45 | cooked.stdout = raw.stdout 46 | cooked.stderr = raw.stderr 47 | cooked.kill = function (sig) { return raw.kill(sig) } 48 | 49 | return cooked 50 | } 51 | -------------------------------------------------------------------------------- /test/network/git-cache-no-hooks.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var fs = require('fs') 3 | var path = require('path') 4 | var common = require('../common-tap.js') 5 | var rimraf = require('rimraf') 6 | var mkdirp = require('mkdirp') 7 | var pkg = path.resolve(__dirname, 'git-cache-no-hooks') 8 | var osenv = require('osenv') 9 | var tmp = path.join(pkg, 'tmp') 10 | var cache = path.join(pkg, 'cache') 11 | 12 | test('setup', function (t) { 13 | rimraf.sync(pkg) 14 | mkdirp.sync(pkg) 15 | mkdirp.sync(cache) 16 | mkdirp.sync(tmp) 17 | mkdirp.sync(path.resolve(pkg, 'node_modules')) 18 | t.end() 19 | }) 20 | 21 | test('git-cache-no-hooks: install a git dependency', function (t) { 22 | // disable git integration tests on Travis. 23 | if (process.env.TRAVIS) return t.end() 24 | 25 | common.npm([ 26 | 'install', 'git://github.com/nigelzor/npm-4503-a.git', 27 | '--cache', cache, 28 | '--tmp', tmp 29 | ], { 30 | cwd: pkg 31 | }, function (err, code, stdout, stderr) { 32 | t.ifErr(err, 'npm completed') 33 | t.equal(stderr, '', 'no error output') 34 | t.equal(code, 0, 'npm install should succeed') 35 | 36 | // verify permissions on git hooks 37 | var repoDir = 'git-github-com-nigelzor-npm-4503-a-git-40c5cb24' 38 | var hooksPath = path.join(cache, '_git-remotes', repoDir, 'hooks') 39 | fs.readdir(hooksPath, function (err) { 40 | t.equal(err && err.code, 'ENOENT', 'hooks are not brought along with repo') 41 | t.end() 42 | }) 43 | }) 44 | }) 45 | 46 | test('cleanup', function (t) { 47 | process.chdir(osenv.tmpdir()) 48 | rimraf.sync(pkg) 49 | t.end() 50 | }) 51 | -------------------------------------------------------------------------------- /test/tap/ping.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var mr = require('npm-registry-mock') 6 | var rimraf = require('rimraf') 7 | var test = require('tap').test 8 | 9 | var common = require('../common-tap.js') 10 | 11 | var pkg = path.resolve(__dirname, 'ping') 12 | var opts = { cwd: pkg } 13 | 14 | var outfile = path.join(pkg, '_npmrc') 15 | 16 | var contents = function () { 17 | }.toString().split('\n').slice(1, -1).join('\n') 18 | 19 | var pingResponse = { 20 | host: 'registry.npmjs.org', 21 | ok: true, 22 | username: null, 23 | peer: 'example.com' 24 | } 25 | 26 | function mocks (server) { 27 | server.get('/-/ping?write=true').reply(200, JSON.stringify(pingResponse)) 28 | } 29 | 30 | test('setup', function (t) { 31 | cleanup() 32 | setup() 33 | t.end() 34 | }) 35 | 36 | test('npm ping', function (t) { 37 | mr({ port: common.port, plugin: mocks }, function (err, s) { 38 | if (err) throw err 39 | 40 | common.npm([ 41 | 'ping', 42 | '--registry', common.registry, 43 | '--loglevel', 'silent', 44 | '--userconfig', outfile 45 | ], opts, function (err, code, stdout) { 46 | s.close() 47 | t.ifError(err, 'no error output') 48 | t.notOk(code, 'exited OK') 49 | 50 | t.same(JSON.parse(stdout), pingResponse) 51 | t.end() 52 | }) 53 | }) 54 | }) 55 | 56 | test('cleanup', function (t) { 57 | cleanup() 58 | t.end() 59 | }) 60 | 61 | function setup () { 62 | mkdirp.sync(pkg) 63 | fs.writeFileSync(outfile, contents) 64 | } 65 | 66 | function cleanup () { 67 | rimraf.sync(pkg) 68 | } 69 | -------------------------------------------------------------------------------- /test/tap/init-interrupt.js: -------------------------------------------------------------------------------- 1 | // if 'npm init' is interrupted with ^C, don't report 2 | // 'init written successfully' 3 | var test = require('tap').test 4 | var path = require('path') 5 | var osenv = require('osenv') 6 | var rimraf = require('rimraf') 7 | var npmlog = require('npmlog') 8 | var requireInject = require('require-inject') 9 | 10 | var npm = require('../../lib/npm.js') 11 | 12 | var PKG_DIR = path.resolve(__dirname, 'init-interrupt') 13 | 14 | test('setup', function (t) { 15 | cleanup() 16 | 17 | t.end() 18 | }) 19 | 20 | test('issue #6684 remove confusing message', function (t) { 21 | var initJsonMock = function (dir, input, config, cb) { 22 | process.nextTick(function () { 23 | cb({ message: 'canceled' }) 24 | }) 25 | } 26 | initJsonMock.yes = function () { return true } 27 | 28 | npm.load({ loglevel: 'silent' }, function () { 29 | var log = '' 30 | var init = requireInject('../../lib/init', { 31 | 'init-package-json': initJsonMock 32 | }) 33 | 34 | // capture log messages 35 | npmlog.on('log', function (chunk) { log += chunk.message + '\n' }) 36 | 37 | init([], function (err, code) { 38 | t.ifError(err, 'init ran successfully') 39 | t.notOk(code, 'exited without issue') 40 | t.notSimilar(log, /written successfully/, 'no success message written') 41 | t.similar(log, /canceled/, 'alerted that init was canceled') 42 | 43 | t.end() 44 | }) 45 | }) 46 | }) 47 | 48 | test('cleanup', function (t) { 49 | cleanup() 50 | 51 | t.end() 52 | }) 53 | 54 | function cleanup () { 55 | process.chdir(osenv.tmpdir()) 56 | rimraf.sync(PKG_DIR) 57 | } 58 | -------------------------------------------------------------------------------- /lib/whoami.js: -------------------------------------------------------------------------------- 1 | var npm = require('./npm.js') 2 | var output = require('./utils/output.js') 3 | 4 | module.exports = whoami 5 | 6 | whoami.usage = 'npm whoami [--registry ]\n(just prints username according to given registry)' 7 | 8 | function whoami (args, silent, cb) { 9 | // FIXME: need tighter checking on this, but is a breaking change 10 | if (typeof cb !== 'function') { 11 | cb = silent 12 | silent = false 13 | } 14 | 15 | var registry = npm.config.get('registry') 16 | if (!registry) return cb(new Error('no default registry set')) 17 | 18 | var auth = npm.config.getCredentialsByURI(registry) 19 | if (auth) { 20 | if (auth.username) { 21 | if (!silent) output(auth.username) 22 | return process.nextTick(cb.bind(this, null, auth.username)) 23 | } else if (auth.token) { 24 | return npm.registry.whoami(registry, { auth: auth }, function (er, username) { 25 | if (er) return cb(er) 26 | if (!username) { 27 | var needNewSession = new Error( 28 | 'Your auth token is no longer valid. Please log in again.' 29 | ) 30 | needNewSession.code = 'ENEEDAUTH' 31 | return cb(needNewSession) 32 | } 33 | 34 | if (!silent) output(username) 35 | cb(null, username) 36 | }) 37 | } 38 | } 39 | 40 | // At this point, if they have a credentials object, it doesn't have a token 41 | // or auth in it. Probably just the default registry. 42 | var needAuth = new Error( 43 | 'this command requires you to be logged in.' 44 | ) 45 | needAuth.code = 'ENEEDAUTH' 46 | process.nextTick(cb.bind(this, needAuth)) 47 | } 48 | -------------------------------------------------------------------------------- /test/tap/logout.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var mr = require('npm-registry-mock') 6 | var rimraf = require('rimraf') 7 | var test = require('tap').test 8 | 9 | var common = require('../common-tap.js') 10 | 11 | var pkg = path.resolve(__dirname, 'logout') 12 | var outfile = path.join(pkg, '_npmrc') 13 | var opts = { cwd: pkg } 14 | 15 | var contents = function () { /* 16 | foo=boo 17 | //localhost:1337/:_authToken=glarb 18 | */ }.toString().split('\n').slice(1, -1).join('\n') 19 | 20 | function mocks (server) { 21 | server.delete('/-/user/token/glarb') 22 | .reply(200, {}) 23 | } 24 | 25 | test('setup', function (t) { 26 | cleanup() 27 | setup() 28 | t.end() 29 | }) 30 | 31 | test('npm logout', function (t) { 32 | mr({ port: common.port, plugin: mocks }, function (err, s) { 33 | if (err) throw err 34 | 35 | common.npm( 36 | [ 37 | 'logout', 38 | '--registry', common.registry, 39 | '--loglevel', 'silent', 40 | '--userconfig', outfile 41 | ], 42 | opts, 43 | function (err, code) { 44 | t.ifError(err, 'no error output') 45 | t.notOk(code, 'exited OK') 46 | 47 | var config = fs.readFileSync(outfile, 'utf8') 48 | t.notMatch(config, /localhost/, 'creds gone') 49 | s.close() 50 | t.end() 51 | } 52 | ) 53 | }) 54 | }) 55 | 56 | test('cleanup', function (t) { 57 | cleanup() 58 | t.end() 59 | }) 60 | 61 | function setup () { 62 | mkdirp.sync(pkg) 63 | fs.writeFileSync(outfile, contents) 64 | } 65 | 66 | function cleanup () { 67 | rimraf.sync(pkg) 68 | } 69 | -------------------------------------------------------------------------------- /doc/cli/npm-config.md: -------------------------------------------------------------------------------- 1 | npm-config(1) -- Manage the npm configuration files 2 | =================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | npm config set [-g|--global] 7 | npm config get 8 | npm config delete 9 | npm config list 10 | npm config edit 11 | npm get 12 | npm set [-g|--global] 13 | 14 | aliases: c 15 | 16 | ## DESCRIPTION 17 | 18 | npm gets its config settings from the command line, environment 19 | variables, `npmrc` files, and in some cases, the `package.json` file. 20 | 21 | See npmrc(5) for more information about the npmrc files. 22 | 23 | See `npm-config(7)` for a more thorough discussion of the mechanisms 24 | involved. 25 | 26 | The `npm config` command can be used to update and edit the contents 27 | of the user and global npmrc files. 28 | 29 | ## Sub-commands 30 | 31 | Config supports the following sub-commands: 32 | 33 | ### set 34 | 35 | npm config set key value 36 | 37 | Sets the config key to the value. 38 | 39 | If value is omitted, then it sets it to "true". 40 | 41 | ### get 42 | 43 | npm config get key 44 | 45 | Echo the config value to stdout. 46 | 47 | ### list 48 | 49 | npm config list 50 | 51 | Show all the config settings. 52 | 53 | ### delete 54 | 55 | npm config delete key 56 | 57 | Deletes the key from all configuration files. 58 | 59 | ### edit 60 | 61 | npm config edit 62 | 63 | Opens the config file in an editor. Use the `--global` flag to edit the 64 | global config. 65 | 66 | ## SEE ALSO 67 | 68 | * npm-folders(5) 69 | * npm-config(7) 70 | * package.json(5) 71 | * npmrc(5) 72 | * npm(1) 73 | -------------------------------------------------------------------------------- /test/tap/install-scoped-with-peer-dependency.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var osenv = require('osenv') 6 | var rimraf = require('rimraf') 7 | var test = require('tap').test 8 | 9 | var common = require('../common-tap.js') 10 | var pkg = path.join(__dirname, 'install-scoped-with-peer-dependency') 11 | var local = path.join(pkg, 'package') 12 | 13 | var EXEC_OPTS = { } 14 | 15 | var json = { 16 | name: '@scope/package', 17 | version: '0.0.0', 18 | peerDependencies: { 19 | underscore: '*' 20 | } 21 | } 22 | 23 | test('setup', function (t) { 24 | setup() 25 | 26 | t.end() 27 | }) 28 | 29 | test('it should install peerDependencies in same tree level as the parent package', function (t) { 30 | common.npm(['install', '--loglevel=warn', './package'], EXEC_OPTS, function (err, code, stdout, stderr) { 31 | t.ifError(err, 'install local package successful') 32 | t.equal(code, 0, 'npm install exited with code') 33 | t.match(stderr, /npm WARN @scope[/]package@0[.]0[.]0 requires a peer of underscore@[*] but none was installed[.]\n/, 34 | 'npm install warned about unresolved peer dep') 35 | 36 | t.end() 37 | }) 38 | }) 39 | 40 | test('cleanup', function (t) { 41 | cleanup() 42 | t.end() 43 | }) 44 | 45 | function setup () { 46 | cleanup() 47 | mkdirp.sync(local) 48 | mkdirp.sync(path.resolve(pkg, 'node_modules')) 49 | fs.writeFileSync( 50 | path.join(local, 'package.json'), 51 | JSON.stringify(json, null, 2) 52 | ) 53 | process.chdir(pkg) 54 | } 55 | 56 | function cleanup () { 57 | process.chdir(osenv.tmpdir()) 58 | rimraf.sync(pkg) 59 | } 60 | -------------------------------------------------------------------------------- /lib/deprecate.js: -------------------------------------------------------------------------------- 1 | var npm = require('./npm.js') 2 | var mapToRegistry = require('./utils/map-to-registry.js') 3 | var npa = require('npm-package-arg') 4 | 5 | module.exports = deprecate 6 | 7 | deprecate.usage = 'npm deprecate [@] ' 8 | 9 | deprecate.completion = function (opts, cb) { 10 | // first, get a list of remote packages this user owns. 11 | // once we have a user account, then don't complete anything. 12 | if (opts.conf.argv.remain.length > 2) return cb() 13 | // get the list of packages by user 14 | var path = '/-/by-user/' 15 | mapToRegistry(path, npm.config, function (er, uri, c) { 16 | if (er) return cb(er) 17 | 18 | if (!(c && c.username)) return cb() 19 | 20 | var params = { 21 | timeout: 60000, 22 | auth: c 23 | } 24 | npm.registry.get(uri + c.username, params, function (er, list) { 25 | if (er) return cb() 26 | console.error(list) 27 | return cb(null, list[c.username]) 28 | }) 29 | }) 30 | } 31 | 32 | function deprecate (args, cb) { 33 | var pkg = args[0] 34 | var msg = args[1] 35 | if (msg === undefined) return cb('Usage: ' + deprecate.usage) 36 | 37 | // fetch the data and make sure it exists. 38 | var p = npa(pkg) 39 | 40 | // npa makes the default spec "latest", but for deprecation 41 | // "*" is the appropriate default. 42 | var spec = p.rawSpec === '' ? '*' : p.fetchSpec 43 | 44 | mapToRegistry(p.name, npm.config, function (er, uri, auth) { 45 | if (er) return cb(er) 46 | 47 | var params = { 48 | version: spec, 49 | message: msg, 50 | auth: auth 51 | } 52 | npm.registry.deprecate(uri, params, cb) 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /lib/team.js: -------------------------------------------------------------------------------- 1 | var mapToRegistry = require('./utils/map-to-registry.js') 2 | var npm = require('./npm') 3 | var output = require('./utils/output.js') 4 | 5 | module.exports = team 6 | 7 | team.subcommands = ['create', 'destroy', 'add', 'rm', 'ls', 'edit'] 8 | 9 | team.usage = 10 | 'npm team create \n' + 11 | 'npm team destroy \n' + 12 | 'npm team add \n' + 13 | 'npm team rm \n' + 14 | 'npm team ls |\n' + 15 | 'npm team edit ' 16 | 17 | team.completion = function (opts, cb) { 18 | var argv = opts.conf.argv.remain 19 | if (argv.length === 2) { 20 | return cb(null, team.subcommands) 21 | } 22 | switch (argv[2]) { 23 | case 'ls': 24 | case 'create': 25 | case 'destroy': 26 | case 'add': 27 | case 'rm': 28 | case 'edit': 29 | return cb(null, []) 30 | default: 31 | return cb(new Error(argv[2] + ' not recognized')) 32 | } 33 | } 34 | 35 | function team (args, cb) { 36 | // Entities are in the format : 37 | var cmd = args.shift() 38 | var entity = (args.shift() || '').split(':') 39 | return mapToRegistry('/', npm.config, function (err, uri, auth) { 40 | if (err) { return cb(err) } 41 | try { 42 | return npm.registry.team(cmd, uri, { 43 | auth: auth, 44 | scope: entity[0], 45 | team: entity[1], 46 | user: args.shift() 47 | }, function (err, data) { 48 | !err && data && output(JSON.stringify(data, undefined, 2)) 49 | cb(err, data) 50 | }) 51 | } catch (e) { 52 | cb(e.message + '\n\nUsage:\n' + team.usage) 53 | } 54 | }) 55 | } 56 | -------------------------------------------------------------------------------- /test/tap/bundled-dependencies-no-pkgjson.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var path = require('path') 3 | var fs = require('graceful-fs') 4 | 5 | var mkdirp = require('mkdirp') 6 | var rimraf = require('rimraf') 7 | var common = require('../common-tap.js') 8 | 9 | var dir = path.resolve(__dirname, 'bundled-dependencies-no-pkgjson') 10 | var pkg = path.resolve(dir, 'pkg-with-bundled-dep') 11 | var dep = path.resolve(pkg, 'node_modules', 'a-bundled-dep') 12 | 13 | var pkgJson = JSON.stringify({ 14 | name: 'pkg-with-bundled-dep', 15 | version: '1.0.0', 16 | dependencies: { 17 | }, 18 | bundledDependencies: [ 19 | 'a-bundled-dep' 20 | ] 21 | }, null, 2) + '\n' 22 | var packed 23 | 24 | test('setup', function (t) { 25 | rimraf.sync(dir) 26 | mkdirp.sync(path.join(dir, 'node_modules')) 27 | mkdirp.sync(dep) 28 | 29 | fs.writeFileSync(path.resolve(pkg, 'package.json'), pkgJson) 30 | fs.writeFileSync(path.resolve(dep, 'index.js'), '') 31 | common.npm(['pack', pkg], {cwd: dir}, function (err, code, stdout, stderr) { 32 | if (err) throw err 33 | t.is(code, 0, 'packed ok') 34 | packed = stdout.trim() 35 | t.comment(stderr) 36 | t.end() 37 | }) 38 | }) 39 | 40 | test('proper error on bundled dep with no package.json', function (t) { 41 | t.plan(2) 42 | var npmArgs = ['install', packed] 43 | 44 | common.npm(npmArgs, { cwd: dir }, function (err, code, stdout, stderr) { 45 | if (err) throw err 46 | t.notEqual(code, 0, 'npm ended in error') 47 | t.like(stderr, /ENOENT/, 'ENOENT should be in stderr') 48 | t.end() 49 | }) 50 | }) 51 | 52 | test('cleanup', function (t) { 53 | rimraf.sync(dir) 54 | t.end() 55 | }) 56 | -------------------------------------------------------------------------------- /test/tap/shrinkwrap-lifecycle.js: -------------------------------------------------------------------------------- 1 | var fs = require('graceful-fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var osenv = require('osenv') 6 | var rimraf = require('rimraf') 7 | var test = require('tap').test 8 | 9 | var common = require('../common-tap.js') 10 | var pkg = path.resolve(__dirname, 'shrinkwrap-lifecycle') 11 | 12 | test('npm shrinkwrap execution order', function (t) { 13 | setup() 14 | fs.writeFileSync(path.resolve(pkg, 'package.json'), JSON.stringify({ 15 | author: 'Simen Bekkhus', 16 | name: 'shrinkwrap-lifecycle', 17 | shrinkwrap: '0.0.0', 18 | description: 'Test for npm shrinkwrap execution order', 19 | scripts: { 20 | preshrinkwrap: 'echo this happens first', 21 | shrinkwrap: 'echo this happens second', 22 | postshrinkwrap: 'echo this happens third' 23 | } 24 | }), 'utf8') 25 | common.npm(['shrinkwrap', '--loglevel=error'], [], function (err, code, stdout, stderr) { 26 | if (err) throw err 27 | 28 | t.comment(stdout) 29 | t.comment(stderr) 30 | var indexOfFirst = stdout.indexOf('echo this happens first') 31 | var indexOfSecond = stdout.indexOf('echo this happens second') 32 | var indexOfThird = stdout.indexOf('echo this happens third') 33 | 34 | t.ok(indexOfFirst >= 0) 35 | t.ok(indexOfSecond >= 0) 36 | t.ok(indexOfThird >= 0) 37 | 38 | t.ok(indexOfFirst < indexOfSecond) 39 | t.ok(indexOfSecond < indexOfThird) 40 | 41 | t.end() 42 | }) 43 | }) 44 | 45 | test('cleanup', function (t) { 46 | process.chdir(osenv.tmpdir()) 47 | rimraf.sync(pkg) 48 | t.end() 49 | }) 50 | 51 | function setup () { 52 | mkdirp.sync(pkg) 53 | process.chdir(pkg) 54 | } 55 | -------------------------------------------------------------------------------- /lib/repo.js: -------------------------------------------------------------------------------- 1 | module.exports = repo 2 | 3 | repo.usage = 'npm repo []' 4 | 5 | var npm = require('./npm.js') 6 | var opener = require('opener') 7 | var hostedGitInfo = require('hosted-git-info') 8 | var url_ = require('url') 9 | var fetchPackageMetadata = require('./fetch-package-metadata.js') 10 | 11 | repo.completion = function (opts, cb) { 12 | // FIXME: there used to be registry completion here, but it stopped making 13 | // sense somewhere around 50,000 packages on the registry 14 | cb() 15 | } 16 | 17 | function repo (args, cb) { 18 | var n = args.length ? args[0] : '.' 19 | fetchPackageMetadata(n, '.', {fullMetadata: true}, function (er, d) { 20 | if (er) return cb(er) 21 | getUrlAndOpen(d, cb) 22 | }) 23 | } 24 | 25 | function getUrlAndOpen (d, cb) { 26 | var r = d.repository 27 | if (!r) return cb(new Error('no repository')) 28 | // XXX remove this when npm@v1.3.10 from node 0.10 is deprecated 29 | // from https://github.com/npm/npm-www/issues/418 30 | var info = hostedGitInfo.fromUrl(r.url) 31 | var url = info ? info.browse() : unknownHostedUrl(r.url) 32 | 33 | if (!url) return cb(new Error('no repository: could not get url')) 34 | 35 | opener(url, { command: npm.config.get('browser') }, cb) 36 | } 37 | 38 | function unknownHostedUrl (url) { 39 | try { 40 | var idx = url.indexOf('@') 41 | if (idx !== -1) { 42 | url = url.slice(idx + 1).replace(/:([^\d]+)/, '/$1') 43 | } 44 | url = url_.parse(url) 45 | var protocol = url.protocol === 'https:' 46 | ? 'https:' 47 | : 'http:' 48 | return protocol + '//' + (url.host || '') + 49 | url.path.replace(/\.git$/, '') 50 | } catch (e) {} 51 | } 52 | -------------------------------------------------------------------------------- /test/tap/legacy-platform.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var test = require('tap').test 3 | var common = require('../common-tap.js') 4 | var path = require('path') 5 | var rimraf = require('rimraf') 6 | var mkdirp = require('mkdirp') 7 | var basepath = path.resolve(__dirname, path.basename(__filename, '.js')) 8 | var fixturepath = path.resolve(basepath, 'npm-test-platform') 9 | var modulepath = path.resolve(basepath, 'node_modules') 10 | var Tacks = require('tacks') 11 | var File = Tacks.File 12 | var Dir = Tacks.Dir 13 | 14 | var fixture = new Tacks( 15 | Dir({ 16 | README: File( 17 | 'just an npm test\n' 18 | ), 19 | 'package.json': File({ 20 | name: 'npm-test-platform', 21 | version: '9.9.9-9', 22 | homepage: 'http://www.youtube.com/watch?v=dQw4w9WgXcQ', 23 | os: [ 24 | '!this_is_not_a_real_os', 25 | '!neither_is_this' 26 | ], 27 | cpu: [ 28 | '!this_is_not_a_real_cpu', 29 | '!this_isnt_either' 30 | ] 31 | }) 32 | }) 33 | ) 34 | 35 | test('setup', function (t) { 36 | setup() 37 | t.done() 38 | }) 39 | 40 | test('platform', function (t) { 41 | common.npm(['install', fixturepath], {cwd: basepath}, installCheckAndTest) 42 | function installCheckAndTest (err, code, stdout, stderr) { 43 | if (err) throw err 44 | console.error(stderr) 45 | t.is(code, 0, 'install went ok') 46 | t.done() 47 | } 48 | }) 49 | 50 | test('cleanup', function (t) { 51 | cleanup() 52 | t.done() 53 | }) 54 | 55 | function setup () { 56 | cleanup() 57 | fixture.create(fixturepath) 58 | mkdirp.sync(modulepath) 59 | } 60 | 61 | function cleanup () { 62 | fixture.remove(fixturepath) 63 | rimraf.sync(basepath) 64 | } 65 | -------------------------------------------------------------------------------- /test/tap/config-project.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test 2 | var path = require('path') 3 | var fix = path.resolve(__dirname, '..', 'fixtures', 'config') 4 | var projectRc = path.resolve(fix, '.npmrc') 5 | var npmconf = require('../../lib/config/core.js') 6 | var common = require('./00-config-setup.js') 7 | 8 | var projectData = { just: 'testing' } 9 | 10 | var ucData = common.ucData 11 | var envData = common.envData 12 | var envDataFix = common.envDataFix 13 | 14 | var gcData = { 'package-config:foo': 'boo' } 15 | 16 | var biData = {} 17 | 18 | var cli = { foo: 'bar', umask: parseInt('022', 8), prefix: fix } 19 | 20 | var expectList = [ 21 | cli, 22 | envDataFix, 23 | projectData, 24 | ucData, 25 | gcData, 26 | biData 27 | ] 28 | 29 | var expectSources = { 30 | cli: { data: cli }, 31 | env: { 32 | data: envDataFix, 33 | source: envData, 34 | prefix: '' 35 | }, 36 | project: { 37 | path: projectRc, 38 | type: 'ini', 39 | data: projectData 40 | }, 41 | user: { 42 | path: common.userconfig, 43 | type: 'ini', 44 | data: ucData 45 | }, 46 | global: { 47 | path: common.globalconfig, 48 | type: 'ini', 49 | data: gcData 50 | }, 51 | builtin: { data: biData } 52 | } 53 | 54 | test('no builtin', function (t) { 55 | npmconf.load(cli, function (er, conf) { 56 | if (er) throw er 57 | t.same(conf.list, expectList) 58 | t.same(conf.sources, expectSources) 59 | t.same(npmconf.rootConf.list, []) 60 | t.equal(npmconf.rootConf.root, npmconf.defs.defaults) 61 | t.equal(conf.root, npmconf.defs.defaults) 62 | t.equal(conf.get('umask'), parseInt('022', 8)) 63 | t.equal(conf.get('heading'), 'npm') 64 | t.end() 65 | }) 66 | }) 67 | -------------------------------------------------------------------------------- /test/tap/version-no-git.js: -------------------------------------------------------------------------------- 1 | var common = require('../common-tap.js') 2 | var test = require('tap').test 3 | var npm = require('../../') 4 | var osenv = require('osenv') 5 | var path = require('path') 6 | var fs = require('fs') 7 | var mkdirp = require('mkdirp') 8 | var rimraf = require('rimraf') 9 | var requireInject = require('require-inject') 10 | 11 | var pkg = path.resolve(__dirname, 'version-no-git') 12 | var cache = path.resolve(pkg, 'cache') 13 | var gitDir = path.resolve(pkg, '.git') 14 | 15 | test('npm version in a git repo without the git binary', function (t) { 16 | setup() 17 | npm.load({cache: cache, registry: common.registry}, function () { 18 | var version = requireInject('../../lib/version', { 19 | which: function (cmd, cb) { 20 | process.nextTick(function () { 21 | cb(new Error('ENOGIT!')) 22 | }) 23 | } 24 | }) 25 | 26 | version(['patch'], function (err) { 27 | if (!t.error(err)) return t.end() 28 | var p = path.resolve(pkg, 'package') 29 | var testPkg = require(p) 30 | t.equal('0.0.1', testPkg.version, '\'' + testPkg.version + '\' === \'0.0.1\'') 31 | t.end() 32 | }) 33 | }) 34 | }) 35 | 36 | test('cleanup', function (t) { 37 | process.chdir(osenv.tmpdir()) 38 | 39 | rimraf.sync(pkg) 40 | t.end() 41 | }) 42 | 43 | function setup () { 44 | mkdirp.sync(pkg) 45 | mkdirp.sync(cache) 46 | mkdirp.sync(gitDir) 47 | fs.writeFileSync(path.resolve(pkg, 'package.json'), JSON.stringify({ 48 | author: 'Terin Stock', 49 | name: 'version-no-git-test', 50 | version: '0.0.0', 51 | description: "Test for npm version if git binary doesn't exist" 52 | }), 'utf8') 53 | process.chdir(pkg) 54 | } 55 | -------------------------------------------------------------------------------- /test/tap/install-cli-production-nosave.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | 4 | var mkdirp = require('mkdirp') 5 | var mr = require('npm-registry-mock') 6 | var osenv = require('osenv') 7 | var rimraf = require('rimraf') 8 | var test = require('tap').test 9 | 10 | var common = require('../common-tap.js') 11 | var server 12 | 13 | var pkg = path.join(__dirname, 'install-cli-production-nosave') 14 | 15 | var EXEC_OPTS = { cwd: pkg } 16 | 17 | var PACKAGE_JSON1 = { 18 | name: 'install-cli-production-nosave', 19 | version: '0.0.1', 20 | dependencies: { 21 | } 22 | } 23 | 24 | test('setup', function (t) { 25 | setup() 26 | mr({ port: common.port }, function (er, s) { 27 | t.ifError(er, 'started mock registry') 28 | server = s 29 | t.end() 30 | }) 31 | }) 32 | 33 | test('install --production without --save exits successfully', function (t) { 34 | common.npm( 35 | [ 36 | '--registry', common.registry, 37 | '--loglevel', 'silent', 38 | 'install', '--production', 'underscore' 39 | ], 40 | EXEC_OPTS, 41 | function (err, code) { 42 | t.ifError(err, 'npm install ran without issue') 43 | t.notOk(code, 'npm install exited with code 0') 44 | t.end() 45 | } 46 | ) 47 | }) 48 | 49 | test('cleanup', function (t) { 50 | server.close() 51 | cleanup() 52 | t.end() 53 | }) 54 | 55 | function cleanup () { 56 | process.chdir(osenv.tmpdir()) 57 | rimraf.sync(pkg) 58 | } 59 | 60 | function setup () { 61 | cleanup() 62 | mkdirp.sync(path.resolve(pkg, 'node_modules')) 63 | fs.writeFileSync( 64 | path.join(pkg, 'package.json'), 65 | JSON.stringify(PACKAGE_JSON1, null, 2) 66 | ) 67 | 68 | process.chdir(pkg) 69 | } 70 | -------------------------------------------------------------------------------- /test/tap/ls-top-errors.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var fs = require('fs') 3 | var path = require('path') 4 | 5 | var test = require('tap').test 6 | var mkdirp = require('mkdirp') 7 | var rimraf = require('rimraf') 8 | 9 | var common = require('../common-tap') 10 | 11 | var pkg = path.resolve(__dirname, path.basename(__filename, '.js')) 12 | var pathModA = path.join(pkg, 'node_modules', 'moduleA') 13 | var pathModB = path.join(pkg, 'node_modules', 'moduleB') 14 | 15 | var modA = { 16 | name: 'moduleA', 17 | version: '1.0.0', 18 | _requiredBy: [ '#USER', '/moduleB' ], 19 | dependencies: { 20 | moduleB: '1.0.0' 21 | } 22 | } 23 | var modB = { 24 | name: 'moduleB', 25 | version: '1.0.0', 26 | _requiredBy: [ '/moduleA' ], 27 | dependencies: { 28 | moduleA: '1.0.0' 29 | } 30 | } 31 | 32 | function setup () { 33 | mkdirp.sync(pkg) 34 | fs.writeFileSync( 35 | path.join(pkg, 'package.json'), 36 | '{broken json' 37 | ) 38 | mkdirp.sync(pathModA) 39 | fs.writeFileSync( 40 | path.join(pathModA, 'package.json'), 41 | JSON.stringify(modA, null, 2) 42 | ) 43 | mkdirp.sync(pathModB) 44 | fs.writeFileSync( 45 | path.join(pathModB, 'package.json'), 46 | JSON.stringify(modB, null, 2) 47 | ) 48 | } 49 | 50 | function cleanup () { 51 | rimraf.sync(pkg) 52 | } 53 | 54 | test('setup', function (t) { 55 | cleanup() 56 | setup() 57 | t.end() 58 | }) 59 | 60 | test('ls-top-errors', function (t) { 61 | common.npm(['ls'], {cwd: pkg}, function (er, code, stdout, stderr) { 62 | t.ifErr(er, 'install finished successfully') 63 | t.match(stderr, /Failed to parse json/) 64 | t.end() 65 | }) 66 | }) 67 | 68 | test('cleanup', function (t) { 69 | cleanup() 70 | t.end() 71 | }) 72 | -------------------------------------------------------------------------------- /test/tap/gently-rm-overeager.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var fs = require('graceful-fs') 3 | var test = require('tap').test 4 | var mkdirp = require('mkdirp') 5 | var rimraf = require('rimraf') 6 | 7 | var common = require('../common-tap.js') 8 | 9 | var testdir = path.join(__dirname, path.basename(__filename, '.js')) 10 | var pkg = path.join(testdir, 'gently-rm-overeager') 11 | var dep = path.join(testdir, 'test-whoops') 12 | 13 | var EXEC_OPTS = { cwd: pkg } 14 | 15 | var fixture = { 16 | name: '@test/whoops', 17 | version: '1.0.0', 18 | scripts: { 19 | postinstall: 'echo \'nope\' && exit 1' 20 | } 21 | } 22 | 23 | test('setup', function (t) { 24 | cleanup() 25 | setup() 26 | 27 | return common.npm(['pack', 'file:test-whoops'], {cwd: testdir, stdio: 'inherit'}).spread((code) => { 28 | t.is(code, 0, 'pack') 29 | }) 30 | }) 31 | 32 | test('cache add', function (t) { 33 | common.npm(['install', '--no-save', '../test-whoops-1.0.0.tgz'], EXEC_OPTS, function (er, c) { 34 | t.ifError(er, "test-whoops install didn't explode") 35 | t.ok(c, 'test-whoops install also failed') 36 | fs.readdir(pkg, function (er, files) { 37 | t.ifError(er, 'package directory is still there') 38 | t.deepEqual(files, [], 'no files remain') 39 | t.end() 40 | }) 41 | }) 42 | }) 43 | 44 | test('cleanup', function (t) { 45 | cleanup() 46 | 47 | t.end() 48 | }) 49 | 50 | function cleanup () { 51 | rimraf.sync(testdir) 52 | } 53 | 54 | function setup () { 55 | mkdirp.sync(pkg) 56 | // so it doesn't try to install into npm's own node_modules 57 | mkdirp.sync(path.join(pkg, 'node_modules')) 58 | mkdirp.sync(dep) 59 | fs.writeFileSync(path.join(dep, 'package.json'), JSON.stringify(fixture)) 60 | } 61 | --------------------------------------------------------------------------------