pacote 11.2.4 → 11.3.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
@@ -168,6 +168,18 @@ resolved, and other properties, as they are determined.
168
168
  times (even just to validate the cache) for a given packument, since it
169
169
  is unlikely to change in the span of a single command.
170
170
 
171
+
172
+ ### Advanced API
173
+
174
+ Each different type of fetcher is exposed for more advanced usage such as
175
+ using helper methods from this classes:
176
+
177
+ * `DirFetcher`
178
+ * `FileFetcher`
179
+ * `GitFetcher`
180
+ * `RegistryFetcher`
181
+ * `RemoteFetcher`
182
+
171
183
  ## Extracted File Modes
172
184
 
173
185
  Files are extracted with a mode matching the following formula:
package/lib/dir.js CHANGED
@@ -4,11 +4,10 @@ const cacache = require('cacache')
4
4
  const Minipass = require('minipass')
5
5
  const { promisify } = require('util')
6
6
  const readPackageJson = require('read-package-json-fast')
7
- const isPackageBin = require('./util/is-package-bin.js')
7
+ const tarCreateOptions = require('./util/tar-create-options.js')
8
8
  const packlist = require('npm-packlist')
9
9
  const tar = require('tar')
10
10
  const _prepareDir = Symbol('_prepareDir')
11
- const _tarcOpts = Symbol('_tarcOpts')
12
11
  const { resolve } = require('path')
13
12
 
14
13
  const runScript = require('@npmcli/run-script')
@@ -21,6 +20,11 @@ class DirFetcher extends Fetcher {
21
20
  this.resolved = this.spec.fetchSpec
22
21
  }
23
22
 
23
+ // exposes tarCreateOptions as public API
24
+ static tarCreateOptions (manifest) {
25
+ return tarCreateOptions(manifest)
26
+ }
27
+
24
28
  get types () {
25
29
  return ['directory']
26
30
  }
@@ -33,11 +37,20 @@ class DirFetcher extends Fetcher {
33
37
  // we *only* run prepare.
34
38
  // pre/post-pack is run by the npm CLI for publish and pack,
35
39
  // but this function is *also* run when installing git deps
40
+ const stdio = this.opts.foregroundScripts ? 'inherit' : 'pipe'
41
+
42
+ // hide the banner if loglevel is silent, or if prepare running
43
+ // in the background.
44
+ const banner = this.opts.log && this.opts.log.level === 'silent' ? false
45
+ : stdio === 'inherit'
46
+
36
47
  return runScript({
37
48
  pkg: mani,
38
49
  event: 'prepare',
39
50
  path: this.resolved,
40
51
  stdioString: true,
52
+ stdio,
53
+ banner,
41
54
  env: {
42
55
  npm_package_resolved: this.resolved,
43
56
  npm_package_integrity: this.integrity,
@@ -56,35 +69,12 @@ class DirFetcher extends Fetcher {
56
69
  // pipe to the stream, and proxy errors the chain.
57
70
  this[_prepareDir]()
58
71
  .then(() => packlist({ path: this.resolved }))
59
- .then(files => tar.c(this[_tarcOpts](), files)
72
+ .then(files => tar.c(tarCreateOptions(this.package), files)
60
73
  .on('error', er => stream.emit('error', er)).pipe(stream))
61
74
  .catch(er => stream.emit('error', er))
62
75
  return stream
63
76
  }
64
77
 
65
- [_tarcOpts] () {
66
- return {
67
- cwd: this.resolved,
68
- prefix: 'package/',
69
- portable: true,
70
- gzip: true,
71
-
72
- // ensure that package bins are always executable
73
- // Note that npm-packlist is already filtering out
74
- // anything that is not a regular file, ignored by
75
- // .npmignore or package.json "files", etc.
76
- filter: (path, stat) => {
77
- if (isPackageBin(this.package, path))
78
- stat.mode |= 0o111
79
- return true
80
- },
81
-
82
- // Provide a specific date in the 1980s for the benefit of zip,
83
- // which is confounded by files dated at the Unix epoch 0.
84
- mtime: new Date('1985-10-26T08:15:00.000Z'),
85
- }
86
- }
87
-
88
78
  manifest () {
89
79
  if (this.package)
90
80
  return Promise.resolve(this.package)
package/lib/fetcher.js CHANGED
@@ -110,7 +110,7 @@ class FetcherBase {
110
110
  // going to be packing in the context of a publish, which may set
111
111
  // a dist-tag, but certainly wants to keep defaulting to latest.
112
112
  this.npmCliConfig = opts.npmCliConfig || [
113
- `--cache=${this.cache}`,
113
+ `--cache=${dirname(this.cache)}`,
114
114
  `--prefer-offline=${!!this.preferOffline}`,
115
115
  `--prefer-online=${!!this.preferOnline}`,
116
116
  `--offline=${!!this.offline}`,
package/lib/git.js CHANGED
@@ -18,6 +18,7 @@ const _resolvedFromHosted = Symbol('_resolvedFromHosted')
18
18
  const _resolvedFromClone = Symbol('_resolvedFromClone')
19
19
  const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
20
20
  const _addGitSha = Symbol('_addGitSha')
21
+ const addGitSha = require('./util/add-git-sha.js')
21
22
  const _clone = Symbol('_clone')
22
23
  const _cloneHosted = Symbol('_cloneHosted')
23
24
  const _cloneRepo = Symbol('_cloneRepo')
@@ -131,16 +132,7 @@ class GitFetcher extends Fetcher {
131
132
  // when we get the git sha, we affix it to our spec to build up
132
133
  // either a git url with a hash, or a tarball download URL
133
134
  [_addGitSha] (sha) {
134
- if (this.spec.hosted) {
135
- const h = this.spec.hosted
136
- const opt = { noCommittish: true }
137
- const base = h.https && h.auth ? h.https(opt) : h.shortcut(opt)
138
-
139
- this[_setResolvedWithSha](`${base}#${sha}`)
140
- } else {
141
- const u = url.format(new url.URL(`#${sha}`, this.spec.rawSpec))
142
- this[_setResolvedWithSha](url.format(u))
143
- }
135
+ this[_setResolvedWithSha](addGitSha(this.spec, sha))
144
136
  }
145
137
 
146
138
  [_resolvedFromClone] () {
@@ -161,12 +153,28 @@ class GitFetcher extends Fetcher {
161
153
  scripts.prepare))
162
154
  return
163
155
 
156
+ // to avoid cases where we have an cycle of git deps that depend
157
+ // on one another, we only ever do preparation for one instance
158
+ // of a given git dep along the chain of installations.
159
+ // Note that this does mean that a dependency MAY in theory end up
160
+ // trying to run its prepare script using a dependency that has not
161
+ // been properly prepared itself, but that edge case is smaller
162
+ // and less hazardous than a fork bomb of npm and git commands.
163
+ const noPrepare = !process.env._PACOTE_NO_PREPARE_ ? []
164
+ : process.env._PACOTE_NO_PREPARE_.split('\n')
165
+ if (noPrepare.includes(this.resolved)) {
166
+ this.log.info('prepare', 'skip prepare, already seen', this.resolved)
167
+ return
168
+ }
169
+ noPrepare.push(this.resolved)
170
+
164
171
  // the DirFetcher will do its own preparation to run the prepare scripts
165
172
  // All we have to do is put the deps in place so that it can succeed.
166
173
  return npm(
167
174
  this.npmBin,
168
175
  [].concat(this.npmInstallCmd).concat(this.npmCliConfig),
169
176
  dir,
177
+ { ...process.env, _PACOTE_NO_PREPARE_: noPrepare.join('\n') },
170
178
  { message: 'git dep preparation failed' }
171
179
  )
172
180
  })
package/lib/index.js CHANGED
@@ -1,5 +1,16 @@
1
1
  const { get } = require('./fetcher.js')
2
+ const GitFetcher = require('./git.js')
3
+ const RegistryFetcher = require('./registry.js')
4
+ const FileFetcher = require('./file.js')
5
+ const DirFetcher = require('./dir.js')
6
+ const RemoteFetcher = require('./remote.js')
7
+
2
8
  module.exports = {
9
+ GitFetcher,
10
+ RegistryFetcher,
11
+ FileFetcher,
12
+ DirFetcher,
13
+ RemoteFetcher,
3
14
  resolve: (spec, opts) => get(spec, opts).resolve(),
4
15
  extract: (spec, dest, opts) => get(spec, opts).extract(dest),
5
16
  manifest: (spec, opts) => get(spec, opts).manifest(),
@@ -0,0 +1,15 @@
1
+ // add a sha to a git remote url spec
2
+ const addGitSha = (spec, sha) => {
3
+ if (spec.hosted) {
4
+ const h = spec.hosted
5
+ const opt = { noCommittish: true }
6
+ const base = h.https && h.auth ? h.https(opt) : h.shortcut(opt)
7
+
8
+ return `${base}#${sha}`
9
+ } else {
10
+ // don't use new URL for this, because it doesn't handle scp urls
11
+ return spec.rawSpec.replace(/#.*$/, '') + `#${sha}`
12
+ }
13
+ }
14
+
15
+ module.exports = addGitSha
@@ -7,6 +7,6 @@ module.exports = (fakePlatform = false) => {
7
7
  const home = os.homedir() || resolve(temp, 'npm-' + uidOrPid)
8
8
  const platform = fakePlatform || process.platform
9
9
  const cacheExtra = platform === 'win32' ? 'npm-cache' : '.npm'
10
- const cacheRoot = (platform === 'win32' && process.env.APPDATA) || home
11
- return resolve(cacheRoot, cacheExtra)
10
+ const cacheRoot = (platform === 'win32' && process.env.LOCALAPPDATA) || home
11
+ return resolve(cacheRoot, cacheExtra, '_cacache')
12
12
  }
package/lib/util/npm.js CHANGED
@@ -1,9 +1,15 @@
1
1
  // run an npm command
2
2
  const spawn = require('@npmcli/promise-spawn')
3
+ const {dirname} = require('path')
3
4
 
4
- module.exports = (npmBin, npmCommand, cwd, extra) => {
5
+ module.exports = (npmBin, npmCommand, cwd, env, extra) => {
5
6
  const isJS = npmBin.endsWith('.js')
6
7
  const cmd = isJS ? process.execPath : npmBin
7
8
  const args = (isJS ? [npmBin] : []).concat(npmCommand)
8
- return spawn(cmd, args, { cwd, stdioString: true }, extra)
9
+ // when installing to run the `prepare` script for a git dep, we need
10
+ // to ensure that we don't run into a cycle of checking out packages
11
+ // in temp directories. this lets us link previously-seen repos that
12
+ // are also being prepared.
13
+
14
+ return spawn(cmd, args, { cwd, stdioString: true, env }, extra)
9
15
  }
@@ -0,0 +1,24 @@
1
+ const isPackageBin = require('./is-package-bin.js')
2
+
3
+ const tarCreateOptions = manifest => ({
4
+ cwd: manifest._resolved,
5
+ prefix: 'package/',
6
+ portable: true,
7
+ gzip: true,
8
+
9
+ // ensure that package bins are always executable
10
+ // Note that npm-packlist is already filtering out
11
+ // anything that is not a regular file, ignored by
12
+ // .npmignore or package.json "files", etc.
13
+ filter: (path, stat) => {
14
+ if (isPackageBin(manifest, path))
15
+ stat.mode |= 0o111
16
+ return true
17
+ },
18
+
19
+ // Provide a specific date in the 1980s for the benefit of zip,
20
+ // which is confounded by files dated at the Unix epoch 0.
21
+ mtime: new Date('1985-10-26T08:15:00.000Z'),
22
+ })
23
+
24
+ module.exports = tarCreateOptions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pacote",
3
- "version": "11.2.4",
3
+ "version": "11.3.0",
4
4
  "description": "JavaScript package downloader",
5
5
  "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "mutate-fs": "^2.1.1",
26
26
  "npm-registry-mock": "^1.3.1",
27
27
  "require-inject": "^1.4.4",
28
- "tap": "^14.10.8"
28
+ "tap": "^14.11.0"
29
29
  },
30
30
  "files": [
31
31
  "lib/**/*.js"
@@ -37,9 +37,9 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@npmcli/git": "^2.0.1",
40
- "@npmcli/installed-package-contents": "^1.0.5",
40
+ "@npmcli/installed-package-contents": "^1.0.6",
41
41
  "@npmcli/promise-spawn": "^1.2.0",
42
- "@npmcli/run-script": "^1.3.0",
42
+ "@npmcli/run-script": "^1.8.2",
43
43
  "cacache": "^15.0.5",
44
44
  "chownr": "^2.0.0",
45
45
  "fs-minipass": "^2.1.0",
@@ -50,10 +50,10 @@
50
50
  "npm-packlist": "^2.1.4",
51
51
  "npm-pick-manifest": "^6.0.0",
52
52
  "npm-registry-fetch": "^9.0.0",
53
- "promise-retry": "^1.1.1",
54
- "read-package-json-fast": "^1.1.3",
53
+ "promise-retry": "^2.0.1",
54
+ "read-package-json-fast": "^2.0.1",
55
55
  "rimraf": "^3.0.2",
56
- "ssri": "^8.0.0",
56
+ "ssri": "^8.0.1",
57
57
  "tar": "^6.1.0"
58
58
  },
59
59
  "engines": {