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 var EventEmitter = require("events").EventEmitter
15 , npm = module.exports = new EventEmitter()
16 , npmconf = require("./config/core.js")
17 , log = require("npmlog")
18 , gfs = require('graceful-fs')
19 , fs = gfs.gracefulify(require('fs'))
20 , path = require("path")
21 , abbrev = require("abbrev")
22 , which = require("which")
23 , CachingRegClient = require("./cache/caching-client.js")
24 , charSpin = require("char-spinner")
29 throw new Error('npm.load() required')
32 throw new Error('npm.load() required')
41 // startup, ok to do this synchronously
42 var j = JSON.parse(fs.readFileSync(
43 path.join(__dirname, "../package.json"))+"")
44 npm.version = j.version
47 log.info("error reading version", ex)
53 // short names for common things
54 , aliases = { "rm" : "uninstall"
57 , "unlink" : "uninstall"
58 , "remove" : "uninstall"
65 , "isntall" : "install"
67 , "upgrade" : "update"
69 , "dist-tags" : "dist-tag"
78 , "unstar": "star" // same function
81 , "add-user": "adduser"
84 , "find-dupes": "dedupe"
87 , "verison": "version"
90 , aliasNames = Object.keys(aliases)
91 // these are filenames in .
92 , cmdList = [ "install"
147 , plumbing = [ "build"
153 , littleGuys = [ "isntall", "verison" ]
154 , fullList = cmdList.concat(aliasNames).filter(function (c) {
155 return plumbing.indexOf(c) === -1
157 , abbrevs = abbrev(fullList)
159 // we have our reasons
160 fullList = npm.fullList = fullList.filter(function (c) {
161 return littleGuys.indexOf(c) === -1
167 , start: function () {
168 if (npm.spinner.int) return
169 var c = npm.config.get("spin")
171 var stream = npm.config.get("logstream")
172 var opt = { tty: c !== "always", stream: stream }
173 opt.cleanup = !npm.spinner.started
174 npm.spinner.int = charSpin(opt)
175 npm.spinner.started = true
177 , stop: function () {
178 clearInterval(npm.spinner.int)
179 npm.spinner.int = null
183 Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) {
184 Object.defineProperty(npm.commands, c, { get : function () {
185 if (!loaded) throw new Error(
186 "Call npm.load(config, cb) before using this command.\n"+
187 "See the README.md or cli.js for example usage.")
189 if (c === "la" || c === "ll") {
190 npm.config.set("long", true)
194 if (commandCache[a]) return commandCache[a]
196 var cmd = require(__dirname+"/"+a+".js")
198 commandCache[a] = function () {
199 var args = Array.prototype.slice.call(arguments, 0)
200 if (typeof args[args.length - 1] !== "function") {
203 if (args.length === 1) args.unshift([])
205 npm.registry.version = npm.version
206 if (!npm.registry.refer) {
207 npm.registry.refer = [a].concat(args[0]).map(function (arg) {
208 // exclude anything that might be a URL, path, or private module
209 // Those things will always have a slash in them somewhere
210 if (arg && arg.match && arg.match(/\/|\\/)) {
215 }).filter(function (arg) {
216 return arg && arg.match
223 Object.keys(cmd).forEach(function (k) {
224 commandCache[a][k] = cmd[k]
227 return commandCache[a]
228 }, enumerable: fullList.indexOf(c) !== -1, configurable: true })
230 // make css-case commands callable via camelCase as well
231 if (c.match(/\-([a-z])/)) {
232 addCommand(c.replace(/\-([a-z])/g, function (a, b) {
233 return b.toUpperCase()
238 function defaultCb (er, data) {
239 if (er) console.error(er.stack || er.message)
240 else console.log(data)
243 npm.deref = function (c) {
245 if (c.match(/[A-Z]/)) c = c.replace(/([A-Z])/g, function (m) {
246 return "-" + m.toLowerCase()
248 if (plumbing.indexOf(c) !== -1) return c
250 if (aliases[a]) a = aliases[a]
259 function loadCb (er) {
260 loadListeners.forEach(function (cb) {
261 process.nextTick(cb.bind(npm, er, npm))
263 loadListeners.length = 0
266 npm.load = function (cli, cb_) {
267 if (!cb_ && typeof cli === "function") cb_ = cli , cli = {}
268 if (!cb_) cb_ = function () {}
270 loadListeners.push(cb_)
271 if (loaded || loadErr) return cb(loadErr)
279 if (er) return cb_(er)
280 if (npm.config.get("force")) {
281 log.warn("using --force", "I sure hope you know what you are doing.")
283 npm.config.loaded = true
286 onload = onload && npm.config.get('onload-script')
291 log.warn('onload-script', 'failed to require onload script', onload)
292 log.warn('onload-script', err)
303 function load (npm, cli, cb) {
304 which(process.argv[0], function (er, node) {
305 if (!er && node.toUpperCase() !== process.execPath.toUpperCase()) {
306 log.verbose("node symlink", node)
307 process.execPath = node
308 process.installPrefix = path.resolve(node, "..", "..")
312 //console.error("about to look up configs")
314 var builtin = path.resolve(__dirname, "..", "npmrc")
315 npmconf.load(cli, builtin, function (er, config) {
316 if (er === config) er = null
319 if (er) return cb(er)
321 // if the "project" config is not a filename, and we're
322 // not in global mode, then that means that it collided
323 // with either the default or effective userland config
324 if (!config.get("global")
325 && config.sources.project
326 && config.sources.project.type !== "ini") {
328 , "Skipping project config: %s. "
329 + "(matches userconfig)"
330 , config.localPrefix + "/.npmrc")
333 // Include npm-version and node-version in user-agent
334 var ua = config.get("user-agent") || ""
335 ua = ua.replace(/\{node-version\}/gi, process.version)
336 ua = ua.replace(/\{npm-version\}/gi, npm.version)
337 ua = ua.replace(/\{platform\}/gi, process.platform)
338 ua = ua.replace(/\{arch\}/gi, process.arch)
339 config.set("user-agent", ua)
341 var color = config.get("color")
343 log.level = config.get("loglevel")
344 log.heading = config.get("heading") || "npm"
345 log.stream = config.get("logstream")
357 var tty = require("tty")
358 if (process.stdout.isTTY) npm.color = true
359 else if (!tty.isatty) npm.color = true
360 else if (tty.isatty(1)) npm.color = true
361 else npm.color = false
367 // at this point the configs are all set.
368 // go ahead and spin up the registry client.
369 npm.registry = new CachingRegClient(npm.config)
371 var umask = npm.config.get("umask")
372 npm.modes = { exec: 0777 & (~umask)
373 , file: 0666 & (~umask)
376 var gp = Object.getOwnPropertyDescriptor(config, "globalPrefix")
377 Object.defineProperty(npm, "globalPrefix", gp)
379 var lp = Object.getOwnPropertyDescriptor(config, "localPrefix")
380 Object.defineProperty(npm, "localPrefix", lp)
387 Object.defineProperty(npm, "prefix",
388 { get : function () {
389 return npm.config.get("global") ? npm.globalPrefix : npm.localPrefix
391 , set : function (r) {
392 var k = npm.config.get("global") ? "globalPrefix" : "localPrefix"
398 Object.defineProperty(npm, "bin",
399 { get : function () {
400 if (npm.config.get("global")) return npm.globalBin
401 return path.resolve(npm.root, ".bin")
406 Object.defineProperty(npm, "globalBin",
407 { get : function () {
408 var b = npm.globalPrefix
409 if (process.platform !== "win32") b = path.resolve(b, "bin")
414 Object.defineProperty(npm, "dir",
415 { get : function () {
416 if (npm.config.get("global")) return npm.globalDir
417 return path.resolve(npm.prefix, "node_modules")
422 Object.defineProperty(npm, "globalDir",
423 { get : function () {
424 return (process.platform !== "win32")
425 ? path.resolve(npm.globalPrefix, "lib", "node_modules")
426 : path.resolve(npm.globalPrefix, "node_modules")
431 Object.defineProperty(npm, "root",
432 { get : function () { return npm.dir } })
434 Object.defineProperty(npm, "cache",
435 { get : function () { return npm.config.get("cache") }
436 , set : function (r) { return npm.config.set("cache", r) }
441 var rand = require("crypto").randomBytes(4).toString("hex")
442 Object.defineProperty(npm, "tmp",
443 { get : function () {
444 if (!tmpFolder) tmpFolder = "npm-" + process.pid + "-" + rand
445 return path.resolve(npm.config.get("tmp"), tmpFolder)
450 // the better to repl you with
451 Object.getOwnPropertyNames(npm.commands).forEach(function (n) {
452 if (npm.hasOwnProperty(n) || n === "config") return
454 Object.defineProperty(npm, n, { get: function () {
456 var args = Array.prototype.slice.call(arguments, 0)
459 if (args.length === 1 && Array.isArray(args[0])) {
463 if (typeof args[args.length - 1] === "function") {
467 npm.commands[n](args, cb)
469 }, enumerable: false, configurable: true })
472 if (require.main === module) {
473 require("../bin/npm-cli.js")