1 // defaults, types, and shorthands.
4 var path = require("path")
6 , Stream = require("stream").Stream
7 , semver = require("semver")
8 , stableFamily = semver.parse(process.version)
9 , nopt = require("nopt")
11 , osenv = require("osenv")
12 , umask = require("../utils/umask")
16 log = require("npmlog")
18 var util = require("util")
19 log = { warn: function (m) {
20 console.warn(m + " " + util.format.apply(util, [].slice.call(arguments, 1)))
26 function validateUmask (data, k, val) {
27 return umask.validate(data, k, val)
30 function validateSemver (data, k, val) {
31 if (!semver.valid(val)) return false
32 data[k] = semver.valid(val)
35 function validateStream (data, k, val) {
36 if (!(val instanceof Stream)) return false
40 nopt.typeDefs.semver = { type: semver, validate: validateSemver }
41 nopt.typeDefs.Stream = { type: Stream, validate: validateStream }
42 nopt.typeDefs.Umask = { type: Umask, validate: validateUmask }
44 nopt.invalidHandler = function (k, val, type) {
45 log.warn("invalid config", k + "=" + JSON.stringify(val))
47 if (Array.isArray(type)) {
48 if (type.indexOf(url) !== -1) type = url
49 else if (type.indexOf(path) !== -1) type = path
54 log.warn("invalid config", "Must be umask, octal number in range 0000..0777")
57 log.warn("invalid config", "Must be a full url with 'http://'")
60 log.warn("invalid config", "Must be a valid filesystem path")
63 log.warn("invalid config", "Must be a numeric value")
66 log.warn("invalid config", "Must be an instance of the Stream class")
71 if (!stableFamily || (+stableFamily.minor % 2)) stableFamily = null
72 else stableFamily = stableFamily.major + "." + stableFamily.minor
76 var temp = osenv.tmpdir()
77 var home = osenv.home()
79 var uidOrPid = process.getuid ? process.getuid() : process.pid
81 if (home) process.env.HOME = home
82 else home = path.resolve(temp, "npm-" + uidOrPid)
84 var cacheExtra = process.platform === "win32" ? "npm-cache" : ".npm"
85 var cacheRoot = process.platform === "win32" && process.env.APPDATA || home
86 var cache = path.resolve(cacheRoot, cacheExtra)
90 Object.defineProperty(exports, "defaults", {get: function () {
91 if (defaults) return defaults
93 if (process.env.PREFIX) {
94 globalPrefix = process.env.PREFIX
95 } else if (process.platform === "win32") {
96 // c:\node\node.exe --> prefix=c:\node\
97 globalPrefix = path.dirname(process.execPath)
99 // /usr/local/bin/node --> prefix=/usr/local
100 globalPrefix = path.dirname(path.dirname(process.execPath))
102 // destdir only is respected on Unix
103 if (process.env.DESTDIR) {
104 globalPrefix = path.join(process.env.DESTDIR, globalPrefix)
110 , "always-auth" : false
120 , "cache-lock-stale": 60000
121 , "cache-lock-retries": 10
122 , "cache-lock-wait": 10000
124 , "cache-max": Infinity
133 , editor : osenv.editor()
134 , "engine-strict": false
138 , "fetch-retry-factor": 10
139 , "fetch-retry-mintimeout": 10000
140 , "fetch-retry-maxtimeout": 60000
143 , "git-tag-version": true
146 , globalconfig : path.resolve(globalPrefix, "etc", "npmrc")
147 , group : process.platform === "win32" ? 0
148 : process.env.SUDO_GID || (process.getgid && process.getgid())
150 , "if-present": false
151 , "ignore-scripts": false
152 , "init-module": path.resolve(home, ".npm-init.js")
153 , "init-author-name" : ""
154 , "init-author-email" : ""
155 , "init-author-url" : ""
156 , "init-version": "1.0.0"
157 , "init-license": "ISC"
161 , "local-address" : undefined
163 , logstream : process.stderr
167 , "node-version" : process.version
169 , "onload-script" : false
172 , prefix : globalPrefix
173 , production: process.env.NODE_ENV === "production"
174 , "proprietary-attribs": true
176 , "https-proxy" : null
177 , "user-agent" : "npm/{npm-version} "
178 + "node/{node-version} "
181 , "rebuild-bundle" : true
182 , registry : "https://registry.npmjs.org/"
185 , "save-bundle": false
187 , "save-exact" : false
188 , "save-optional" : false
192 , searchexclude: null
194 , shell : osenv.shell()
196 , "sign-git-tag": false
200 , "tag-version-prefix" : "v"
203 , "unsafe-perm" : process.platform === "win32"
204 || process.platform === "cygwin"
205 || !( process.getuid && process.setuid
206 && process.getgid && process.setgid )
207 || process.getuid() !== 0
209 , user : process.platform === "win32" ? 0 : "nobody"
210 , userconfig : path.resolve(home, ".npmrc")
211 , umask: process.umask ? process.umask() : umask.fromString("022")
214 , viewer: process.platform === "win32" ? "browser" : "man"
223 { access : [null, "restricted", "public"]
224 , "always-auth" : Boolean
225 , "bin-links": Boolean
226 , browser : [null, String]
227 , ca: [null, String, Array]
230 , "cache-lock-stale": Number
231 , "cache-lock-retries": Number
232 , "cache-lock-wait": Number
233 , "cache-max": Number
234 , "cache-min": Number
235 , cert: [null, String]
236 , color : ["always", Boolean]
238 , description : Boolean
241 , "engine-strict": Boolean
243 , "fetch-retries": Number
244 , "fetch-retry-factor": Number
245 , "fetch-retry-mintimeout": Number
246 , "fetch-retry-maxtimeout": Number
248 , "git-tag-version": Boolean
250 , globalconfig : path
251 , group : [Number, String]
252 , "https-proxy" : [null, url]
253 , "user-agent" : String
255 , "if-present": Boolean
256 , "ignore-scripts": Boolean
257 , "init-module": path
258 , "init-author-name" : String
259 , "init-author-email" : String
260 , "init-author-url" : ["", url]
261 , "init-license": String
262 , "init-version": semver
264 , key: [null, String]
266 // local-address must be listed as an IP for a local network interface
267 // must be IPv4 due to node bug
268 , "local-address" : getLocalAddresses()
269 , loglevel : ["silent", "error", "warn", "http", "info", "verbose", "silly"]
272 , maxsockets : Number
274 , "node-version" : [null, semver]
276 , "onload-script" : [null, String]
278 , parseable : Boolean
280 , production: Boolean
281 , "proprietary-attribs": Boolean
282 , proxy : [null, false, url] // allow proxy to be disabled explicitly
283 , "rebuild-bundle" : Boolean
284 , registry : [null, url]
287 , "save-bundle": Boolean
288 , "save-dev" : Boolean
289 , "save-exact" : Boolean
290 , "save-optional" : Boolean
291 , "save-prefix": String
293 , searchopts : String
294 , searchexclude: [null, String]
295 , searchsort: [ "name", "-name"
296 , "description", "-description"
297 , "author", "-author"
299 , "keywords", "-keywords" ]
301 , shrinkwrap: Boolean
302 , "sign-git-tag": Boolean
303 , spin: ["always", Boolean]
304 , "strict-ssl": Boolean
308 , "unsafe-perm" : Boolean
310 , user : [Number, String]
314 , "tag-version-prefix" : String
320 function getLocalAddresses () {
322 // #8094: some environments require elevated permissions to enumerate
323 // interfaces, and synchronously throw EPERM when run without
324 // elevated privileges
326 interfaces = os.networkInterfaces()
331 return Object.keys(interfaces).map(function (nic) {
332 return interfaces[nic].filter(function (addr) {
333 return addr.family === 'IPv4'
335 .map(function (addr) {
338 }).reduce(function (curr, next) {
339 return curr.concat(next)
340 }, []).concat(undefined)
344 { s : ["--loglevel", "silent"]
345 , d : ["--loglevel", "info"]
346 , dd : ["--loglevel", "verbose"]
347 , ddd : ["--loglevel", "silly"]
348 , noreg : ["--no-registry"]
349 , N : ["--no-registry"]
350 , reg : ["--registry"]
351 , "no-reg" : ["--no-registry"]
352 , silent : ["--loglevel", "silent"]
353 , verbose : ["--loglevel", "verbose"]
354 , quiet: ["--loglevel", "warn"]
355 , q: ["--loglevel", "warn"]
362 , gangster : ["--force"]
363 , gangsta : ["--force"]
364 , desc : ["--description"]
365 , "no-desc" : ["--no-description"]
366 , "local" : ["--no-global"]
369 , p : ["--parseable"]
370 , porcelain : ["--parseable"]
374 , E : ["--save-exact"]
375 , O : ["--save-optional"]
378 , B : ["--save-bundle"]