1 | ;(function () {
|
2 |
|
3 |
|
4 | if (typeof WScript !== 'undefined') {
|
5 | WScript.echo(
|
6 | 'npm does not work when run\n' +
|
7 | 'with the Windows Scripting Host\n\n' +
|
8 | '"cd" to a different directory,\n' +
|
9 | 'or type "npm.cmd <args>",\n' +
|
10 | 'or type "node npm <args>".'
|
11 | )
|
12 | WScript.quit(1)
|
13 | return
|
14 | }
|
15 |
|
16 | var unsupported = require('../lib/utils/unsupported.js')
|
17 | unsupported.checkForBrokenNode()
|
18 |
|
19 | var gfs = require('graceful-fs')
|
20 |
|
21 | var fs = gfs.gracefulify(require('fs'))
|
22 |
|
23 | var EventEmitter = require('events').EventEmitter
|
24 | var npm = module.exports = new EventEmitter()
|
25 | var npmconf = require('./config/core.js')
|
26 | var log = require('npmlog')
|
27 |
|
28 | var tty = require('tty')
|
29 | var path = require('path')
|
30 | var abbrev = require('abbrev')
|
31 | var which = require('which')
|
32 | var glob = require('glob')
|
33 | var rimraf = require('rimraf')
|
34 | var lazyProperty = require('lazy-property')
|
35 | var parseJSON = require('./utils/parse-json.js')
|
36 | var aliases = require('./config/cmd-list').aliases
|
37 | var cmdList = require('./config/cmd-list').cmdList
|
38 | var plumbing = require('./config/cmd-list').plumbing
|
39 | var output = require('./utils/output.js')
|
40 | var startMetrics = require('./utils/metrics.js').start
|
41 | var perf = require('./utils/perf.js')
|
42 |
|
43 | perf.emit('time', 'npm')
|
44 | perf.on('timing', function (name, finished) {
|
45 | log.timing(name, 'Completed in', finished + 'ms')
|
46 | })
|
47 |
|
48 | npm.config = {
|
49 | loaded: false,
|
50 | get: function () {
|
51 | throw new Error('npm.load() required')
|
52 | },
|
53 | set: function () {
|
54 | throw new Error('npm.load() required')
|
55 | }
|
56 | }
|
57 |
|
58 | npm.commands = {}
|
59 |
|
60 |
|
61 | npm.limit = {
|
62 | fetch: 10,
|
63 | action: 50
|
64 | }
|
65 |
|
66 |
|
67 | npm.lockfileVersion = 1
|
68 |
|
69 | npm.rollbacks = []
|
70 |
|
71 | try {
|
72 |
|
73 | var j = parseJSON(fs.readFileSync(
|
74 | path.join(__dirname, '../package.json')) + '')
|
75 | npm.name = j.name
|
76 | npm.version = j.version
|
77 | } catch (ex) {
|
78 | try {
|
79 | log.info('error reading version', ex)
|
80 | } catch (er) {}
|
81 | npm.version = ex
|
82 | }
|
83 |
|
84 | var commandCache = {}
|
85 | var aliasNames = Object.keys(aliases)
|
86 |
|
87 | var littleGuys = [ 'isntall', 'verison' ]
|
88 | var fullList = cmdList.concat(aliasNames).filter(function (c) {
|
89 | return plumbing.indexOf(c) === -1
|
90 | })
|
91 | var abbrevs = abbrev(fullList)
|
92 |
|
93 |
|
94 | fullList = npm.fullList = fullList.filter(function (c) {
|
95 | return littleGuys.indexOf(c) === -1
|
96 | })
|
97 |
|
98 | var registryRefer
|
99 | var registryLoaded
|
100 |
|
101 | Object.keys(abbrevs).concat(plumbing).forEach(function addCommand (c) {
|
102 | Object.defineProperty(npm.commands, c, { get: function () {
|
103 | if (!loaded) {
|
104 | throw new Error(
|
105 | 'Call npm.load(config, cb) before using this command.\n' +
|
106 | 'See the README.md or bin/npm-cli.js for example usage.'
|
107 | )
|
108 | }
|
109 | var a = npm.deref(c)
|
110 | if (c === 'la' || c === 'll') {
|
111 | npm.config.set('long', true)
|
112 | }
|
113 |
|
114 | npm.command = c
|
115 | if (commandCache[a]) return commandCache[a]
|
116 |
|
117 | var cmd = require(path.join(__dirname, a + '.js'))
|
118 |
|
119 | commandCache[a] = function () {
|
120 | var args = Array.prototype.slice.call(arguments, 0)
|
121 | if (typeof args[args.length - 1] !== 'function') {
|
122 | args.push(defaultCb)
|
123 | }
|
124 | if (args.length === 1) args.unshift([])
|
125 |
|
126 |
|
127 |
|
128 | Array(args[0]).forEach(function (arg) {
|
129 | if (/^[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/.test(arg)) {
|
130 | log.error('arg', 'Argument starts with non-ascii dash, this is probably invalid:', arg)
|
131 | }
|
132 | })
|
133 |
|
134 | if (!registryRefer) {
|
135 | registryRefer = [a].concat(args[0]).map(function (arg) {
|
136 |
|
137 |
|
138 | if (arg && arg.match && arg.match(/\/|\\/)) {
|
139 | return '[REDACTED]'
|
140 | } else {
|
141 | return arg
|
142 | }
|
143 | }).filter(function (arg) {
|
144 | return arg && arg.match
|
145 | }).join(' ')
|
146 | if (registryLoaded) npm.registry.refer = registryRefer
|
147 | }
|
148 |
|
149 | cmd.apply(npm, args)
|
150 | }
|
151 |
|
152 | Object.keys(cmd).forEach(function (k) {
|
153 | commandCache[a][k] = cmd[k]
|
154 | })
|
155 |
|
156 | return commandCache[a]
|
157 | }, enumerable: fullList.indexOf(c) !== -1, configurable: true })
|
158 |
|
159 |
|
160 | if (c.match(/\-([a-z])/)) {
|
161 | addCommand(c.replace(/\-([a-z])/g, function (a, b) {
|
162 | return b.toUpperCase()
|
163 | }))
|
164 | }
|
165 | })
|
166 |
|
167 | function defaultCb (er, data) {
|
168 | log.disableProgress()
|
169 | if (er) console.error(er.stack || er.message)
|
170 | else output(data)
|
171 | }
|
172 |
|
173 | npm.deref = function (c) {
|
174 | if (!c) return ''
|
175 | if (c.match(/[A-Z]/)) {
|
176 | c = c.replace(/([A-Z])/g, function (m) {
|
177 | return '-' + m.toLowerCase()
|
178 | })
|
179 | }
|
180 | if (plumbing.indexOf(c) !== -1) return c
|
181 | var a = abbrevs[c]
|
182 | if (aliases[a]) a = aliases[a]
|
183 | return a
|
184 | }
|
185 |
|
186 | var loaded = false
|
187 | var loading = false
|
188 | var loadErr = null
|
189 | var loadListeners = []
|
190 |
|
191 | function loadCb (er) {
|
192 | loadListeners.forEach(function (cb) {
|
193 | process.nextTick(cb.bind(npm, er, npm))
|
194 | })
|
195 | loadListeners.length = 0
|
196 | }
|
197 |
|
198 | npm.load = function (cli, cb_) {
|
199 | if (!cb_ && typeof cli === 'function') {
|
200 | cb_ = cli
|
201 | cli = {}
|
202 | }
|
203 | if (!cb_) cb_ = function () {}
|
204 | if (!cli) cli = {}
|
205 | loadListeners.push(cb_)
|
206 | if (loaded || loadErr) return cb(loadErr)
|
207 | if (loading) return
|
208 | loading = true
|
209 | var onload = true
|
210 |
|
211 | function cb (er) {
|
212 | if (loadErr) return
|
213 | loadErr = er
|
214 | if (er) return cb_(er)
|
215 | log.notice('BETA', 'npm5 is beta software. Please see https://github.com/npm/npm/issues/16510 for known issues, and please file a new one if you find something new.')
|
216 | if (npm.config.get('force')) {
|
217 | log.warn('using --force', 'I sure hope you know what you are doing.')
|
218 | }
|
219 | npm.config.loaded = true
|
220 | loaded = true
|
221 | loadCb(loadErr = er)
|
222 | onload = onload && npm.config.get('onload-script')
|
223 | if (onload) {
|
224 | try {
|
225 | require(onload)
|
226 | } catch (err) {
|
227 | log.warn('onload-script', 'failed to require onload script', onload)
|
228 | log.warn('onload-script', err)
|
229 | }
|
230 | onload = false
|
231 | }
|
232 | }
|
233 |
|
234 | log.pause()
|
235 |
|
236 | load(npm, cli, cb)
|
237 | }
|
238 |
|
239 | function load (npm, cli, cb) {
|
240 | which(process.argv[0], function (er, node) {
|
241 | if (!er && node.toUpperCase() !== process.execPath.toUpperCase()) {
|
242 | log.verbose('node symlink', node)
|
243 | process.execPath = node
|
244 | process.installPrefix = path.resolve(node, '..', '..')
|
245 | }
|
246 |
|
247 |
|
248 | var builtin = path.resolve(__dirname, '..', 'npmrc')
|
249 | npmconf.load(cli, builtin, function (er, config) {
|
250 | if (er === config) er = null
|
251 |
|
252 | npm.config = config
|
253 | if (er) return cb(er)
|
254 |
|
255 |
|
256 |
|
257 |
|
258 | if (!config.get('global') &&
|
259 | config.sources.project &&
|
260 | config.sources.project.type !== 'ini') {
|
261 | log.verbose(
|
262 | 'config',
|
263 | 'Skipping project config: %s. (matches userconfig)',
|
264 | config.localPrefix + '/.npmrc'
|
265 | )
|
266 | }
|
267 |
|
268 |
|
269 | var ua = config.get('user-agent') || ''
|
270 | ua = ua.replace(/\{node-version\}/gi, process.version)
|
271 | ua = ua.replace(/\{npm-version\}/gi, npm.version)
|
272 | ua = ua.replace(/\{platform\}/gi, process.platform)
|
273 | ua = ua.replace(/\{arch\}/gi, process.arch)
|
274 | config.set('user-agent', ua)
|
275 |
|
276 | if (config.get('metrics-registry') == null) {
|
277 | config.set('metrics-registry', config.get('registry'))
|
278 | }
|
279 |
|
280 | var color = config.get('color')
|
281 |
|
282 | log.level = config.get('loglevel')
|
283 | log.heading = config.get('heading') || 'npm'
|
284 | log.stream = config.get('logstream')
|
285 |
|
286 | switch (color) {
|
287 | case 'always':
|
288 | log.enableColor()
|
289 | npm.color = true
|
290 | break
|
291 | case false:
|
292 | log.disableColor()
|
293 | npm.color = false
|
294 | break
|
295 | default:
|
296 | if (process.stdout.isTTY) npm.color = true
|
297 | else if (!tty.isatty) npm.color = true
|
298 | else if (tty.isatty(1)) npm.color = true
|
299 | else npm.color = false
|
300 | break
|
301 | }
|
302 |
|
303 | if (config.get('unicode')) {
|
304 | log.enableUnicode()
|
305 | } else {
|
306 | log.disableUnicode()
|
307 | }
|
308 |
|
309 | if (config.get('progress') && (process.stderr.isTTY || (tty.isatty && tty.isatty(2)))) {
|
310 | log.enableProgress()
|
311 | } else {
|
312 | log.disableProgress()
|
313 | }
|
314 |
|
315 | glob(path.resolve(npm.cache, '_logs', '*-debug.log'), function (er, files) {
|
316 | if (er) return cb(er)
|
317 |
|
318 | while (files.length >= npm.config.get('logs-max')) {
|
319 | rimraf.sync(files[0])
|
320 | files.splice(0, 1)
|
321 | }
|
322 | })
|
323 |
|
324 | log.resume()
|
325 |
|
326 | var umask = npm.config.get('umask')
|
327 | npm.modes = {
|
328 | exec: parseInt('0777', 8) & (~umask),
|
329 | file: parseInt('0666', 8) & (~umask),
|
330 | umask: umask
|
331 | }
|
332 |
|
333 | var gp = Object.getOwnPropertyDescriptor(config, 'globalPrefix')
|
334 | Object.defineProperty(npm, 'globalPrefix', gp)
|
335 |
|
336 | var lp = Object.getOwnPropertyDescriptor(config, 'localPrefix')
|
337 | Object.defineProperty(npm, 'localPrefix', lp)
|
338 |
|
339 | config.set('scope', scopeifyScope(config.get('scope')))
|
340 | npm.projectScope = config.get('scope') ||
|
341 | scopeifyScope(getProjectScope(npm.prefix))
|
342 |
|
343 |
|
344 |
|
345 | lazyProperty(npm, 'registry', function () {
|
346 | registryLoaded = true
|
347 | var RegClient = require('npm-registry-client')
|
348 | var registry = new RegClient(adaptClientConfig(npm.config))
|
349 | registry.version = npm.version
|
350 | registry.refer = registryRefer
|
351 | return registry
|
352 | })
|
353 |
|
354 | startMetrics()
|
355 |
|
356 | return cb(null, npm)
|
357 | })
|
358 | })
|
359 | }
|
360 |
|
361 | Object.defineProperty(npm, 'prefix',
|
362 | {
|
363 | get: function () {
|
364 | return npm.config.get('global') ? npm.globalPrefix : npm.localPrefix
|
365 | },
|
366 | set: function (r) {
|
367 | var k = npm.config.get('global') ? 'globalPrefix' : 'localPrefix'
|
368 | npm[k] = r
|
369 | return r
|
370 | },
|
371 | enumerable: true
|
372 | })
|
373 |
|
374 | Object.defineProperty(npm, 'bin',
|
375 | {
|
376 | get: function () {
|
377 | if (npm.config.get('global')) return npm.globalBin
|
378 | return path.resolve(npm.root, '.bin')
|
379 | },
|
380 | enumerable: true
|
381 | })
|
382 |
|
383 | Object.defineProperty(npm, 'globalBin',
|
384 | {
|
385 | get: function () {
|
386 | var b = npm.globalPrefix
|
387 | if (process.platform !== 'win32') b = path.resolve(b, 'bin')
|
388 | return b
|
389 | }
|
390 | })
|
391 |
|
392 | Object.defineProperty(npm, 'dir',
|
393 | {
|
394 | get: function () {
|
395 | if (npm.config.get('global')) return npm.globalDir
|
396 | return path.resolve(npm.prefix, 'node_modules')
|
397 | },
|
398 | enumerable: true
|
399 | })
|
400 |
|
401 | Object.defineProperty(npm, 'globalDir',
|
402 | {
|
403 | get: function () {
|
404 | return (process.platform !== 'win32')
|
405 | ? path.resolve(npm.globalPrefix, 'lib', 'node_modules')
|
406 | : path.resolve(npm.globalPrefix, 'node_modules')
|
407 | },
|
408 | enumerable: true
|
409 | })
|
410 |
|
411 | Object.defineProperty(npm, 'root',
|
412 | { get: function () { return npm.dir } })
|
413 |
|
414 | Object.defineProperty(npm, 'cache',
|
415 | { get: function () { return npm.config.get('cache') },
|
416 | set: function (r) { return npm.config.set('cache', r) },
|
417 | enumerable: true
|
418 | })
|
419 |
|
420 | var tmpFolder
|
421 | var rand = require('crypto').randomBytes(4).toString('hex')
|
422 | Object.defineProperty(npm, 'tmp',
|
423 | {
|
424 | get: function () {
|
425 | if (!tmpFolder) tmpFolder = 'npm-' + process.pid + '-' + rand
|
426 | return path.resolve(npm.config.get('tmp'), tmpFolder)
|
427 | },
|
428 | enumerable: true
|
429 | })
|
430 |
|
431 |
|
432 | Object.getOwnPropertyNames(npm.commands).forEach(function (n) {
|
433 | if (npm.hasOwnProperty(n) || n === 'config') return
|
434 |
|
435 | Object.defineProperty(npm, n, { get: function () {
|
436 | return function () {
|
437 | var args = Array.prototype.slice.call(arguments, 0)
|
438 | var cb = defaultCb
|
439 |
|
440 | if (args.length === 1 && Array.isArray(args[0])) {
|
441 | args = args[0]
|
442 | }
|
443 |
|
444 | if (typeof args[args.length - 1] === 'function') {
|
445 | cb = args.pop()
|
446 | }
|
447 | npm.commands[n](args, cb)
|
448 | }
|
449 | }, enumerable: false, configurable: true })
|
450 | })
|
451 |
|
452 | if (require.main === module) {
|
453 | require('../bin/npm-cli.js')
|
454 | }
|
455 |
|
456 | function scopeifyScope (scope) {
|
457 | return (!scope || scope[0] === '@') ? scope : ('@' + scope)
|
458 | }
|
459 |
|
460 | function getProjectScope (prefix) {
|
461 | try {
|
462 | var pkg = JSON.parse(fs.readFileSync(path.join(prefix, 'package.json')))
|
463 | if (typeof pkg.name !== 'string') return ''
|
464 | var sep = pkg.name.indexOf('/')
|
465 | if (sep === -1) return ''
|
466 | return pkg.name.slice(0, sep)
|
467 | } catch (ex) {
|
468 | return ''
|
469 | }
|
470 | }
|
471 |
|
472 | function adaptClientConfig (config) {
|
473 | return {
|
474 | proxy: {
|
475 | http: config.get('proxy'),
|
476 | https: config.get('https-proxy'),
|
477 | localAddress: config.get('local-address')
|
478 | },
|
479 | ssl: {
|
480 | certificate: config.get('cert'),
|
481 | key: config.get('key'),
|
482 | ca: config.get('ca'),
|
483 | strict: config.get('strict-ssl')
|
484 | },
|
485 | retry: {
|
486 | retries: config.get('fetch-retries'),
|
487 | factor: config.get('fetch-retry-factor'),
|
488 | minTimeout: config.get('fetch-retry-mintimeout'),
|
489 | maxTimeout: config.get('fetch-retry-maxtimeout')
|
490 | },
|
491 | userAgent: config.get('user-agent'),
|
492 | log: log,
|
493 | defaultTag: config.get('tag'),
|
494 | maxSockets: config.get('maxsockets'),
|
495 | scope: npm.projectScope
|
496 | }
|
497 | }
|
498 | })()
|