• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// defaults, types, and shorthands.
2
3var path = require('path')
4var url = require('url')
5var Stream = require('stream').Stream
6var semver = require('semver')
7var stableFamily = semver.parse(process.version)
8var nopt = require('nopt')
9var os = require('os')
10var osenv = require('osenv')
11var umask = require('../utils/umask')
12var hasUnicode = require('has-unicode')
13
14var log
15try {
16  log = require('npmlog')
17} catch (er) {
18  var util = require('util')
19  log = { warn: function (m) {
20    console.warn(m + ' ' + util.format.apply(util, [].slice.call(arguments, 1)))
21  } }
22}
23
24exports.Umask = Umask
25function Umask () {}
26function validateUmask (data, k, val) {
27  return umask.validate(data, k, val)
28}
29
30function validateSemver (data, k, val) {
31  if (!semver.valid(val)) return false
32  data[k] = semver.valid(val)
33}
34
35function validateStream (data, k, val) {
36  if (!(val instanceof Stream)) return false
37  data[k] = val
38}
39
40nopt.typeDefs.semver = { type: semver, validate: validateSemver }
41nopt.typeDefs.Stream = { type: Stream, validate: validateStream }
42nopt.typeDefs.Umask = { type: Umask, validate: validateUmask }
43
44nopt.invalidHandler = function (k, val, type) {
45  log.warn('invalid config', k + '=' + JSON.stringify(val))
46
47  if (Array.isArray(type)) {
48    if (type.indexOf(url) !== -1) type = url
49    else if (type.indexOf(path) !== -1) type = path
50  }
51
52  switch (type) {
53    case Umask:
54      log.warn('invalid config', 'Must be umask, octal number in range 0000..0777')
55      break
56    case url:
57      log.warn('invalid config', "Must be a full url with 'http://'")
58      break
59    case path:
60      log.warn('invalid config', 'Must be a valid filesystem path')
61      break
62    case Number:
63      log.warn('invalid config', 'Must be a numeric value')
64      break
65    case Stream:
66      log.warn('invalid config', 'Must be an instance of the Stream class')
67      break
68  }
69}
70
71if (!stableFamily || (+stableFamily.minor % 2)) stableFamily = null
72else stableFamily = stableFamily.major + '.' + stableFamily.minor
73
74var defaults
75
76var temp = osenv.tmpdir()
77var home = osenv.home()
78
79var uidOrPid = process.getuid ? process.getuid() : process.pid
80
81if (home) process.env.HOME = home
82else home = path.resolve(temp, 'npm-' + uidOrPid)
83
84var cacheExtra = process.platform === 'win32' ? 'npm-cache' : '.npm'
85var cacheRoot = (process.platform === 'win32' && process.env.APPDATA) || home
86var cache = path.resolve(cacheRoot, cacheExtra)
87
88var globalPrefix
89Object.defineProperty(exports, 'defaults', {get: function () {
90  if (defaults) return defaults
91
92  if (process.env.PREFIX) {
93    globalPrefix = process.env.PREFIX
94  } else if (process.platform === 'win32') {
95    // c:\node\node.exe --> prefix=c:\node\
96    globalPrefix = path.dirname(process.execPath)
97  } else {
98    // /usr/local/bin/node --> prefix=/usr/local
99    globalPrefix = path.dirname(path.dirname(process.execPath))
100
101    // destdir only is respected on Unix
102    if (process.env.DESTDIR) {
103      globalPrefix = path.join(process.env.DESTDIR, globalPrefix)
104    }
105  }
106
107  defaults = {
108    access: null,
109    'allow-same-version': false,
110    'always-auth': false,
111    also: null,
112    audit: true,
113    'audit-level': 'low',
114    'auth-type': 'legacy',
115
116    'before': null,
117    'bin-links': true,
118    browser: null,
119
120    ca: null,
121    cafile: null,
122
123    cache: cache,
124
125    'cache-lock-stale': 60000,
126    'cache-lock-retries': 10,
127    'cache-lock-wait': 10000,
128
129    'cache-max': Infinity,
130    'cache-min': 10,
131
132    cert: null,
133
134    cidr: null,
135
136    color: process.env.NO_COLOR == null,
137    depth: Infinity,
138    description: true,
139    dev: false,
140    'dry-run': false,
141    editor: osenv.editor(),
142    'engine-strict': false,
143    force: false,
144    'format-package-lock': true,
145
146    fund: true,
147
148    'fetch-retries': 2,
149    'fetch-retry-factor': 10,
150    'fetch-retry-mintimeout': 10000,
151    'fetch-retry-maxtimeout': 60000,
152
153    git: 'git',
154    'git-tag-version': true,
155    'commit-hooks': true,
156
157    global: false,
158    globalconfig: path.resolve(globalPrefix, 'etc', 'npmrc'),
159    'global-style': false,
160    group: process.platform === 'win32' ? 0
161      : process.env.SUDO_GID || (process.getgid && process.getgid()),
162    'ham-it-up': false,
163    heading: 'npm',
164    'if-present': false,
165    'ignore-prepublish': false,
166    'ignore-scripts': false,
167    'init-module': path.resolve(home, '.npm-init.js'),
168    'init-author-name': '',
169    'init-author-email': '',
170    'init-author-url': '',
171    'init-version': '1.0.0',
172    'init-license': 'ISC',
173    json: false,
174    key: null,
175    'legacy-bundling': false,
176    link: false,
177    'local-address': undefined,
178    loglevel: 'notice',
179    logstream: process.stderr,
180    'logs-max': 10,
181    long: false,
182    maxsockets: 50,
183    message: '%s',
184    'metrics-registry': null,
185    'node-options': null,
186    'node-version': process.version,
187    'offline': false,
188    'onload-script': false,
189    only: null,
190    optional: true,
191    otp: null,
192    'package-lock': true,
193    'package-lock-only': false,
194    parseable: false,
195    'prefer-offline': false,
196    'prefer-online': false,
197    prefix: globalPrefix,
198    preid: '',
199    production: process.env.NODE_ENV === 'production',
200    'progress': !process.env.TRAVIS && !process.env.CI,
201    proxy: null,
202    'https-proxy': null,
203    'noproxy': null,
204    'user-agent': 'npm/{npm-version} ' +
205                    'node/{node-version} ' +
206                    '{platform} ' +
207                    '{arch} ' +
208                    '{ci}',
209    'read-only': false,
210    'rebuild-bundle': true,
211    registry: 'https://registry.npmjs.org/',
212    rollback: true,
213    save: true,
214    'save-bundle': false,
215    'save-dev': false,
216    'save-exact': false,
217    'save-optional': false,
218    'save-prefix': '^',
219    'save-prod': false,
220    scope: '',
221    'script-shell': null,
222    'scripts-prepend-node-path': 'warn-only',
223    searchopts: '',
224    searchexclude: null,
225    searchlimit: 20,
226    searchstaleness: 15 * 60,
227    'send-metrics': false,
228    shell: osenv.shell(),
229    shrinkwrap: true,
230    'sign-git-commit': false,
231    'sign-git-tag': false,
232    'sso-poll-frequency': 500,
233    'sso-type': 'oauth',
234    'strict-ssl': true,
235    tag: 'latest',
236    'tag-version-prefix': 'v',
237    timing: false,
238    tmp: temp,
239    unicode: hasUnicode(),
240    'unsafe-perm': process.platform === 'win32' ||
241                     process.platform === 'cygwin' ||
242                     !(process.getuid && process.setuid &&
243                       process.getgid && process.setgid) ||
244                     process.getuid() !== 0,
245    'update-notifier': true,
246    usage: false,
247    user: (process.platform === 'win32' || os.type() === 'OS400') ? 0 : 'nobody',
248    userconfig: path.resolve(home, '.npmrc'),
249    umask: process.umask ? process.umask() : umask.fromString('022'),
250    version: false,
251    versions: false,
252    viewer: process.platform === 'win32' ? 'browser' : 'man',
253
254    _exit: true
255  }
256
257  return defaults
258}})
259
260exports.types = {
261  access: [null, 'restricted', 'public'],
262  'allow-same-version': Boolean,
263  'always-auth': Boolean,
264  also: [null, 'dev', 'development'],
265  audit: Boolean,
266  'audit-level': ['low', 'moderate', 'high', 'critical'],
267  'auth-type': ['legacy', 'sso', 'saml', 'oauth'],
268  'before': [null, Date],
269  'bin-links': Boolean,
270  browser: [null, String],
271  ca: [null, String, Array],
272  cafile: path,
273  cache: path,
274  'cache-lock-stale': Number,
275  'cache-lock-retries': Number,
276  'cache-lock-wait': Number,
277  'cache-max': Number,
278  'cache-min': Number,
279  cert: [null, String],
280  cidr: [null, String, Array],
281  color: ['always', Boolean],
282  depth: Number,
283  description: Boolean,
284  dev: Boolean,
285  'dry-run': Boolean,
286  editor: String,
287  'engine-strict': Boolean,
288  force: Boolean,
289  fund: Boolean,
290  'format-package-lock': Boolean,
291  'fetch-retries': Number,
292  'fetch-retry-factor': Number,
293  'fetch-retry-mintimeout': Number,
294  'fetch-retry-maxtimeout': Number,
295  git: String,
296  'git-tag-version': Boolean,
297  'commit-hooks': Boolean,
298  global: Boolean,
299  globalconfig: path,
300  'global-style': Boolean,
301  group: [Number, String],
302  'https-proxy': [null, url],
303  'user-agent': String,
304  'ham-it-up': Boolean,
305  'heading': String,
306  'if-present': Boolean,
307  'ignore-prepublish': Boolean,
308  'ignore-scripts': Boolean,
309  'init-module': path,
310  'init-author-name': String,
311  'init-author-email': String,
312  'init-author-url': ['', url],
313  'init-license': String,
314  'init-version': semver,
315  json: Boolean,
316  key: [null, String],
317  'legacy-bundling': Boolean,
318  link: Boolean,
319  'local-address': getLocalAddresses(),
320  loglevel: ['silent', 'error', 'warn', 'notice', 'http', 'timing', 'info', 'verbose', 'silly'],
321  logstream: Stream,
322  'logs-max': Number,
323  long: Boolean,
324  maxsockets: Number,
325  message: String,
326  'metrics-registry': [null, String],
327  'node-options': [null, String],
328  'node-version': [null, semver],
329  'noproxy': [null, String, Array],
330  offline: Boolean,
331  'onload-script': [null, String],
332  only: [null, 'dev', 'development', 'prod', 'production'],
333  optional: Boolean,
334  'package-lock': Boolean,
335  otp: [null, String],
336  'package-lock-only': Boolean,
337  parseable: Boolean,
338  'prefer-offline': Boolean,
339  'prefer-online': Boolean,
340  prefix: path,
341  preid: String,
342  production: Boolean,
343  progress: Boolean,
344  proxy: [null, false, url], // allow proxy to be disabled explicitly
345  'read-only': Boolean,
346  'rebuild-bundle': Boolean,
347  registry: [null, url],
348  rollback: Boolean,
349  save: Boolean,
350  'save-bundle': Boolean,
351  'save-dev': Boolean,
352  'save-exact': Boolean,
353  'save-optional': Boolean,
354  'save-prefix': String,
355  'save-prod': Boolean,
356  scope: String,
357  'script-shell': [null, String],
358  'scripts-prepend-node-path': [false, true, 'auto', 'warn-only'],
359  searchopts: String,
360  searchexclude: [null, String],
361  searchlimit: Number,
362  searchstaleness: Number,
363  'send-metrics': Boolean,
364  shell: String,
365  shrinkwrap: Boolean,
366  'sign-git-commit': Boolean,
367  'sign-git-tag': Boolean,
368  'sso-poll-frequency': Number,
369  'sso-type': [null, 'oauth', 'saml'],
370  'strict-ssl': Boolean,
371  tag: String,
372  timing: Boolean,
373  tmp: path,
374  unicode: Boolean,
375  'unsafe-perm': Boolean,
376  'update-notifier': Boolean,
377  usage: Boolean,
378  user: [Number, String],
379  userconfig: path,
380  umask: Umask,
381  version: Boolean,
382  'tag-version-prefix': String,
383  versions: Boolean,
384  viewer: String,
385  _exit: Boolean
386}
387
388function getLocalAddresses () {
389  var interfaces
390  // #8094: some environments require elevated permissions to enumerate
391  // interfaces, and synchronously throw EPERM when run without
392  // elevated privileges
393  try {
394    interfaces = os.networkInterfaces()
395  } catch (e) {
396    interfaces = {}
397  }
398
399  return Object.keys(interfaces).map(
400    nic => interfaces[nic].map(({address}) => address)
401  ).reduce((curr, next) => curr.concat(next), []).concat(undefined)
402}
403
404exports.shorthands = {
405  before: ['--enjoy-by'],
406  s: ['--loglevel', 'silent'],
407  d: ['--loglevel', 'info'],
408  dd: ['--loglevel', 'verbose'],
409  ddd: ['--loglevel', 'silly'],
410  noreg: ['--no-registry'],
411  N: ['--no-registry'],
412  reg: ['--registry'],
413  'no-reg': ['--no-registry'],
414  silent: ['--loglevel', 'silent'],
415  verbose: ['--loglevel', 'verbose'],
416  quiet: ['--loglevel', 'warn'],
417  q: ['--loglevel', 'warn'],
418  h: ['--usage'],
419  H: ['--usage'],
420  '?': ['--usage'],
421  help: ['--usage'],
422  v: ['--version'],
423  f: ['--force'],
424  desc: ['--description'],
425  'no-desc': ['--no-description'],
426  'local': ['--no-global'],
427  l: ['--long'],
428  m: ['--message'],
429  p: ['--parseable'],
430  porcelain: ['--parseable'],
431  readonly: ['--read-only'],
432  g: ['--global'],
433  S: ['--save'],
434  D: ['--save-dev'],
435  E: ['--save-exact'],
436  O: ['--save-optional'],
437  P: ['--save-prod'],
438  y: ['--yes'],
439  n: ['--no-yes'],
440  B: ['--save-bundle'],
441  C: ['--prefix']
442}
443