pacote 12.0.3 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -146,10 +146,6 @@ resolved, and other properties, as they are determined.
146
146
  `0o666`. See "Extracted File Modes" below.
147
147
  * `dmode` Minimum permission mode for extracted directories. Defaults to
148
148
  `0o777`. See "Extracted File Modes" below.
149
- * `log` A logger object with methods for various log levels. Typically,
150
- this will be [`npmlog`](http://npm.im/npmlog) in the npm CLI use case,
151
- but if not specified, the default is a logger that emits `'log'` events
152
- on the `process` object.
153
149
  * `preferOnline` Prefer to revalidate cache entries, even when it would not
154
150
  be strictly necessary. Default `false`.
155
151
  * `before` When picking a manifest from a packument, only consider
@@ -162,11 +158,16 @@ resolved, and other properties, as they are determined.
162
158
  including information not strictly required for installation (author,
163
159
  description, etc.) Defaults to `true` when `before` is set, since the
164
160
  version publish time is part of the extended packument metadata.
161
+ * `fullReadJson` Use the slower `read-package-json` package insted of
162
+ `read-package-json-fast` in order to include extra fields like "readme" in
163
+ the manifest. Defaults to `false`.
165
164
  * `packumentCache` For registry packuments only, you may provide a `Map`
166
165
  object which will be used to cache packument requests between pacote
167
166
  calls. This allows you to easily avoid hitting the registry multiple
168
167
  times (even just to validate the cache) for a given packument, since it
169
168
  is unlikely to change in the span of a single command.
169
+ * `silent` A boolean that determines whether the banner is displayed
170
+ when calling `@npmcli/run-script`.
170
171
 
171
172
 
172
173
  ### Advanced API
package/lib/bin.js CHANGED
@@ -4,26 +4,28 @@ const run = conf => {
4
4
  const pacote = require('../')
5
5
  switch (conf._[0]) {
6
6
  case 'resolve':
7
- if (conf.long)
7
+ case 'manifest':
8
+ case 'packument':
9
+ if (conf._[0] === 'resolve' && conf.long) {
8
10
  return pacote.manifest(conf._[1], conf).then(mani => ({
9
11
  resolved: mani._resolved,
10
12
  integrity: mani._integrity,
11
13
  from: mani._from,
12
14
  }))
13
- case 'manifest':
14
- case 'packument':
15
+ }
15
16
  return pacote[conf._[0]](conf._[1], conf)
16
17
 
17
18
  case 'tarball':
18
19
  if (!conf._[2] || conf._[2] === '-') {
19
20
  return pacote.tarball.stream(conf._[1], stream => {
20
21
  stream.pipe(conf.testStdout ||
21
- /* istanbul ignore next */ process.stdout)
22
+ /* istanbul ignore next */ process.stdout)
22
23
  // make sure it resolves something falsey
23
24
  return stream.promise().then(() => {})
24
25
  }, conf)
25
- } else
26
+ } else {
26
27
  return pacote.tarball.file(conf._[1], conf._[2], conf)
28
+ }
27
29
 
28
30
  case 'extract':
29
31
  return pacote.extract(conf._[1], conf._[2], conf)
@@ -81,8 +83,9 @@ const pretty = (conf, result) =>
81
83
  let addedLogListener = false
82
84
  const main = args => {
83
85
  const conf = parse(args)
84
- if (conf.help || conf.h)
86
+ if (conf.help || conf.h) {
85
87
  return console.log(usage())
88
+ }
86
89
 
87
90
  if (!addedLogListener) {
88
91
  process.on('log', console.error)
@@ -121,14 +124,14 @@ const parse = args => {
121
124
  }
122
125
  let dashdash = false
123
126
  args.forEach(arg => {
124
- if (dashdash)
127
+ if (dashdash) {
125
128
  conf._.push(arg)
126
- else if (arg === '--')
129
+ } else if (arg === '--') {
127
130
  dashdash = true
128
- else if (arg === '-h')
131
+ } else if (arg === '-h') {
129
132
  conf.help = true
130
- else if (/^--/.test(arg)) {
131
- const {key, value} = parseArg(arg)
133
+ } else if (/^--/.test(arg)) {
134
+ const { key, value } = parseArg(arg)
132
135
  conf[key] = value
133
136
  } else {
134
137
  conf._.push(arg)
@@ -137,9 +140,9 @@ const parse = args => {
137
140
  return conf
138
141
  }
139
142
 
140
- if (module === require.main)
143
+ if (module === require.main) {
141
144
  main(process.argv.slice(2))
142
- else
145
+ } else {
143
146
  module.exports = {
144
147
  main,
145
148
  run,
@@ -147,3 +150,4 @@ else
147
150
  parseArg,
148
151
  parse,
149
152
  }
153
+ }
package/lib/dir.js CHANGED
@@ -1,14 +1,12 @@
1
1
  const Fetcher = require('./fetcher.js')
2
2
  const FileFetcher = require('./file.js')
3
- const cacache = require('cacache')
4
3
  const Minipass = require('minipass')
5
- const { promisify } = require('util')
6
- const readPackageJson = require('read-package-json-fast')
7
4
  const tarCreateOptions = require('./util/tar-create-options.js')
8
5
  const packlist = require('npm-packlist')
9
6
  const tar = require('tar')
10
7
  const _prepareDir = Symbol('_prepareDir')
11
8
  const { resolve } = require('path')
9
+ const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
12
10
 
13
11
  const runScript = require('@npmcli/run-script')
14
12
 
@@ -31,18 +29,18 @@ class DirFetcher extends Fetcher {
31
29
 
32
30
  [_prepareDir] () {
33
31
  return this.manifest().then(mani => {
34
- if (!mani.scripts || !mani.scripts.prepare)
32
+ if (!mani.scripts || !mani.scripts.prepare) {
35
33
  return
34
+ }
36
35
 
37
36
  // we *only* run prepare.
38
37
  // pre/post-pack is run by the npm CLI for publish and pack,
39
38
  // but this function is *also* run when installing git deps
40
39
  const stdio = this.opts.foregroundScripts ? 'inherit' : 'pipe'
41
40
 
42
- // hide the banner if loglevel is silent, or if prepare running
41
+ // hide the banner if silent opt is passed in, or if prepare running
43
42
  // in the background.
44
- const banner = this.opts.log && this.opts.log.level === 'silent' ? false
45
- : stdio === 'inherit'
43
+ const banner = this.opts.silent ? false : stdio === 'inherit'
46
44
 
47
45
  return runScript({
48
46
  pkg: mani,
@@ -76,10 +74,11 @@ class DirFetcher extends Fetcher {
76
74
  }
77
75
 
78
76
  manifest () {
79
- if (this.package)
77
+ if (this.package) {
80
78
  return Promise.resolve(this.package)
79
+ }
81
80
 
82
- return readPackageJson(this.resolved + '/package.json')
81
+ return this[_readPackageJson](this.resolved + '/package.json')
83
82
  .then(mani => this.package = {
84
83
  ...mani,
85
84
  _integrity: this.integrity && String(this.integrity),
package/lib/fetcher.js CHANGED
@@ -9,12 +9,15 @@ const { promisify } = require('util')
9
9
  const { basename, dirname } = require('path')
10
10
  const rimraf = promisify(require('rimraf'))
11
11
  const tar = require('tar')
12
- const procLog = require('./util/proc-log.js')
12
+ const log = require('proc-log')
13
13
  const retry = require('promise-retry')
14
14
  const fsm = require('fs-minipass')
15
15
  const cacache = require('cacache')
16
16
  const isPackageBin = require('./util/is-package-bin.js')
17
+ const removeTrailingSlashes = require('./util/trailing-slashes.js')
17
18
  const getContents = require('@npmcli/installed-package-contents')
19
+ const readPackageJsonFast = require('read-package-json-fast')
20
+ const readPackageJson = promisify(require('read-package-json'))
18
21
 
19
22
  // we only change ownership on unix platforms, and only if uid is 0
20
23
  const selfOwner = process.getuid && process.getuid() === 0 ? {
@@ -41,11 +44,13 @@ const _assertType = Symbol('_assertType')
41
44
  const _tarballFromCache = Symbol('_tarballFromCache')
42
45
  const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
43
46
  const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
47
+ const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
44
48
 
45
49
  class FetcherBase {
46
50
  constructor (spec, opts) {
47
- if (!opts || typeof opts !== 'object')
51
+ if (!opts || typeof opts !== 'object') {
48
52
  throw new TypeError('options object is required')
53
+ }
49
54
  this.spec = npa(spec, opts.where)
50
55
 
51
56
  this.allowGitIgnore = !!opts.allowGitIgnore
@@ -62,7 +67,7 @@ class FetcherBase {
62
67
  this[_assertType]()
63
68
  // clone the opts object so that others aren't upset when we mutate it
64
69
  // by adding/modifying the integrity value.
65
- this.opts = {...opts}
70
+ this.opts = { ...opts }
66
71
 
67
72
  this.cache = opts.cache || cacheDir()
68
73
  this.resolved = opts.resolved || null
@@ -72,8 +77,9 @@ class FetcherBase {
72
77
  // is no longer strong enough.
73
78
  this.defaultIntegrityAlgorithm = opts.defaultIntegrityAlgorithm || 'sha512'
74
79
 
75
- if (typeof opts.integrity === 'string')
80
+ if (typeof opts.integrity === 'string') {
76
81
  this.opts.integrity = ssri.parse(opts.integrity)
82
+ }
77
83
 
78
84
  this.package = null
79
85
  this.type = this.constructor.name
@@ -85,7 +91,6 @@ class FetcherBase {
85
91
  // the process's umask setting do its job. but if configured, we do
86
92
  // respect it.
87
93
  this.umask = opts.umask || 0
88
- this.log = opts.log || procLog
89
94
 
90
95
  this.preferOnline = !!opts.preferOnline
91
96
  this.preferOffline = !!opts.preferOffline
@@ -93,10 +98,15 @@ class FetcherBase {
93
98
 
94
99
  this.before = opts.before
95
100
  this.fullMetadata = this.before ? true : !!opts.fullMetadata
101
+ this.fullReadJson = !!opts.fullReadJson
102
+ if (this.fullReadJson) {
103
+ this[_readPackageJson] = readPackageJson
104
+ } else {
105
+ this[_readPackageJson] = readPackageJsonFast
106
+ }
96
107
 
97
108
  this.defaultTag = opts.defaultTag || 'latest'
98
- this.registry = (opts.registry || 'https://registry.npmjs.org')
99
- .replace(/\/+$/, '')
109
+ this.registry = removeTrailingSlashes(opts.registry || 'https://registry.npmjs.org')
100
110
 
101
111
  // command to run 'prepare' scripts on directories and git dirs
102
112
  // To use pacote with yarn, for example, set npmBin to 'yarn'
@@ -104,7 +114,7 @@ class FetcherBase {
104
114
  this.npmBin = opts.npmBin || 'npm'
105
115
 
106
116
  // command to install deps for preparing
107
- this.npmInstallCmd = opts.npmInstallCmd || [ 'install', '--force' ]
117
+ this.npmInstallCmd = opts.npmInstallCmd || ['install', '--force']
108
118
 
109
119
  // XXX fill more of this in based on what we know from this.opts
110
120
  // we explicitly DO NOT fill in --tag, though, since we are often
@@ -132,19 +142,22 @@ class FetcherBase {
132
142
  get integrity () {
133
143
  return this.opts.integrity || null
134
144
  }
145
+
135
146
  set integrity (i) {
136
- if (!i)
147
+ if (!i) {
137
148
  return
149
+ }
138
150
 
139
151
  i = ssri.parse(i)
140
152
  const current = this.opts.integrity
141
153
 
142
154
  // do not ever update an existing hash value, but do
143
155
  // merge in NEW algos and hashes that we don't already have.
144
- if (current)
156
+ if (current) {
145
157
  current.merge(i)
146
- else
158
+ } else {
147
159
  this.opts.integrity = i
160
+ }
148
161
  }
149
162
 
150
163
  get notImplementedError () {
@@ -212,8 +225,9 @@ class FetcherBase {
212
225
  stream.on('error', er => istream.emit('error', er))
213
226
 
214
227
  // if not caching this, just pipe through to the istream and return it
215
- if (!this.opts.cache || !this[_cacheFetches])
228
+ if (!this.opts.cache || !this[_cacheFetches]) {
216
229
  return stream.pipe(istream)
230
+ }
217
231
 
218
232
  // we have to return a stream that gets ALL the data, and proxies errors,
219
233
  // but then pipe from the original tarball stream into the cache as well.
@@ -288,39 +302,42 @@ class FetcherBase {
288
302
  this.integrity &&
289
303
  this.resolved
290
304
  ) ? streamHandler(this[_tarballFromCache]()).catch(er => {
291
- if (this.isDataCorruptionError(er)) {
292
- this.log.warn('tarball', `cached data for ${
305
+ if (this.isDataCorruptionError(er)) {
306
+ log.warn('tarball', `cached data for ${
293
307
  this.spec
294
308
  } (${this.integrity}) seems to be corrupted. Refreshing cache.`)
295
- return this.cleanupCached().then(() => { throw er })
296
- } else {
297
- throw er
298
- }
299
- }) : null
309
+ return this.cleanupCached().then(() => {
310
+ throw er
311
+ })
312
+ } else {
313
+ throw er
314
+ }
315
+ }) : null
300
316
 
301
317
  const fromResolved = er => {
302
318
  if (er) {
303
- if (!this.isRetriableError(er))
319
+ if (!this.isRetriableError(er)) {
304
320
  throw er
305
- this.log.silly('tarball', `no local data for ${
321
+ }
322
+ log.silly('tarball', `no local data for ${
306
323
  this.spec
307
324
  }. Extracting by manifest.`)
308
325
  }
309
326
  return this.resolve().then(() => retry(tryAgain =>
310
327
  streamHandler(this[_istream](this[_tarballFromResolved]()))
311
- .catch(er => {
328
+ .catch(er => {
312
329
  // Most likely data integrity. A cache ENOENT error is unlikely
313
330
  // here, since we're definitely not reading from the cache, but it
314
331
  // IS possible that the fetch subsystem accessed the cache, and the
315
332
  // entry got blown away or something. Try one more time to be sure.
316
- if (this.isRetriableError(er)) {
317
- this.log.warn('tarball', `tarball data for ${
333
+ if (this.isRetriableError(er)) {
334
+ log.warn('tarball', `tarball data for ${
318
335
  this.spec
319
336
  } (${this.integrity}) seems to be corrupted. Trying again.`)
320
- return this.cleanupCached().then(() => tryAgain(er))
321
- }
322
- throw er
323
- }), { retries: 1, minTimeout: 0, maxTimeout: 0 }))
337
+ return this.cleanupCached().then(() => tryAgain(er))
338
+ }
339
+ throw er
340
+ }), { retries: 1, minTimeout: 0, maxTimeout: 0 }))
324
341
  }
325
342
 
326
343
  return fromCache ? fromCache.catch(fromResolved) : fromResolved()
@@ -337,7 +354,7 @@ class FetcherBase {
337
354
  }
338
355
 
339
356
  [_empty] (path) {
340
- return getContents({path, depth: 1}).then(contents => Promise.all(
357
+ return getContents({ path, depth: 1 }).then(contents => Promise.all(
341
358
  contents.map(entry => rimraf(entry))))
342
359
  }
343
360
 
@@ -350,7 +367,7 @@ class FetcherBase {
350
367
  // parent folder (rare, but probably happens sometimes).
351
368
  return !inferOwner
352
369
  ? this[_empty](dest).then(() => mkdirp(dest)).then(() => ({}))
353
- : inferOwner(dest).then(({uid, gid}) =>
370
+ : inferOwner(dest).then(({ uid, gid }) =>
354
371
  this[_empty](dest)
355
372
  .then(() => mkdirp(dest))
356
373
  .then(made => {
@@ -360,13 +377,13 @@ class FetcherBase {
360
377
  const dir = made || /* istanbul ignore next */ dest
361
378
  return this[_chown](dir, uid, gid)
362
379
  })
363
- .then(() => ({uid, gid})))
380
+ .then(() => ({ uid, gid })))
364
381
  }
365
382
 
366
383
  // extraction is always the same. the only difference is where
367
384
  // the tarball comes from.
368
385
  extract (dest) {
369
- return this[_mkdir](dest).then(({uid, gid}) =>
386
+ return this[_mkdir](dest).then(({ uid, gid }) =>
370
387
  this.tarballStream(tarball => this[_extract](dest, tarball, uid, gid)))
371
388
  }
372
389
 
@@ -389,7 +406,7 @@ class FetcherBase {
389
406
  const dir = dirname(dest)
390
407
  return !inferOwner
391
408
  ? mkdirp(dir).then(() => this[_toFile](dest))
392
- : inferOwner(dest).then(({uid, gid}) =>
409
+ : inferOwner(dest).then(({ uid, gid }) =>
393
410
  mkdirp(dir).then(made => this[_toFile](dest)
394
411
  .then(res => this[_chown](made || dir, uid, gid)
395
412
  .then(() => res))))
@@ -407,8 +424,8 @@ class FetcherBase {
407
424
  })
408
425
 
409
426
  extractor.on('error', er => {
410
- this.log.warn('tar', er.message)
411
- this.log.silly('tar', er)
427
+ log.warn('tar', er.message)
428
+ log.silly('tar', er)
412
429
  reject(er)
413
430
  })
414
431
 
@@ -439,21 +456,23 @@ class FetcherBase {
439
456
  noChmod: true,
440
457
  noMtime: true,
441
458
  filter: (name, entry) => {
442
- if (/Link$/.test(entry.type))
459
+ if (/Link$/.test(entry.type)) {
443
460
  return false
461
+ }
444
462
  entry.mode = this[_entryMode](entry.path, entry.mode, entry.type)
445
463
  // this replicates the npm pack behavior where .gitignore files
446
464
  // are treated like .npmignore files, but only if a .npmignore
447
465
  // file is not present.
448
466
  if (/File$/.test(entry.type)) {
449
467
  const base = basename(entry.path)
450
- if (base === '.npmignore')
468
+ if (base === '.npmignore') {
451
469
  sawIgnores.add(entry.path)
452
- else if (base === '.gitignore' && !this.allowGitIgnore) {
470
+ } else if (base === '.gitignore' && !this.allowGitIgnore) {
453
471
  // rename, but only if there's not already a .npmignore
454
472
  const ni = entry.path.replace(/\.gitignore$/, '.npmignore')
455
- if (sawIgnores.has(ni))
473
+ if (sawIgnores.has(ni)) {
456
474
  return false
475
+ }
457
476
  entry.path = ni
458
477
  }
459
478
  return true
@@ -462,8 +481,8 @@ class FetcherBase {
462
481
  strip: 1,
463
482
  onwarn: /* istanbul ignore next - we can trust that tar logs */
464
483
  (code, msg, data) => {
465
- this.log.warn('tar', code, msg)
466
- this.log.silly('tar', code, msg, data)
484
+ log.warn('tar', code, msg)
485
+ log.silly('tar', code, msg, data)
467
486
  },
468
487
  uid,
469
488
  gid,
package/lib/file.js CHANGED
@@ -1,12 +1,11 @@
1
1
  const Fetcher = require('./fetcher.js')
2
2
  const fsm = require('fs-minipass')
3
3
  const cacache = require('cacache')
4
- const { promisify } = require('util')
5
- const readPackageJson = require('read-package-json-fast')
6
4
  const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
7
5
  const _exeBins = Symbol('_exeBins')
8
6
  const { resolve } = require('path')
9
7
  const fs = require('fs')
8
+ const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
10
9
 
11
10
  class FileFetcher extends Fetcher {
12
11
  constructor (spec, opts) {
@@ -20,24 +19,26 @@ class FileFetcher extends Fetcher {
20
19
  }
21
20
 
22
21
  manifest () {
23
- if (this.package)
22
+ if (this.package) {
24
23
  return Promise.resolve(this.package)
24
+ }
25
25
 
26
26
  // have to unpack the tarball for this.
27
27
  return cacache.tmp.withTmp(this.cache, this.opts, dir =>
28
28
  this.extract(dir)
29
- .then(() => readPackageJson(dir + '/package.json'))
30
- .then(mani => this.package = {
31
- ...mani,
32
- _integrity: this.integrity && String(this.integrity),
33
- _resolved: this.resolved,
34
- _from: this.from,
35
- }))
29
+ .then(() => this[_readPackageJson](dir + '/package.json'))
30
+ .then(mani => this.package = {
31
+ ...mani,
32
+ _integrity: this.integrity && String(this.integrity),
33
+ _resolved: this.resolved,
34
+ _from: this.from,
35
+ }))
36
36
  }
37
37
 
38
38
  [_exeBins] (pkg, dest) {
39
- if (!pkg.bin)
39
+ if (!pkg.bin) {
40
40
  return Promise.resolve()
41
+ }
41
42
 
42
43
  return Promise.all(Object.keys(pkg.bin).map(k => new Promise(res => {
43
44
  const script = resolve(dest, pkg.bin[k])
@@ -46,11 +47,13 @@ class FileFetcher extends Fetcher {
46
47
  // something, we just leave it for a later stage to trip over
47
48
  // when we can provide a more useful contextual error.
48
49
  fs.stat(script, (er, st) => {
49
- if (er)
50
+ if (er) {
50
51
  return res()
52
+ }
51
53
  const mode = st.mode | 0o111
52
- if (mode === st.mode)
54
+ if (mode === st.mode) {
53
55
  return res()
56
+ }
54
57
  fs.chmod(script, mode, res)
55
58
  })
56
59
  })))
@@ -61,8 +64,8 @@ class FileFetcher extends Fetcher {
61
64
  // but if not, read the unpacked manifest and chmod properly.
62
65
  return super.extract(dest)
63
66
  .then(result => this.package ? result
64
- : readPackageJson(dest + '/package.json').then(pkg =>
65
- this[_exeBins](pkg, dest)).then(() => result))
67
+ : this[_readPackageJson](dest + '/package.json').then(pkg =>
68
+ this[_exeBins](pkg, dest)).then(() => result))
66
69
  }
67
70
 
68
71
  [_tarballFromResolved] () {
@@ -75,7 +78,7 @@ class FileFetcher extends Fetcher {
75
78
  return this.manifest().then(mani => ({
76
79
  name: mani.name,
77
80
  'dist-tags': {
78
- [this.defaultTag]: mani.version
81
+ [this.defaultTag]: mani.version,
79
82
  },
80
83
  versions: {
81
84
  [mani.version]: {
@@ -83,9 +86,9 @@ class FileFetcher extends Fetcher {
83
86
  dist: {
84
87
  tarball: `file:${this.resolved}`,
85
88
  integrity: this.integrity && String(this.integrity),
86
- }
87
- }
88
- }
89
+ },
90
+ },
91
+ },
89
92
  }))
90
93
  }
91
94
  }
package/lib/git.js CHANGED
@@ -6,11 +6,9 @@ const hashre = /^[a-f0-9]{40}$/
6
6
  const git = require('@npmcli/git')
7
7
  const pickManifest = require('npm-pick-manifest')
8
8
  const npa = require('npm-package-arg')
9
- const url = require('url')
10
9
  const Minipass = require('minipass')
11
10
  const cacache = require('cacache')
12
- const { promisify } = require('util')
13
- const readPackageJson = require('read-package-json-fast')
11
+ const log = require('proc-log')
14
12
  const npm = require('./util/npm.js')
15
13
 
16
14
  const _resolvedFromRepo = Symbol('_resolvedFromRepo')
@@ -24,6 +22,7 @@ const _cloneHosted = Symbol('_cloneHosted')
24
22
  const _cloneRepo = Symbol('_cloneRepo')
25
23
  const _setResolvedWithSha = Symbol('_setResolvedWithSha')
26
24
  const _prepareDir = Symbol('_prepareDir')
25
+ const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
27
26
 
28
27
  // get the repository url.
29
28
  // prefer https if there's auth, since ssh will drop that.
@@ -40,8 +39,9 @@ class GitFetcher extends Fetcher {
40
39
  constructor (spec, opts) {
41
40
  super(spec, opts)
42
41
  this.resolvedRef = null
43
- if (this.spec.hosted)
42
+ if (this.spec.hosted) {
44
43
  this.from = this.spec.hosted.shortcut({ noCommittish: false })
44
+ }
45
45
 
46
46
  // shortcut: avoid full clone when we can go straight to the tgz
47
47
  // if we have the full sha and it's a hosted git platform
@@ -51,8 +51,9 @@ class GitFetcher extends Fetcher {
51
51
  this.resolved = this.spec.hosted
52
52
  ? repoUrl(this.spec.hosted, { noCommittish: false })
53
53
  : this.spec.rawSpec
54
- } else
54
+ } else {
55
55
  this.resolvedSha = ''
56
+ }
56
57
  }
57
58
 
58
59
  // just exposed to make it easier to test all the combinations
@@ -67,8 +68,9 @@ class GitFetcher extends Fetcher {
67
68
  resolve () {
68
69
  // likely a hosted git repo with a sha, so get the tarball url
69
70
  // but in general, no reason to resolve() more than necessary!
70
- if (this.resolved)
71
+ if (this.resolved) {
71
72
  return super.resolve()
73
+ }
72
74
 
73
75
  // fetch the git repo and then look at the current hash
74
76
  const h = this.spec.hosted
@@ -86,37 +88,41 @@ class GitFetcher extends Fetcher {
86
88
  return this[_resolvedFromRepo](hosted.https && hosted.https())
87
89
  .catch(er => {
88
90
  // Throw early since we know pathspec errors will fail again if retried
89
- if (er instanceof git.errors.GitPathspecError)
91
+ if (er instanceof git.errors.GitPathspecError) {
90
92
  throw er
93
+ }
91
94
  const ssh = hosted.sshurl && hosted.sshurl()
92
95
  // no fallthrough if we can't fall through or have https auth
93
- if (!ssh || hosted.auth)
96
+ if (!ssh || hosted.auth) {
94
97
  throw er
98
+ }
95
99
  return this[_resolvedFromRepo](ssh)
96
100
  })
97
101
  }
98
102
 
99
103
  [_resolvedFromRepo] (gitRemote) {
100
104
  // XXX make this a custom error class
101
- if (!gitRemote)
105
+ if (!gitRemote) {
102
106
  return Promise.reject(new Error(`No git url for ${this.spec}`))
107
+ }
103
108
  const gitRange = this.spec.gitRange
104
109
  const name = this.spec.name
105
110
  return git.revs(gitRemote, this.opts).then(remoteRefs => {
106
111
  return gitRange ? pickManifest({
107
- versions: remoteRefs.versions,
108
- 'dist-tags': remoteRefs['dist-tags'],
109
- name,
110
- }, gitRange, this.opts)
112
+ versions: remoteRefs.versions,
113
+ 'dist-tags': remoteRefs['dist-tags'],
114
+ name,
115
+ }, gitRange, this.opts)
111
116
  : this.spec.gitCommittish ?
112
117
  remoteRefs.refs[this.spec.gitCommittish] ||
113
118
  remoteRefs.refs[remoteRefs.shas[this.spec.gitCommittish]]
114
- : remoteRefs.refs.HEAD // no git committish, get default head
119
+ : remoteRefs.refs.HEAD // no git committish, get default head
115
120
  }).then(revDoc => {
116
121
  // the committish provided isn't in the rev list
117
122
  // things like HEAD~3 or @yesterday can land here.
118
- if (!revDoc || !revDoc.sha)
123
+ if (!revDoc || !revDoc.sha) {
119
124
  return this[_resolvedFromClone]()
125
+ }
120
126
 
121
127
  this.resolvedRef = revDoc
122
128
  this.resolvedSha = revDoc.sha
@@ -145,16 +151,17 @@ class GitFetcher extends Fetcher {
145
151
  }
146
152
 
147
153
  [_prepareDir] (dir) {
148
- return readPackageJson(dir + '/package.json').then(mani => {
154
+ return this[_readPackageJson](dir + '/package.json').then(mani => {
149
155
  // no need if we aren't going to do any preparation.
150
156
  const scripts = mani.scripts
151
157
  if (!scripts || !(
152
- scripts.postinstall ||
158
+ scripts.postinstall ||
153
159
  scripts.build ||
154
160
  scripts.preinstall ||
155
161
  scripts.install ||
156
- scripts.prepare))
162
+ scripts.prepare)) {
157
163
  return
164
+ }
158
165
 
159
166
  // to avoid cases where we have an cycle of git deps that depend
160
167
  // on one another, we only ever do preparation for one instance
@@ -166,7 +173,7 @@ class GitFetcher extends Fetcher {
166
173
  const noPrepare = !process.env._PACOTE_NO_PREPARE_ ? []
167
174
  : process.env._PACOTE_NO_PREPARE_.split('\n')
168
175
  if (noPrepare.includes(this.resolved)) {
169
- this.log.info('prepare', 'skip prepare, already seen', this.resolved)
176
+ log.info('prepare', 'skip prepare, already seen', this.resolved)
170
177
  return
171
178
  }
172
179
  noPrepare.push(this.resolved)
@@ -202,9 +209,9 @@ class GitFetcher extends Fetcher {
202
209
  dirStream.on('end', res)
203
210
  dirStream.pipe(stream)
204
211
  }))).catch(
205
- /* istanbul ignore next: very unlikely and hard to test */
206
- er => stream.emit('error', er)
207
- )
212
+ /* istanbul ignore next: very unlikely and hard to test */
213
+ er => stream.emit('error', er)
214
+ )
208
215
  return stream
209
216
  }
210
217
 
@@ -237,10 +244,11 @@ class GitFetcher extends Fetcher {
237
244
  integrity: null, // it'll always be different, if we have one
238
245
  }).extract(tmp).then(() => handler(tmp), er => {
239
246
  // fall back to ssh download if tarball fails
240
- if (er.constructor.name.match(/^Http/))
247
+ if (er.constructor.name.match(/^Http/)) {
241
248
  return this[_clone](handler, false)
242
- else
249
+ } else {
243
250
  throw er
251
+ }
244
252
  })
245
253
  }
246
254
 
@@ -249,10 +257,11 @@ class GitFetcher extends Fetcher {
249
257
  : this[_cloneRepo](this.spec.fetchSpec, ref, tmp)
250
258
  ).then(sha => {
251
259
  this.resolvedSha = sha
252
- if (!this.resolved)
260
+ if (!this.resolved) {
253
261
  this[_addGitSha](sha)
262
+ }
254
263
  })
255
- .then(() => handler(tmp))
264
+ .then(() => handler(tmp))
256
265
  })
257
266
  }
258
267
 
@@ -266,12 +275,14 @@ class GitFetcher extends Fetcher {
266
275
  return this[_cloneRepo](hosted.https({ noCommittish: true }), ref, tmp)
267
276
  .catch(er => {
268
277
  // Throw early since we know pathspec errors will fail again if retried
269
- if (er instanceof git.errors.GitPathspecError)
278
+ if (er instanceof git.errors.GitPathspecError) {
270
279
  throw er
280
+ }
271
281
  const ssh = hosted.sshurl && hosted.sshurl({ noCommittish: true })
272
282
  // no fallthrough if we can't fall through or have https auth
273
- if (!ssh || hosted.auth)
283
+ if (!ssh || hosted.auth) {
274
284
  throw er
285
+ }
275
286
  return this[_cloneRepo](ssh, ref, tmp)
276
287
  })
277
288
  }
@@ -282,19 +293,20 @@ class GitFetcher extends Fetcher {
282
293
  }
283
294
 
284
295
  manifest () {
285
- if (this.package)
296
+ if (this.package) {
286
297
  return Promise.resolve(this.package)
298
+ }
287
299
 
288
300
  return this.spec.hosted && this.resolved
289
301
  ? FileFetcher.prototype.manifest.apply(this)
290
302
  : this[_clone](dir =>
291
- readPackageJson(dir + '/package.json')
292
- .then(mani => this.package = {
293
- ...mani,
294
- _integrity: this.integrity && String(this.integrity),
295
- _resolved: this.resolved,
296
- _from: this.from,
297
- }))
303
+ this[_readPackageJson](dir + '/package.json')
304
+ .then(mani => this.package = {
305
+ ...mani,
306
+ _integrity: this.integrity && String(this.integrity),
307
+ _resolved: this.resolved,
308
+ _from: this.from,
309
+ }))
298
310
  }
299
311
 
300
312
  packument () {
package/lib/registry.js CHANGED
@@ -2,11 +2,11 @@ const Fetcher = require('./fetcher.js')
2
2
  const RemoteFetcher = require('./remote.js')
3
3
  const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
4
4
  const pacoteVersion = require('../package.json').version
5
+ const removeTrailingSlashes = require('./util/trailing-slashes.js')
5
6
  const npa = require('npm-package-arg')
6
7
  const rpj = require('read-package-json-fast')
7
8
  const pickManifest = require('npm-pick-manifest')
8
9
  const ssri = require('ssri')
9
- const Minipass = require('minipass')
10
10
 
11
11
  // Corgis are cute. 🐕🐶
12
12
  const corgiDoc = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'
@@ -32,10 +32,11 @@ class RegistryFetcher extends Fetcher {
32
32
  // handle case when npm-package-arg guesses wrong.
33
33
  if (this.spec.type === 'tag' &&
34
34
  this.spec.rawSpec === '' &&
35
- this.defaultTag !== 'latest')
35
+ this.defaultTag !== 'latest') {
36
36
  this.spec = npa(`${this.spec.name}@${this.defaultTag}`)
37
+ }
37
38
  this.registry = fetch.pickRegistry(spec, opts)
38
- this.packumentUrl = this.registry.replace(/\/*$/, '/') +
39
+ this.packumentUrl = removeTrailingSlashes(this.registry) + '/' +
39
40
  this.spec.escapedName
40
41
 
41
42
  // XXX pacote <=9 has some logic to ignore opts.resolved if
@@ -45,13 +46,15 @@ class RegistryFetcher extends Fetcher {
45
46
  }
46
47
 
47
48
  resolve () {
48
- if (this.resolved)
49
+ if (this.resolved) {
49
50
  return Promise.resolve(this.resolved)
51
+ }
50
52
 
51
53
  // fetching the manifest sets resolved and (usually) integrity
52
54
  return this.manifest().then(() => {
53
- if (this.resolved)
55
+ if (this.resolved) {
54
56
  return this.resolved
57
+ }
55
58
 
56
59
  throw Object.assign(
57
60
  new Error('Invalid package manifest: no `dist.tarball` field'),
@@ -77,8 +80,9 @@ class RegistryFetcher extends Fetcher {
77
80
  // note this might be either an in-flight promise for a request,
78
81
  // or the actual packument, but we never want to make more than
79
82
  // one request at a time for the same thing regardless.
80
- if (this.packumentCache && this.packumentCache.has(this.packumentUrl))
83
+ if (this.packumentCache && this.packumentCache.has(this.packumentUrl)) {
81
84
  return this.packumentCache.get(this.packumentUrl)
85
+ }
82
86
 
83
87
  // npm-registry-fetch the packument
84
88
  // set the appropriate header for corgis if fullMetadata isn't set
@@ -92,12 +96,14 @@ class RegistryFetcher extends Fetcher {
92
96
  }).then(res => res.json().then(packument => {
93
97
  packument._cached = res.headers.has('x-local-cache')
94
98
  packument._contentLength = +res.headers.get('content-length')
95
- if (this.packumentCache)
99
+ if (this.packumentCache) {
96
100
  this.packumentCache.set(this.packumentUrl, packument)
101
+ }
97
102
  return packument
98
103
  })).catch(er => {
99
- if (this.packumentCache)
104
+ if (this.packumentCache) {
100
105
  this.packumentCache.delete(this.packumentUrl)
106
+ }
101
107
  if (er.code === 'E404' && !this.fullMetadata) {
102
108
  // possible that corgis are not supported by this registry
103
109
  this.fullMetadata = true
@@ -105,14 +111,16 @@ class RegistryFetcher extends Fetcher {
105
111
  }
106
112
  throw er
107
113
  })
108
- if (this.packumentCache)
114
+ if (this.packumentCache) {
109
115
  this.packumentCache.set(this.packumentUrl, p)
116
+ }
110
117
  return p
111
118
  }
112
119
 
113
120
  manifest () {
114
- if (this.package)
121
+ if (this.package) {
115
122
  return Promise.resolve(this.package)
123
+ }
116
124
 
117
125
  return this.packument()
118
126
  .then(packument => pickManifest(packument, this.spec.fetchSpec, {
@@ -127,12 +135,12 @@ class RegistryFetcher extends Fetcher {
127
135
  this.resolved = mani._resolved = dist.tarball
128
136
  mani._from = this.from
129
137
  const distIntegrity = dist.integrity ? ssri.parse(dist.integrity)
130
- : dist.shasum ? ssri.fromHex(dist.shasum, 'sha1', {...this.opts})
138
+ : dist.shasum ? ssri.fromHex(dist.shasum, 'sha1', { ...this.opts })
131
139
  : null
132
140
  if (distIntegrity) {
133
- if (!this.integrity)
141
+ if (!this.integrity) {
134
142
  this.integrity = distIntegrity
135
- else if (!this.integrity.match(distIntegrity)) {
143
+ } else if (!this.integrity.match(distIntegrity)) {
136
144
  // only bork if they have algos in common.
137
145
  // otherwise we end up breaking if we have saved a sha512
138
146
  // previously for the tarball, but the manifest only
@@ -143,7 +151,7 @@ class RegistryFetcher extends Fetcher {
143
151
  for (const algo of Object.keys(this.integrity)) {
144
152
  if (distIntegrity[algo]) {
145
153
  throw Object.assign(new Error(
146
- `Integrity checksum failed when using ${algo}: `+
154
+ `Integrity checksum failed when using ${algo}: ` +
147
155
  `wanted ${this.integrity} but got ${distIntegrity}.`
148
156
  ), { code: 'EINTEGRITY' })
149
157
  }
@@ -155,8 +163,9 @@ class RegistryFetcher extends Fetcher {
155
163
  }
156
164
  }
157
165
  }
158
- if (this.integrity)
166
+ if (this.integrity) {
159
167
  mani._integrity = String(this.integrity)
168
+ }
160
169
  this.package = rpj.normalize(mani)
161
170
  return this.package
162
171
  })
package/lib/remote.js CHANGED
@@ -3,7 +3,6 @@ const FileFetcher = require('./file.js')
3
3
  const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
4
4
  const pacoteVersion = require('../package.json').version
5
5
  const fetch = require('npm-registry-fetch')
6
- const ssri = require('ssri')
7
6
  const Minipass = require('minipass')
8
7
  // The default registry URL is a string of great magic.
9
8
  const magic = /^https?:\/\/registry\.npmjs\.org\//
@@ -14,8 +13,9 @@ class RemoteFetcher extends Fetcher {
14
13
  constructor (spec, opts) {
15
14
  super(spec, opts)
16
15
  this.resolved = this.spec.fetchSpec
17
- if (magic.test(this.resolved) && !magic.test(this.registry + '/'))
16
+ if (magic.test(this.resolved) && !magic.test(this.registry + '/')) {
18
17
  this.resolved = this.resolved.replace(magic, this.registry + '/')
18
+ }
19
19
 
20
20
  // nam is a fermented pork sausage that is good to eat
21
21
  const nameat = this.spec.name ? `${this.spec.name}@` : ''
@@ -35,7 +35,7 @@ class RemoteFetcher extends Fetcher {
35
35
  headers: this[_headers](),
36
36
  spec: this.spec,
37
37
  integrity: this.integrity,
38
- algorithms: [ this.pickIntegrityAlgorithm() ],
38
+ algorithms: [this.pickIntegrityAlgorithm()],
39
39
  }
40
40
  fetch(this.resolved, fetchOpts).then(res => {
41
41
  const hash = res.headers.get('x-local-cache-hash')
@@ -62,7 +62,7 @@ class RemoteFetcher extends Fetcher {
62
62
  'pacote-req-type': 'tarball',
63
63
  'pacote-pkg-id': this.pkgid,
64
64
  ...(this.integrity ? { 'pacote-integrity': String(this.integrity) }
65
- : {}),
65
+ : {}),
66
66
  ...(this.opts.headers || {}),
67
67
  }
68
68
  }
@@ -1,5 +1,5 @@
1
1
  const os = require('os')
2
- const {resolve} = require('path')
2
+ const { resolve } = require('path')
3
3
 
4
4
  module.exports = (fakePlatform = false) => {
5
5
  const temp = os.tmpdir()
@@ -12,10 +12,11 @@ const binObj = (name, bin) =>
12
12
 
13
13
  const hasBin = (pkg, path) => {
14
14
  const bin = binObj(pkg.name, pkg.bin)
15
- const p = path.replace(/^[^\\\/]*\//, '')
16
- for (const [k, v] of Object.entries(bin)) {
17
- if (v === p)
15
+ const p = path.replace(/^[^\\/]*\//, '')
16
+ for (const kv of Object.entries(bin)) {
17
+ if (kv[1] === p) {
18
18
  return true
19
+ }
19
20
  }
20
21
  return false
21
22
  }
package/lib/util/npm.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // run an npm command
2
2
  const spawn = require('@npmcli/promise-spawn')
3
- const {dirname} = require('path')
4
3
 
5
4
  module.exports = (npmBin, npmCommand, cwd, env, extra) => {
6
5
  const isJS = npmBin.endsWith('.js')
@@ -9,7 +9,7 @@ const tarCreateOptions = manifest => ({
9
9
  // platform specific optimizations that cause
10
10
  // integrity mismatch errors due to differing
11
11
  // end results after compression
12
- level: 9
12
+ level: 9,
13
13
  },
14
14
 
15
15
  // ensure that package bins are always executable
@@ -17,8 +17,9 @@ const tarCreateOptions = manifest => ({
17
17
  // anything that is not a regular file, ignored by
18
18
  // .npmignore or package.json "files", etc.
19
19
  filter: (path, stat) => {
20
- if (isPackageBin(manifest, path))
20
+ if (isPackageBin(manifest, path)) {
21
21
  stat.mode |= 0o111
22
+ }
22
23
  return true
23
24
  },
24
25
 
@@ -0,0 +1,10 @@
1
+ const removeTrailingSlashes = (input) => {
2
+ // in order to avoid regexp redos detection
3
+ let output = input
4
+ while (output.endsWith('/')) {
5
+ output = output.substr(0, output.length - 1)
6
+ }
7
+ return output
8
+ }
9
+
10
+ module.exports = removeTrailingSlashes
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "pacote",
3
- "version": "12.0.3",
3
+ "version": "13.0.0",
4
4
  "description": "JavaScript package downloader",
5
- "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)",
5
+ "author": "GitHub Inc.",
6
6
  "bin": {
7
7
  "pacote": "lib/bin.js"
8
8
  },
@@ -13,19 +13,26 @@
13
13
  "snap": "tap",
14
14
  "preversion": "npm test",
15
15
  "postversion": "npm publish",
16
- "prepublishOnly": "git push origin --follow-tags"
16
+ "prepublishOnly": "git push origin --follow-tags",
17
+ "lint": "eslint '**/*.js'",
18
+ "postlint": "npm-template-check",
19
+ "lintfix": "npm run lint -- --fix",
20
+ "posttest": "npm run lint",
21
+ "template-copy": "npm-template-copy --force"
17
22
  },
18
23
  "tap": {
19
24
  "timeout": 300,
20
25
  "coverage-map": "map.js"
21
26
  },
22
27
  "devDependencies": {
28
+ "@npmcli/template-oss": "^2.7.1",
23
29
  "mutate-fs": "^2.1.1",
24
30
  "npm-registry-mock": "^1.3.1",
25
- "tap": "^15.0.4"
31
+ "tap": "^15.1.6"
26
32
  },
27
33
  "files": [
28
- "lib/**/*.js"
34
+ "bin",
35
+ "lib"
29
36
  ],
30
37
  "keywords": [
31
38
  "packages",
@@ -34,27 +41,33 @@
34
41
  ],
35
42
  "dependencies": {
36
43
  "@npmcli/git": "^2.1.0",
37
- "@npmcli/installed-package-contents": "^1.0.6",
44
+ "@npmcli/installed-package-contents": "^1.0.7",
38
45
  "@npmcli/promise-spawn": "^1.2.0",
39
46
  "@npmcli/run-script": "^2.0.0",
40
- "cacache": "^15.0.5",
47
+ "cacache": "^15.3.0",
41
48
  "chownr": "^2.0.0",
42
49
  "fs-minipass": "^2.1.0",
43
50
  "infer-owner": "^1.0.4",
44
- "minipass": "^3.1.3",
45
- "mkdirp": "^1.0.3",
46
- "npm-package-arg": "^8.0.1",
51
+ "minipass": "^3.1.6",
52
+ "mkdirp": "^1.0.4",
53
+ "npm-package-arg": "^9.0.0",
47
54
  "npm-packlist": "^3.0.0",
48
- "npm-pick-manifest": "^6.0.0",
49
- "npm-registry-fetch": "^12.0.0",
55
+ "npm-pick-manifest": "^7.0.0",
56
+ "npm-registry-fetch": "^12.0.2",
57
+ "proc-log": "^2.0.0",
50
58
  "promise-retry": "^2.0.1",
51
- "read-package-json-fast": "^2.0.1",
59
+ "read-package-json": "^4.1.1",
60
+ "read-package-json-fast": "^2.0.3",
52
61
  "rimraf": "^3.0.2",
53
62
  "ssri": "^8.0.1",
54
- "tar": "^6.1.0"
63
+ "tar": "^6.1.11"
55
64
  },
56
65
  "engines": {
57
66
  "node": "^12.13.0 || ^14.15.0 || >=16"
58
67
  },
59
- "repository": "git@github.com:npm/pacote"
68
+ "repository": "git@github.com:npm/pacote",
69
+ "templateOSS": {
70
+ "version": "2.7.1",
71
+ "windowsCI": false
72
+ }
60
73
  }
@@ -1,21 +0,0 @@
1
- // default logger.
2
- // emits 'log' events on the process
3
- const LEVELS = [
4
- 'notice',
5
- 'error',
6
- 'warn',
7
- 'info',
8
- 'verbose',
9
- 'http',
10
- 'silly',
11
- 'pause',
12
- 'resume'
13
- ]
14
-
15
- const log = level => (...args) => process.emit('log', level, ...args)
16
-
17
- const logger = {}
18
- for (const level of LEVELS) {
19
- logger[level] = log(level)
20
- }
21
- module.exports = logger