2 // windows: running "npm blah" in this folder will invoke WSH, not node.
3 if (typeof WScript !== "undefined") {
4 WScript.echo("npm does not work when run\n"
5 +"with the Windows Scripting Host\n\n"
6 +"'cd' to a different directory,\n"
7 +"or type 'npm.cmd <args>',\n"
8 +"or type 'node npm <args>'.")
14 // monkey-patch support for 0.6 child processes
15 require('child-process-close')
17 var EventEmitter = require("events").EventEmitter
18 , npm = module.exports = new EventEmitter
19 , config = require("./config.js")
20 , npmconf = require("npmconf")
21 , log = require("npmlog")
22 , fs = require("graceful-fs")
23 , path = require("path")
24 , abbrev = require("abbrev")
25 , which = require("which")
26 , semver = require("semver")
27 , findPrefix = require("./utils/find-prefix.js")
28 , getUid = require("uid-number")
29 , mkdirp = require("mkdirp")
30 , slide = require("slide")
32 , RegClient = require("npm-registry-client")
34 npm.config = {loaded: false}
36 // /usr/local is often a read-only fs, which is not
37 // well handled by node or mkdirp. Just double-check
38 // in the case of errors when making the prefix dirs.
39 function mkdir (p, cb) {
40 mkdirp(p, function (er, made) {
41 // it could be that we couldn't create it, because it
42 // already exists, and is on a read-only fs.
44 return fs.stat(p, function (er2, st) {
45 if (er2 || !st.isDirectory()) return cb(er)
56 var pv = process.version.replace(/^v/, '')
57 // startup, ok to do this synchronously
58 var j = JSON.parse(fs.readFileSync(
59 path.join(__dirname, "../package.json"))+"")
60 npm.version = j.version
61 npm.nodeVersionRequired = j.engines.node
62 if (!semver.satisfies(pv, j.engines.node)) {
63 log.warn("unsupported version", [""
64 ,"npm requires node version: "+j.engines.node
66 ,"which is not satisfactory."
68 ,"Bad things will likely happen. You have been warned."
73 log.info("error reading version", ex)
79 // short names for common things
80 , aliases = { "rm" : "uninstall"
83 , "unlink" : "uninstall"
84 , "remove" : "uninstall"
91 , "isntall" : "install"
102 , "unstar": "star" // same function
105 , "add-user": "adduser"
107 , "find-dupes": "dedupe"
112 , aliasNames = Object.keys(aliases)
113 // these are filenames in .
114 , cmdList = [ "install"
165 , plumbing = [ "build"
171 , fullList = npm.fullList = cmdList.concat(aliasNames).filter(function (c) {
172 return plumbing.indexOf(c) === -1
174 , abbrevs = abbrev(fullList)
176 Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) {
177 Object.defineProperty(npm.commands, c, { get : function () {
178 if (!loaded) throw new Error(
179 "Call npm.load(conf, cb) before using this command.\n"+
180 "See the README.md or cli.js for example usage.")
182 if (c === "la" || c === "ll") {
183 npm.config.set("long", true)
186 if (commandCache[a]) return commandCache[a]
187 var cmd = require(__dirname+"/"+a+".js")
188 commandCache[a] = function () {
189 var args = Array.prototype.slice.call(arguments, 0)
190 if (typeof args[args.length - 1] !== "function") {
193 if (args.length === 1) args.unshift([])
196 Object.keys(cmd).forEach(function (k) {
197 commandCache[a][k] = cmd[k]
199 return commandCache[a]
200 }, enumerable: fullList.indexOf(c) !== -1 })
202 // make css-case commands callable via camelCase as well
203 if (c.match(/\-([a-z])/)) {
204 addCommand(c.replace(/\-([a-z])/g, function (a, b) {
205 return b.toUpperCase()
210 function defaultCb (er, data) {
211 if (er) console.error(er.stack || er.message)
212 else console.log(data)
215 npm.deref = function (c) {
217 if (c.match(/[A-Z]/)) c = c.replace(/([A-Z])/g, function (m) {
218 return "-" + m.toLowerCase()
220 if (plumbing.indexOf(c) !== -1) return c
222 if (aliases[a]) a = aliases[a]
231 function loadCb (er) {
232 loadListeners.forEach(function (cb) {
233 process.nextTick(cb.bind(npm, er, npm))
235 loadListeners.length = 0
238 npm.load = function (cli, cb_) {
239 if (!cb_ && typeof cli === "function") cb_ = cli , cli = {}
240 if (!cb_) cb_ = function () {}
242 loadListeners.push(cb_)
243 if (loaded || loadErr) return cb(loadErr)
250 if (npm.config.get("force")) {
251 log.warn("using --force", "I sure hope you know what you are doing.")
253 npm.config.loaded = true
256 if (onload = onload && npm.config.get("onload-script")) {
267 function load (npm, cli, cb) {
268 which(process.argv[0], function (er, node) {
269 if (!er && node.toUpperCase() !== process.execPath.toUpperCase()) {
270 log.verbose("node symlink", node)
271 process.execPath = node
272 process.installPrefix = path.resolve(node, "..", "..")
276 //console.error("about to look up configs")
278 var builtin = path.resolve(__dirname, "..", "npmrc")
279 npmconf.load(cli, builtin, function (er, conf) {
280 if (er === conf) er = null
284 var color = conf.get("color")
286 log.level = conf.get("loglevel")
287 log.heading = conf.get("heading") || "npm"
288 log.stream = conf.get("logstream")
290 case "always": log.enableColor(); break
291 case false: log.disableColor(); break
295 if (er) return cb(er)
297 // see if we need to color normal output
306 var tty = require("tty")
307 if (process.stdout.isTTY) npm.color = true
308 else if (!tty.isatty) npm.color = true
309 else if (tty.isatty(1)) npm.color = true
310 else npm.color = false
314 // at this point the configs are all set.
315 // go ahead and spin up the registry client.
316 var token = conf.get("_token")
317 if (typeof token === "string") {
319 token = JSON.parse(token)
320 conf.set("_token", token, "user")
322 } catch (e) { token = null }
325 npm.registry = new RegClient(npm.config)
327 // save the token cookie in the config file
328 if (npm.registry.couchLogin) {
329 npm.registry.couchLogin.tokenSet = function (tok) {
330 npm.config.set("_token", tok, "user")
331 // ignore save error. best effort.
332 npm.config.save("user")
336 var umask = npm.config.get("umask")
337 npm.modes = { exec: 0777 & (~umask)
338 , file: 0666 & (~umask)
341 chain([ [ loadPrefix, npm, cli ]
342 , [ setUser, conf, conf.root ]
349 function loadPrefix (npm, conf, cb) {
350 // try to guess at a good node_modules location.
353 if (!Object.prototype.hasOwnProperty.call(conf, "prefix")) {
356 p = npm.config.get("prefix")
358 gp = npm.config.get("prefix")
360 findPrefix(p, function (er, p) {
361 Object.defineProperty(npm, "localPrefix",
362 { get : function () { return p }
363 , set : function (r) { return p = r }
366 // the prefix MUST exist, or else nothing works.
367 if (!npm.config.get("global")) {
374 gp = path.resolve(gp)
375 Object.defineProperty(npm, "globalPrefix",
376 { get : function () { return gp }
377 , set : function (r) { return gp = r }
380 // the prefix MUST exist, or else nothing works.
388 if (er) return cb(errState = er)
389 if (--i === 0) return cb()
394 function loadUid (npm, cb) {
395 // if we're not in unsafe-perm mode, then figure out who
396 // to run stuff as. Do this first, to support `npm update npm -g`
397 if (!npm.config.get("unsafe-perm")) {
398 getUid(npm.config.get("user"), npm.config.get("group"), cb)
404 function setUser (cl, dc, cb) {
405 // If global, leave it as-is.
406 // If not global, then set the user to the owner of the prefix folder.
407 // Just set the default, so it can be overridden.
408 if (cl.get("global")) return cb()
409 if (process.env.SUDO_UID) {
410 dc.user = +(process.env.SUDO_UID)
414 var prefix = path.resolve(cl.get("prefix"))
415 mkdir(prefix, function (er) {
417 log.error("could not create prefix dir", prefix)
420 fs.stat(prefix, function (er, st) {
421 dc.user = st && st.uid
428 Object.defineProperty(npm, "prefix",
429 { get : function () {
430 return npm.config.get("global") ? npm.globalPrefix : npm.localPrefix
432 , set : function (r) {
433 var k = npm.config.get("global") ? "globalPrefix" : "localPrefix"
439 Object.defineProperty(npm, "bin",
440 { get : function () {
441 if (npm.config.get("global")) return npm.globalBin
442 return path.resolve(npm.root, ".bin")
447 Object.defineProperty(npm, "globalBin",
448 { get : function () {
449 var b = npm.globalPrefix
450 if (process.platform !== "win32") b = path.resolve(b, "bin")
455 Object.defineProperty(npm, "dir",
456 { get : function () {
457 if (npm.config.get("global")) return npm.globalDir
458 return path.resolve(npm.prefix, "node_modules")
463 Object.defineProperty(npm, "globalDir",
464 { get : function () {
465 return (process.platform !== "win32")
466 ? path.resolve(npm.globalPrefix, "lib", "node_modules")
467 : path.resolve(npm.globalPrefix, "node_modules")
472 Object.defineProperty(npm, "root",
473 { get : function () { return npm.dir } })
475 Object.defineProperty(npm, "cache",
476 { get : function () { return npm.config.get("cache") }
477 , set : function (r) { return npm.config.set("cache", r) }
482 var crypto = require("crypto")
483 var rand = crypto.randomBytes(6)
487 Object.defineProperty(npm, "tmp",
488 { get : function () {
489 if (!tmpFolder) tmpFolder = "npm-" + process.pid + "-" + rand
490 return path.resolve(npm.config.get("tmp"), tmpFolder)
495 // the better to repl you with
496 Object.getOwnPropertyNames(npm.commands).forEach(function (n) {
497 if (npm.hasOwnProperty(n) || n === "config") return
499 Object.defineProperty(npm, n, { get: function () {
501 var args = Array.prototype.slice.call(arguments, 0)
504 if (args.length === 1 && Array.isArray(args[0])) {
508 if (typeof args[args.length - 1] === "function") {
512 npm.commands[n](args, cb)
514 }, enumerable: false, configurable: true })
517 if (require.main === module) {
518 require("../bin/npm-cli.js")