@npmcli/arborist 4.0.3 → 4.1.1

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/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ <!-- This file is automatically added by @npmcli/template-oss. Do not edit. -->
2
+
3
+ ISC License
4
+
5
+ Copyright npm, Inc.
6
+
7
+ Permission to use, copy, modify, and/or distribute this
8
+ software for any purpose with or without fee is hereby
9
+ granted, provided that the above copyright notice and this
10
+ permission notice appear in all copies.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
13
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
15
+ EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
20
+ USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  Inspect and manage `node_modules` trees.
4
4
 
5
- ![a tree with the word ARBORIST superimposed on it](https://raw.githubusercontent.com/npm/arborist/main/logo.svg?sanitize=true)
5
+ ![a tree with the word ARBORIST superimposed on it](https://raw.githubusercontent.com/npm/arborist/main/docs/logo.svg?sanitize=true)
6
6
 
7
- There's more documentation [in the notes
8
- folder](https://github.com/npm/arborist/tree/main/notes).
7
+ There's more documentation [in the docs
8
+ folder](https://github.com/npm/arborist/tree/main/docs).
9
9
 
10
10
  ## USAGE
11
11
 
package/bin/prune.js CHANGED
@@ -6,7 +6,7 @@ require('./lib/logging.js')
6
6
  require('./lib/timers.js')
7
7
 
8
8
  const printDiff = diff => {
9
- const {depth} = require('treeverse')
9
+ const { depth } = require('treeverse')
10
10
  depth({
11
11
  tree: diff,
12
12
  visit: d => {
package/bin/reify.js CHANGED
@@ -6,7 +6,7 @@ require('./lib/logging.js')
6
6
  require('./lib/timers.js')
7
7
 
8
8
  const printDiff = diff => {
9
- const {depth} = require('treeverse')
9
+ const { depth } = require('treeverse')
10
10
  depth({
11
11
  tree: diff,
12
12
  visit: d => {
@@ -2,9 +2,9 @@
2
2
 
3
3
  const localeCompare = require('@isaacs/string-locale-compare')('en')
4
4
 
5
- const add = ({pkg, add, saveBundle, saveType, log}) => {
5
+ const add = ({ pkg, add, saveBundle, saveType, log }) => {
6
6
  for (const spec of add) {
7
- addSingle({pkg, spec, saveBundle, saveType, log})
7
+ addSingle({ pkg, spec, saveBundle, saveType, log })
8
8
  }
9
9
 
10
10
  return pkg
@@ -20,7 +20,7 @@ const saveTypeMap = new Map([
20
20
  ['peer', 'peerDependencies'],
21
21
  ])
22
22
 
23
- const addSingle = ({pkg, spec, saveBundle, saveType, log}) => {
23
+ const addSingle = ({ pkg, spec, saveBundle, saveType, log }) => {
24
24
  const { name, rawSpec } = spec
25
25
 
26
26
  // if the user does not give us a type, we infer which type(s)
@@ -31,7 +31,7 @@ const Node = require('../node.js')
31
31
  const Link = require('../link.js')
32
32
  const addRmPkgDeps = require('../add-rm-pkg-deps.js')
33
33
  const optionalSet = require('../optional-set.js')
34
- const {checkEngine, checkPlatform} = require('npm-install-checks')
34
+ const { checkEngine, checkPlatform } = require('npm-install-checks')
35
35
 
36
36
  const relpath = require('../relpath.js')
37
37
 
@@ -311,7 +311,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
311
311
  ? Shrinkwrap.reset({
312
312
  path: this.path,
313
313
  lockfileVersion: this.options.lockfileVersion,
314
- }).then(meta => Object.assign(root, {meta}))
314
+ }).then(meta => Object.assign(root, { meta }))
315
315
  : this.loadVirtual({ root }))
316
316
 
317
317
  // if we don't have a lockfile to go from, then start with the
@@ -379,6 +379,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
379
379
  optional: false,
380
380
  global: this[_global],
381
381
  legacyPeerDeps: this.legacyPeerDeps,
382
+ loadOverrides: true,
382
383
  })
383
384
  if (root.isLink) {
384
385
  root.target = new Node({
@@ -492,7 +493,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
492
493
 
493
494
  // This returns a promise because we might not have the name yet,
494
495
  // and need to call pacote.manifest to find the name.
495
- [_add] (tree, {add, saveType = null, saveBundle = false}) {
496
+ [_add] (tree, { add, saveType = null, saveBundle = false }) {
496
497
  // get the name for each of the specs in the list.
497
498
  // ie, doing `foo@bar` we just return foo
498
499
  // but if it's a url or git, we don't know the name until we
@@ -676,6 +677,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
676
677
  // calls rather than walking over everything in the tree.
677
678
  const set = this.idealTree.inventory
678
679
  .filter(n => this[_shouldUpdateNode](n))
680
+ // XXX add any invalid edgesOut to the queue
679
681
  for (const node of set) {
680
682
  for (const edge of node.edgesIn) {
681
683
  this.addTracker('idealTree', edge.from.name, edge.from.location)
@@ -772,7 +774,10 @@ This is a one-time fix-up, please be patient...
772
774
  [_buildDeps] () {
773
775
  process.emit('time', 'idealTree:buildDeps')
774
776
  const tree = this.idealTree.target
777
+ tree.assertRootOverrides()
775
778
  this[_depsQueue].push(tree)
779
+ // XXX also push anything that depends on a node with a name
780
+ // in the override list
776
781
  this.log.silly('idealTree', 'buildDeps')
777
782
  this.addTracker('idealTree', tree.name, '')
778
783
  return this[_buildDepStep]()
@@ -936,7 +941,7 @@ This is a one-time fix-up, please be patient...
936
941
  }
937
942
  })
938
943
 
939
- tasks.push({edge, dep})
944
+ tasks.push({ edge, dep })
940
945
  }
941
946
 
942
947
  const placeDeps = tasks
@@ -1112,6 +1117,7 @@ This is a one-time fix-up, please be patient...
1112
1117
  path: node.realpath,
1113
1118
  sourceReference: node,
1114
1119
  legacyPeerDeps: this.legacyPeerDeps,
1120
+ overrides: node.overrides,
1115
1121
  })
1116
1122
 
1117
1123
  // also need to set up any targets from any link deps, so that
@@ -1271,7 +1277,7 @@ This is a one-time fix-up, please be patient...
1271
1277
  // we typically only install non-optional peers, but we have to
1272
1278
  // factor them into the peerSet so that we can avoid conflicts
1273
1279
  .filter(e => e.peer && !(e.valid && e.to))
1274
- .sort(({name: a}, {name: b}) => localeCompare(a, b))
1280
+ .sort(({ name: a }, { name: b }) => localeCompare(a, b))
1275
1281
 
1276
1282
  for (const edge of peerEdges) {
1277
1283
  // already placed this one, and we're happy with it.
@@ -1280,7 +1286,7 @@ This is a one-time fix-up, please be patient...
1280
1286
  }
1281
1287
 
1282
1288
  const parentEdge = node.parent.edgesOut.get(edge.name)
1283
- const {isProjectRoot, isWorkspace} = node.parent.sourceReference
1289
+ const { isProjectRoot, isWorkspace } = node.parent.sourceReference
1284
1290
  const isMine = isProjectRoot || isWorkspace
1285
1291
  const conflictOK = this[_force] || !isMine && !this[_strictPeerDeps]
1286
1292
 
@@ -26,9 +26,10 @@
26
26
  // the base class, so that the overall voltron class is easier to test and
27
27
  // cover, and separation of concerns can be maintained.
28
28
 
29
- const {resolve} = require('path')
30
- const {homedir} = require('os')
29
+ const { resolve } = require('path')
30
+ const { homedir } = require('os')
31
31
  const procLog = require('proc-log')
32
+ const { depth } = require('treeverse')
32
33
  const { saveTypeMap } = require('../add-rm-pkg-deps.js')
33
34
 
34
35
  const mixins = [
@@ -88,6 +89,9 @@ class Arborist extends Base {
88
89
  process.emit('timeEnd', 'arborist:ctor')
89
90
  }
90
91
 
92
+ // TODO: We should change these to static functions instead
93
+ // of methods for the next major version
94
+
91
95
  // returns an array of the actual nodes for all the workspaces
92
96
  workspaceNodes (tree, workspaces) {
93
97
  return getWorkspaceNodes(tree, workspaces, this.log)
@@ -103,15 +107,15 @@ class Arborist extends Base {
103
107
  }
104
108
  }
105
109
  }
106
- const set = new Set(wsNodes)
110
+ const wsDepSet = new Set(wsNodes)
107
111
  const extraneous = new Set()
108
- for (const node of set) {
112
+ for (const node of wsDepSet) {
109
113
  for (const edge of node.edgesOut.values()) {
110
114
  const dep = edge.to
111
115
  if (dep) {
112
- set.add(dep)
116
+ wsDepSet.add(dep)
113
117
  if (dep.isLink) {
114
- set.add(dep.target)
118
+ wsDepSet.add(dep.target)
115
119
  }
116
120
  }
117
121
  }
@@ -122,28 +126,36 @@ class Arborist extends Base {
122
126
  }
123
127
  }
124
128
  for (const extra of extraneous) {
125
- set.add(extra)
129
+ wsDepSet.add(extra)
126
130
  }
127
131
 
128
- return set
132
+ return wsDepSet
129
133
  }
130
134
 
135
+ // returns a set of root dependencies, excluding depdencies that are
136
+ // exclusively workspace dependencies
131
137
  excludeWorkspacesDependencySet (tree) {
132
- const set = new Set()
133
- for (const edge of tree.edgesOut.values()) {
134
- if (edge.type !== 'workspace' && edge.to) {
135
- set.add(edge.to)
136
- }
137
- }
138
- for (const node of set) {
139
- for (const edge of node.edgesOut.values()) {
140
- if (edge.to) {
141
- set.add(edge.to)
138
+ const rootDepSet = new Set()
139
+ depth({
140
+ tree,
141
+ visit: node => {
142
+ for (const { to } of node.edgesOut.values()) {
143
+ if (!to || to.isWorkspace) {
144
+ continue
145
+ }
146
+ for (const edgeIn of to.edgesIn.values()) {
147
+ if (edgeIn.from.isRoot || rootDepSet.has(edgeIn.from)) {
148
+ rootDepSet.add(to)
149
+ }
150
+ }
142
151
  }
143
- }
144
- }
145
-
146
- return set
152
+ return node
153
+ },
154
+ filter: node => node,
155
+ getChildren: (node, tree) =>
156
+ [...tree.edgesOut.values()].map(edge => edge.to),
157
+ })
158
+ return rootDepSet
147
159
  }
148
160
  }
149
161
 
@@ -1,9 +1,9 @@
1
1
  // mix-in implementing the loadActual method
2
2
 
3
- const {relative, dirname, resolve, join, normalize} = require('path')
3
+ const { relative, dirname, resolve, join, normalize } = require('path')
4
4
 
5
5
  const rpj = require('read-package-json-fast')
6
- const {promisify} = require('util')
6
+ const { promisify } = require('util')
7
7
  const readdir = promisify(require('readdir-scoped-modules'))
8
8
  const walkUp = require('walk-up-path')
9
9
  const ancestorPath = require('common-ancestor-path')
@@ -127,16 +127,20 @@ module.exports = cls => class ActualLoader extends cls {
127
127
  realpath: real,
128
128
  pkg: {},
129
129
  global,
130
+ loadOverrides: true,
130
131
  })
131
- return this[_loadActualActually]({root, ignoreMissing, global})
132
+ return this[_loadActualActually]({ root, ignoreMissing, global })
132
133
  }
133
134
 
134
135
  // not in global mode, hidden lockfile is allowed, load root pkg too
135
136
  this[_actualTree] = await this[_loadFSNode]({
136
137
  path: this.path,
137
138
  real: await realpath(this.path, this[_rpcache], this[_stcache]),
139
+ loadOverrides: true,
138
140
  })
139
141
 
142
+ this[_actualTree].assertRootOverrides()
143
+
140
144
  // Note: hidden lockfile will be rejected if it's not the latest thing
141
145
  // in the folder, or if any of the entries in the hidden lockfile are
142
146
  // missing.
@@ -163,7 +167,7 @@ module.exports = cls => class ActualLoader extends cls {
163
167
  // we can't easily get a ref to Arborist in this module, without
164
168
  // creating a circular reference, since this class is a mixin used
165
169
  // to build up the Arborist class itself.
166
- await new this.constructor({...this.options}).loadVirtual({
170
+ await new this.constructor({ ...this.options }).loadVirtual({
167
171
  root: this[_actualTree],
168
172
  })
169
173
  await this[_loadWorkspaces](this[_actualTree])
@@ -236,13 +240,26 @@ module.exports = cls => class ActualLoader extends cls {
236
240
  this[_actualTree] = root
237
241
  }
238
242
 
239
- [_loadFSNode] ({ path, parent, real, root }) {
243
+ [_loadFSNode] ({ path, parent, real, root, loadOverrides }) {
240
244
  if (!real) {
241
245
  return realpath(path, this[_rpcache], this[_stcache])
242
246
  .then(
243
- real => this[_loadFSNode]({ path, parent, real, root }),
247
+ real => this[_loadFSNode]({
248
+ path,
249
+ parent,
250
+ real,
251
+ root,
252
+ loadOverrides,
253
+ }),
244
254
  // if realpath fails, just provide a dummy error node
245
- error => new Node({ error, path, realpath: path, parent, root })
255
+ error => new Node({
256
+ error,
257
+ path,
258
+ realpath: path,
259
+ parent,
260
+ root,
261
+ loadOverrides,
262
+ })
246
263
  )
247
264
  }
248
265
 
@@ -271,6 +288,7 @@ module.exports = cls => class ActualLoader extends cls {
271
288
  error,
272
289
  parent,
273
290
  root,
291
+ loadOverrides,
274
292
  })
275
293
  })
276
294
  .then(node => {
@@ -1,7 +1,7 @@
1
1
  // mixin providing the loadVirtual method
2
2
  const localeCompare = require('@isaacs/string-locale-compare')('en')
3
3
 
4
- const {resolve} = require('path')
4
+ const { resolve } = require('path')
5
5
 
6
6
  const nameFromFolder = require('@npmcli/name-from-folder')
7
7
  const consistentResolve = require('../consistent-resolve.js')
@@ -72,6 +72,7 @@ module.exports = cls => class VirtualLoader extends cls {
72
72
  this[rootOptionProvided] = options.root
73
73
 
74
74
  await this[loadFromShrinkwrap](s, root)
75
+ root.assertRootOverrides()
75
76
  return treeCheck(this.virtualTree)
76
77
  }
77
78
 
@@ -97,7 +98,7 @@ module.exports = cls => class VirtualLoader extends cls {
97
98
  this[checkRootEdges](s, root)
98
99
  root.meta = s
99
100
  this.virtualTree = root
100
- const {links, nodes} = this[resolveNodes](s, root)
101
+ const { links, nodes } = this[resolveNodes](s, root)
101
102
  await this[resolveLinks](links, nodes)
102
103
  if (!(s.originalLockfileVersion >= 2)) {
103
104
  this[assignBundles](nodes)
@@ -208,7 +209,7 @@ module.exports = cls => class VirtualLoader extends cls {
208
209
  nodes.set(location, this[loadNode](location, meta))
209
210
  }
210
211
  }
211
- return {links, nodes}
212
+ return { links, nodes }
212
213
  }
213
214
 
214
215
  // links is the set of metadata, and nodes is the map of non-Link nodes
@@ -240,7 +241,7 @@ module.exports = cls => class VirtualLoader extends cls {
240
241
  if (!location || node.isLink && !node.target.location) {
241
242
  continue
242
243
  }
243
- const { name, parent, package: { inBundle }} = node
244
+ const { name, parent, package: { inBundle } } = node
244
245
 
245
246
  if (!parent) {
246
247
  continue
@@ -2,13 +2,13 @@
2
2
  // bundle building needed. Called by reify, and by `npm rebuild`.
3
3
 
4
4
  const localeCompare = require('@isaacs/string-locale-compare')('en')
5
- const {depth: dfwalk} = require('treeverse')
5
+ const { depth: dfwalk } = require('treeverse')
6
6
  const promiseAllRejectLate = require('promise-all-reject-late')
7
7
  const rpj = require('read-package-json-fast')
8
8
  const binLinks = require('bin-links')
9
9
  const runScript = require('@npmcli/run-script')
10
10
  const promiseCallLimit = require('promise-call-limit')
11
- const {resolve} = require('path')
11
+ const { resolve } = require('path')
12
12
  const {
13
13
  isNodeGypPackage,
14
14
  defaultGypInstallScript,
@@ -220,7 +220,7 @@ module.exports = cls => class Builder extends cls {
220
220
  }
221
221
 
222
222
  if (this[_oldMeta] === null) {
223
- const {root: {meta}} = node
223
+ const { root: { meta } } = node
224
224
  this[_oldMeta] = meta && meta.loadedFromDisk &&
225
225
  !(meta.originalLockfileVersion >= 2)
226
226
  }
@@ -242,7 +242,7 @@ module.exports = cls => class Builder extends cls {
242
242
  const pkg = await rpj(node.path + '/package.json').catch(() => ({}))
243
243
  set.delete(node)
244
244
 
245
- const {scripts = {}} = pkg
245
+ const { scripts = {} } = pkg
246
246
  node.package.scripts = scripts
247
247
  return this[_addToBuildSet](node, set, true)
248
248
  }
@@ -319,9 +319,9 @@ module.exports = cls => class Builder extends cls {
319
319
  }
320
320
  const p = runScript(runOpts).catch(er => {
321
321
  const { code, signal } = er
322
- this.log.info('run', pkg._id, event, {code, signal})
322
+ this.log.info('run', pkg._id, event, { code, signal })
323
323
  throw er
324
- }).then(({args, code, signal, stdout, stderr}) => {
324
+ }).then(({ args, code, signal, stdout, stderr }) => {
325
325
  this.scriptsRun.add({
326
326
  pkg,
327
327
  path,
@@ -333,7 +333,7 @@ module.exports = cls => class Builder extends cls {
333
333
  stdout,
334
334
  stderr,
335
335
  })
336
- this.log.info('run', pkg._id, event, {code, signal})
336
+ this.log.info('run', pkg._id, event, { code, signal })
337
337
  })
338
338
 
339
339
  await (this[_doHandleOptionalFailure]
@@ -3,15 +3,15 @@
3
3
  const onExit = require('../signal-handling.js')
4
4
  const pacote = require('pacote')
5
5
  const AuditReport = require('../audit-report.js')
6
- const {subset, intersects} = require('semver')
6
+ const { subset, intersects } = require('semver')
7
7
  const npa = require('npm-package-arg')
8
8
  const debug = require('../debug.js')
9
9
  const walkUp = require('walk-up-path')
10
10
 
11
- const {dirname, resolve, relative} = require('path')
12
- const {depth: dfwalk} = require('treeverse')
11
+ const { dirname, resolve, relative } = require('path')
12
+ const { depth: dfwalk } = require('treeverse')
13
13
  const fs = require('fs')
14
- const {promisify} = require('util')
14
+ const { promisify } = require('util')
15
15
  const lstat = promisify(fs.lstat)
16
16
  const symlink = promisify(fs.symlink)
17
17
  const mkdirp = require('mkdirp-infer-owner')
@@ -188,7 +188,7 @@ module.exports = cls => class Reifier extends cls {
188
188
  // ok, we're about to start touching the fs. need to roll back
189
189
  // if we get an early termination.
190
190
  let reifyTerminated = null
191
- const removeHandler = onExit(({signal}) => {
191
+ const removeHandler = onExit(({ signal }) => {
192
192
  // only call once. if signal hits twice, we just terminate
193
193
  removeHandler()
194
194
  reifyTerminated = Object.assign(new Error('process terminated'), {
@@ -352,7 +352,7 @@ module.exports = cls => class Reifier extends cls {
352
352
  if (includeRootDeps) {
353
353
  // add all non-workspace nodes to filterNodes
354
354
  for (const tree of [this.idealTree, this.actualTree]) {
355
- for (const {type, to} of tree.edgesOut.values()) {
355
+ for (const { type, to } of tree.edgesOut.values()) {
356
356
  if (type !== 'workspace' && to) {
357
357
  filterNodes.push(to)
358
358
  }
@@ -686,7 +686,7 @@ module.exports = cls => class Reifier extends cls {
686
686
  }
687
687
 
688
688
  [_warnDeprecated] (node) {
689
- const {_id, deprecated} = node.package
689
+ const { _id, deprecated } = node.package
690
690
  if (deprecated) {
691
691
  this.log.warn('deprecated', `${_id}: ${deprecated}`)
692
692
  }
@@ -1159,7 +1159,7 @@ module.exports = cls => class Reifier extends cls {
1159
1159
  const edge = addTree.edgesOut.get(name)
1160
1160
  const pkg = addTree.package
1161
1161
  const req = npa.resolve(name, edge.spec, addTree.realpath)
1162
- const {rawSpec, subSpec} = req
1162
+ const { rawSpec, subSpec } = req
1163
1163
 
1164
1164
  const spec = subSpec ? subSpec.rawSpec : rawSpec
1165
1165
  const child = edge.to
@@ -1173,6 +1173,10 @@ module.exports = cls => class Reifier extends cls {
1173
1173
  }
1174
1174
 
1175
1175
  let newSpec
1176
+ // True if the dependency is getting installed from a local file path
1177
+ // In this case it is not possible to do the normal version comparisons
1178
+ // as the new version will be a file path
1179
+ const isLocalDep = req.type === 'directory' || req.type === 'file'
1176
1180
  if (req.registry) {
1177
1181
  const version = child.version
1178
1182
  const prefixRange = version ? this[_savePrefix] + version : '*'
@@ -1204,7 +1208,7 @@ module.exports = cls => class Reifier extends cls {
1204
1208
  } else {
1205
1209
  newSpec = h.shortcut(opt)
1206
1210
  }
1207
- } else if (req.type === 'directory' || req.type === 'file') {
1211
+ } else if (isLocalDep) {
1208
1212
  // save the relative path in package.json
1209
1213
  // Normally saveSpec is updated with the proper relative
1210
1214
  // path already, but it's possible to specify a full absolute
@@ -1233,11 +1237,11 @@ module.exports = cls => class Reifier extends cls {
1233
1237
  if (hasSubKey(pkg, 'devDependencies', name)) {
1234
1238
  pkg.devDependencies[name] = newSpec
1235
1239
  // don't update peer or optional if we don't have to
1236
- if (hasSubKey(pkg, 'peerDependencies', name) && !intersects(newSpec, pkg.peerDependencies[name])) {
1240
+ if (hasSubKey(pkg, 'peerDependencies', name) && (isLocalDep || !intersects(newSpec, pkg.peerDependencies[name]))) {
1237
1241
  pkg.peerDependencies[name] = newSpec
1238
1242
  }
1239
1243
 
1240
- if (hasSubKey(pkg, 'optionalDependencies', name) && !intersects(newSpec, pkg.optionalDependencies[name])) {
1244
+ if (hasSubKey(pkg, 'optionalDependencies', name) && (isLocalDep || !intersects(newSpec, pkg.optionalDependencies[name]))) {
1241
1245
  pkg.optionalDependencies[name] = newSpec
1242
1246
  }
1243
1247
  } else {
@@ -265,7 +265,7 @@ class AuditReport extends Map {
265
265
  avoid: vuln.range,
266
266
  avoidStrict: true,
267
267
  })
268
- return {name, version, isSemVerMajor}
268
+ return { name, version, isSemVerMajor }
269
269
  } catch (er) {
270
270
  return false
271
271
  }
@@ -285,7 +285,7 @@ class AuditReport extends Map {
285
285
  }
286
286
 
287
287
  const bulk = {}
288
- const {advisories} = report
288
+ const { advisories } = report
289
289
  for (const advisory of Object.values(advisories)) {
290
290
  const {
291
291
  id,
@@ -296,7 +296,7 @@ class AuditReport extends Map {
296
296
  module_name: name,
297
297
  } = advisory
298
298
  bulk[name] = bulk[name] || []
299
- bulk[name].push({id, url, title, severity, vulnerable_versions})
299
+ bulk[name].push({ id, url, title, severity, vulnerable_versions })
300
300
  }
301
301
 
302
302
  return bulk
@@ -38,7 +38,7 @@ const calcDepFlagsStep = (node) => {
38
38
  return calcDepFlagsStep(node.target)
39
39
  }
40
40
 
41
- node.edgesOut.forEach(({peer, optional, dev, to}) => {
41
+ node.edgesOut.forEach(({ peer, optional, dev, to }) => {
42
42
  // if the dep is missing, then its flags are already maximally unset
43
43
  if (!to) {
44
44
  return
@@ -78,7 +78,7 @@ class CanPlaceDep {
78
78
  }
79
79
 
80
80
  this._treeSnapshot = JSON.stringify([...target.root.inventory.entries()]
81
- .map(([loc, {packageName, version, resolved}]) => {
81
+ .map(([loc, { packageName, version, resolved }]) => {
82
82
  return [loc, packageName, version, resolved]
83
83
  }).sort(([a], [b]) => localeCompare(a, b)))
84
84
  })
@@ -118,7 +118,7 @@ class CanPlaceDep {
118
118
 
119
119
  debug(() => {
120
120
  const treeSnapshot = JSON.stringify([...target.root.inventory.entries()]
121
- .map(([loc, {packageName, version, resolved}]) => {
121
+ .map(([loc, { packageName, version, resolved }]) => {
122
122
  return [loc, packageName, version, resolved]
123
123
  }).sort(([a], [b]) => localeCompare(a, b)))
124
124
  /* istanbul ignore if */
package/lib/dep-valid.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  const semver = require('semver')
8
8
  const npa = require('npm-package-arg')
9
- const {relative} = require('path')
9
+ const { relative } = require('path')
10
10
  const fromPath = require('./from-path.js')
11
11
 
12
12
  const depValid = (child, requested, requestor) => {
package/lib/diff.js CHANGED
@@ -5,13 +5,13 @@
5
5
  // Thus, the root Diff node is the shallowest change required
6
6
  // for a given branch of the tree being mutated.
7
7
 
8
- const {depth} = require('treeverse')
9
- const {existsSync} = require('fs')
8
+ const { depth } = require('treeverse')
9
+ const { existsSync } = require('fs')
10
10
 
11
11
  const ssri = require('ssri')
12
12
 
13
13
  class Diff {
14
- constructor ({actual, ideal, filterSet, shrinkwrapInflated}) {
14
+ constructor ({ actual, ideal, filterSet, shrinkwrapInflated }) {
15
15
  this.filterSet = filterSet
16
16
  this.shrinkwrapInflated = shrinkwrapInflated
17
17
  this.children = []
@@ -94,14 +94,14 @@ class Diff {
94
94
  }
95
95
 
96
96
  return depth({
97
- tree: new Diff({actual, ideal, filterSet, shrinkwrapInflated}),
97
+ tree: new Diff({ actual, ideal, filterSet, shrinkwrapInflated }),
98
98
  getChildren,
99
99
  leave,
100
100
  })
101
101
  }
102
102
  }
103
103
 
104
- const getAction = ({actual, ideal}) => {
104
+ const getAction = ({ actual, ideal }) => {
105
105
  if (!ideal) {
106
106
  return 'REMOVE'
107
107
  }
@@ -237,7 +237,7 @@ const diffNode = ({
237
237
  return
238
238
  }
239
239
 
240
- const action = getAction({actual, ideal})
240
+ const action = getAction({ actual, ideal })
241
241
 
242
242
  // if it's a match, then get its children
243
243
  // otherwise, this is the child diff node
@@ -245,7 +245,7 @@ const diffNode = ({
245
245
  if (action === 'REMOVE') {
246
246
  removed.push(actual)
247
247
  }
248
- children.push(new Diff({actual, ideal, filterSet, shrinkwrapInflated}))
248
+ children.push(new Diff({ actual, ideal, filterSet, shrinkwrapInflated }))
249
249
  } else {
250
250
  unchanged.push(ideal)
251
251
  // !*! Weird dirty hack warning !*!
package/lib/edge.js CHANGED
@@ -29,6 +29,7 @@ class ArboristEdge {}
29
29
  const printableEdge = (edge) => {
30
30
  const edgeFrom = edge.from && edge.from.location
31
31
  const edgeTo = edge.to && edge.to.location
32
+ const override = edge.overrides && edge.overrides.value
32
33
 
33
34
  return Object.assign(new ArboristEdge(), {
34
35
  name: edge.name,
@@ -38,12 +39,13 @@ const printableEdge = (edge) => {
38
39
  ...(edgeTo ? { to: edgeTo } : {}),
39
40
  ...(edge.error ? { error: edge.error } : {}),
40
41
  ...(edge.peerConflicted ? { peerConflicted: true } : {}),
42
+ ...(override ? { overridden: override } : {}),
41
43
  })
42
44
  }
43
45
 
44
46
  class Edge {
45
47
  constructor (options) {
46
- const { type, name, spec, accept, from } = options
48
+ const { type, name, spec, accept, from, overrides } = options
47
49
 
48
50
  if (typeof spec !== 'string') {
49
51
  throw new TypeError('must provide string spec')
@@ -55,6 +57,10 @@ class Edge {
55
57
 
56
58
  this[_spec] = spec
57
59
 
60
+ if (overrides !== undefined) {
61
+ this.overrides = overrides
62
+ }
63
+
58
64
  if (accept !== undefined) {
59
65
  if (typeof accept !== 'string') {
60
66
  throw new TypeError('accept field must be a string if provided')
@@ -82,8 +88,11 @@ class Edge {
82
88
  }
83
89
 
84
90
  satisfiedBy (node) {
85
- return node.name === this.name &&
86
- depValid(node, this.spec, this.accept, this.from)
91
+ if (node.name !== this.name) {
92
+ return false
93
+ }
94
+
95
+ return depValid(node, this.spec, this.accept, this.from)
87
96
  }
88
97
 
89
98
  explain (seen = []) {
@@ -101,6 +110,10 @@ class Edge {
101
110
  type: this.type,
102
111
  name: this.name,
103
112
  spec: this.spec,
113
+ ...(this.rawSpec !== this.spec ? {
114
+ rawSpec: this.rawSpec,
115
+ overridden: true,
116
+ } : {}),
104
117
  ...(bundled ? { bundled } : {}),
105
118
  ...(error ? { error } : {}),
106
119
  ...(from ? { from: from.explain(null, seen) } : {}),
@@ -143,7 +156,28 @@ class Edge {
143
156
  return this[_name]
144
157
  }
145
158
 
159
+ get rawSpec () {
160
+ return this[_spec]
161
+ }
162
+
146
163
  get spec () {
164
+ if (this.overrides && this.overrides.value && this.overrides.name === this.name) {
165
+ if (this.overrides.value.startsWith('$')) {
166
+ const ref = this.overrides.value.slice(1)
167
+ const pkg = this.from.root.package
168
+ const overrideSpec = (pkg.devDependencies && pkg.devDependencies[ref]) ||
169
+ (pkg.optionalDependencies && pkg.optionalDependencies[ref]) ||
170
+ (pkg.dependencies && pkg.dependencies[ref]) ||
171
+ (pkg.peerDependencies && pkg.peerDependencies[ref])
172
+
173
+ if (overrideSpec) {
174
+ return overrideSpec
175
+ }
176
+
177
+ throw new Error(`Unable to resolve reference ${this.overrides.value}`)
178
+ }
179
+ return this.overrides.value
180
+ }
147
181
  return this[_spec]
148
182
  }
149
183
 
@@ -213,6 +247,7 @@ class Edge {
213
247
  if (node.edgesOut.has(this.name)) {
214
248
  node.edgesOut.get(this.name).detach()
215
249
  }
250
+
216
251
  node.addEdgeOut(this)
217
252
  this.reload()
218
253
  }
package/lib/from-path.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // end up getting installed. directory (ie, symlink) deps also need
4
4
  // to be resolved based on their targets, but that's what realpath is
5
5
 
6
- const {dirname} = require('path')
6
+ const { dirname } = require('path')
7
7
  const npa = require('npm-package-arg')
8
8
 
9
9
  const fromPath = (node, spec) =>
package/lib/link.js CHANGED
@@ -3,7 +3,7 @@ const relpath = require('./relpath.js')
3
3
  const Node = require('./node.js')
4
4
  const _loadDeps = Symbol.for('Arborist.Node._loadDeps')
5
5
  const _target = Symbol.for('_target')
6
- const {dirname} = require('path')
6
+ const { dirname } = require('path')
7
7
  // defined by Node class
8
8
  const _delistFromMeta = Symbol.for('_delistFromMeta')
9
9
  const _refreshLocation = Symbol.for('_refreshLocation')
package/lib/node.js CHANGED
@@ -32,15 +32,16 @@ const semver = require('semver')
32
32
  const nameFromFolder = require('@npmcli/name-from-folder')
33
33
  const Edge = require('./edge.js')
34
34
  const Inventory = require('./inventory.js')
35
- const {normalize} = require('read-package-json-fast')
36
- const {getPaths: getBinPaths} = require('bin-links')
35
+ const OverrideSet = require('./override-set.js')
36
+ const { normalize } = require('read-package-json-fast')
37
+ const { getPaths: getBinPaths } = require('bin-links')
37
38
  const npa = require('npm-package-arg')
38
39
  const debug = require('./debug.js')
39
40
  const gatherDepSet = require('./gather-dep-set.js')
40
41
  const treeCheck = require('./tree-check.js')
41
42
  const walkUp = require('walk-up-path')
42
43
 
43
- const {resolve, relative, dirname, basename} = require('path')
44
+ const { resolve, relative, dirname, basename } = require('path')
44
45
  const util = require('util')
45
46
  const _package = Symbol('_package')
46
47
  const _parent = Symbol('_parent')
@@ -88,6 +89,8 @@ class Node {
88
89
  legacyPeerDeps = false,
89
90
  linksIn,
90
91
  hasShrinkwrap,
92
+ overrides,
93
+ loadOverrides = false,
91
94
  extraneous = true,
92
95
  dev = true,
93
96
  optional = true,
@@ -190,6 +193,17 @@ class Node {
190
193
  // because this.package is read when adding to inventory
191
194
  this[_package] = pkg && typeof pkg === 'object' ? pkg : {}
192
195
 
196
+ if (overrides) {
197
+ this.overrides = overrides
198
+ } else if (loadOverrides) {
199
+ const overrides = this[_package].overrides || {}
200
+ if (Object.keys(overrides).length > 0) {
201
+ this.overrides = new OverrideSet({
202
+ overrides: this[_package].overrides,
203
+ })
204
+ }
205
+ }
206
+
193
207
  // only relevant for the root and top nodes
194
208
  this.meta = meta
195
209
 
@@ -291,8 +305,8 @@ class Node {
291
305
  }
292
306
 
293
307
  get hasInstallScript () {
294
- const {hasInstallScript, scripts} = this.package
295
- const {install, preinstall, postinstall} = scripts || {}
308
+ const { hasInstallScript, scripts } = this.package
309
+ const { install, preinstall, postinstall } = scripts || {}
296
310
  return !!(hasInstallScript || install || preinstall || postinstall)
297
311
  }
298
312
 
@@ -376,7 +390,7 @@ class Node {
376
390
  }
377
391
 
378
392
  if (this.root.sourceReference) {
379
- const {name, version} = this.root.package
393
+ const { name, version } = this.root.package
380
394
  why.whileInstalling = {
381
395
  name,
382
396
  version,
@@ -963,6 +977,11 @@ class Node {
963
977
  return false
964
978
  }
965
979
 
980
+ // XXX need to check for two root nodes?
981
+ if (node.overrides !== this.overrides) {
982
+ return false
983
+ }
984
+
966
985
  ignorePeers = new Set(ignorePeers)
967
986
 
968
987
  // gather up all the deps of this node and that are only depended
@@ -1208,6 +1227,10 @@ class Node {
1208
1227
  this[_changePath](newPath)
1209
1228
  }
1210
1229
 
1230
+ if (parent.overrides) {
1231
+ this.overrides = parent.overrides.getNodeRule(this)
1232
+ }
1233
+
1211
1234
  // clobbers anything at that path, resets all appropriate references
1212
1235
  this.root = parent.root
1213
1236
  }
@@ -1279,11 +1302,33 @@ class Node {
1279
1302
  }
1280
1303
  }
1281
1304
 
1305
+ assertRootOverrides () {
1306
+ if (!this.isProjectRoot || !this.overrides) {
1307
+ return
1308
+ }
1309
+
1310
+ for (const edge of this.edgesOut.values()) {
1311
+ // if these differ an override has been applied, those are not allowed
1312
+ // for top level dependencies so throw an error
1313
+ if (edge.spec !== edge.rawSpec && !edge.spec.startsWith('$')) {
1314
+ throw Object.assign(new Error(`Override for ${edge.name}@${edge.rawSpec} conflicts with direct dependency`), { code: 'EOVERRIDE' })
1315
+ }
1316
+ }
1317
+ }
1318
+
1282
1319
  addEdgeOut (edge) {
1320
+ if (this.overrides) {
1321
+ edge.overrides = this.overrides.getEdgeRule(edge)
1322
+ }
1323
+
1283
1324
  this.edgesOut.set(edge.name, edge)
1284
1325
  }
1285
1326
 
1286
1327
  addEdgeIn (edge) {
1328
+ if (edge.overrides) {
1329
+ this.overrides = edge.overrides
1330
+ }
1331
+
1287
1332
  this.edgesIn.add(edge)
1288
1333
 
1289
1334
  // try to get metadata from the yarn.lock file
@@ -0,0 +1,123 @@
1
+ const npa = require('npm-package-arg')
2
+ const semver = require('semver')
3
+
4
+ class OverrideSet {
5
+ constructor ({ overrides, key, parent }) {
6
+ this.parent = parent
7
+ this.children = new Map()
8
+
9
+ if (typeof overrides === 'string') {
10
+ overrides = { '.': overrides }
11
+ }
12
+
13
+ // change a literal empty string to * so we can use truthiness checks on
14
+ // the value property later
15
+ if (overrides['.'] === '') {
16
+ overrides['.'] = '*'
17
+ }
18
+
19
+ if (parent) {
20
+ const spec = npa(key)
21
+ if (!spec.name) {
22
+ throw new Error(`Override without name: ${key}`)
23
+ }
24
+
25
+ this.name = spec.name
26
+ spec.name = ''
27
+ this.key = key
28
+ this.keySpec = spec.rawSpec === '' ? '' : spec.toString()
29
+ this.value = overrides['.'] || this.keySpec
30
+ }
31
+
32
+ for (const [key, childOverrides] of Object.entries(overrides)) {
33
+ if (key === '.') {
34
+ continue
35
+ }
36
+
37
+ const child = new OverrideSet({
38
+ parent: this,
39
+ key,
40
+ overrides: childOverrides,
41
+ })
42
+
43
+ this.children.set(child.key, child)
44
+ }
45
+ }
46
+
47
+ getEdgeRule (edge) {
48
+ for (const rule of this.ruleset.values()) {
49
+ if (rule.name !== edge.name) {
50
+ continue
51
+ }
52
+
53
+ if (rule.keySpec === '' ||
54
+ semver.intersects(edge.spec, rule.keySpec)) {
55
+ return rule
56
+ }
57
+ }
58
+
59
+ return this
60
+ }
61
+
62
+ getNodeRule (node) {
63
+ for (const rule of this.ruleset.values()) {
64
+ if (rule.name !== node.name) {
65
+ continue
66
+ }
67
+
68
+ if (rule.keySpec === '' ||
69
+ semver.satisfies(node.version, rule.keySpec) ||
70
+ semver.satisfies(node.version, rule.value)) {
71
+ return rule
72
+ }
73
+ }
74
+
75
+ return this
76
+ }
77
+
78
+ getMatchingRule (node) {
79
+ for (const rule of this.ruleset.values()) {
80
+ if (rule.name !== node.name) {
81
+ continue
82
+ }
83
+
84
+ if (rule.keySpec === '' ||
85
+ semver.satisfies(node.version, rule.keySpec) ||
86
+ semver.satisfies(node.version, rule.value)) {
87
+ return rule
88
+ }
89
+ }
90
+
91
+ return null
92
+ }
93
+
94
+ * ancestry () {
95
+ for (let ancestor = this; ancestor; ancestor = ancestor.parent) {
96
+ yield ancestor
97
+ }
98
+ }
99
+
100
+ get isRoot () {
101
+ return !this.parent
102
+ }
103
+
104
+ get ruleset () {
105
+ const ruleset = new Map()
106
+
107
+ for (const override of this.ancestry()) {
108
+ for (const kid of override.children.values()) {
109
+ if (!ruleset.has(kid.key)) {
110
+ ruleset.set(kid.key, kid)
111
+ }
112
+ }
113
+
114
+ if (!override.isRoot && !ruleset.has(override.key)) {
115
+ ruleset.set(override.key, override)
116
+ }
117
+ }
118
+
119
+ return ruleset
120
+ }
121
+ }
122
+
123
+ module.exports = OverrideSet
package/lib/place-dep.js CHANGED
@@ -295,6 +295,7 @@ class PlaceDep {
295
295
  integrity: dep.integrity,
296
296
  legacyPeerDeps: this.legacyPeerDeps,
297
297
  error: dep.errors[0],
298
+ ...(dep.overrides ? { overrides: dep.overrides } : {}),
298
299
  ...(dep.isLink ? { target: dep.target, realpath: dep.realpath } : {}),
299
300
  })
300
301
 
@@ -407,11 +408,12 @@ class PlaceDep {
407
408
  for (const entryEdge of peerEntrySets(edge.from).keys()) {
408
409
  // either this one needs to be pruned and re-evaluated, or marked
409
410
  // as peerConflicted and warned about. If the entryEdge comes in from
410
- // the root, then we have to leave it alone, and in that case, it
411
- // will have already warned or crashed by getting to this point.
411
+ // the root or a workspace, then we have to leave it alone, and in that
412
+ // case, it will have already warned or crashed by getting to this point
412
413
  const entryNode = entryEdge.to
413
414
  const deepestTarget = deepestNestingTarget(entryNode)
414
- if (deepestTarget !== target && !entryEdge.from.isRoot) {
415
+ if (deepestTarget !== target &&
416
+ !(entryEdge.from.isProjectRoot || entryEdge.from.isWorkspace)) {
415
417
  prunePeerSets.push(...gatherDepSet([entryNode], e => {
416
418
  return e.to !== entryNode && !e.peerConflicted
417
419
  }))
package/lib/printable.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // helper function to output a clearer visualization
2
2
  // of the current node and its descendents
3
-
4
3
  const localeCompare = require('@isaacs/string-locale-compare')('en')
5
4
  const util = require('util')
6
5
  const relpath = require('./relpath.js')
@@ -65,6 +64,11 @@ class ArboristNode {
65
64
  this.errors = tree.errors.map(treeError)
66
65
  }
67
66
 
67
+ if (tree.overrides) {
68
+ this.overrides = new Map([...tree.overrides.ruleset.values()]
69
+ .map((override) => [override.key, override.value]))
70
+ }
71
+
68
72
  // edgesOut sorted by name
69
73
  if (tree.edgesOut.size) {
70
74
  this.edgesOut = new Map([...tree.edgesOut.entries()]
@@ -87,7 +91,7 @@ class ArboristNode {
87
91
  // fsChildren sorted by path
88
92
  if (tree.fsChildren.size) {
89
93
  this.fsChildren = new Set([...tree.fsChildren]
90
- .sort(({path: a}, {path: b}) => localeCompare(a, b))
94
+ .sort(({ path: a }, { path: b }) => localeCompare(a, b))
91
95
  .map(tree => printableTree(tree, path)))
92
96
  }
93
97
 
@@ -114,7 +118,7 @@ class ArboristLink extends ArboristNode {
114
118
  }
115
119
  }
116
120
 
117
- const treeError = ({code, path}) => ({
121
+ const treeError = ({ code, path }) => ({
118
122
  code,
119
123
  ...(path ? { path } : {}),
120
124
  })
@@ -126,7 +130,10 @@ class Edge {
126
130
  constructor (edge) {
127
131
  this.type = edge.type
128
132
  this.name = edge.name
129
- this.spec = edge.spec || '*'
133
+ this.spec = edge.rawSpec || '*'
134
+ if (edge.rawSpec !== edge.spec) {
135
+ this.override = edge.spec
136
+ }
130
137
  if (edge.error) {
131
138
  this.error = edge.error
132
139
  }
@@ -145,6 +152,8 @@ class EdgeOut extends Edge {
145
152
 
146
153
  [util.inspect.custom] () {
147
154
  return `{ ${this.type} ${this.name}@${this.spec}${
155
+ this.override ? ` overridden:${this.override}` : ''
156
+ }${
148
157
  this.to ? ' -> ' + this.to : ''
149
158
  }${
150
159
  this.error ? ' ' + this.error : ''
package/lib/relpath.js CHANGED
@@ -1,3 +1,3 @@
1
- const {relative} = require('path')
1
+ const { relative } = require('path')
2
2
  const relpath = (from, to) => relative(from, to).replace(/\\/g, '/')
3
3
  module.exports = relpath
@@ -1,5 +1,5 @@
1
1
  const crypto = require('crypto')
2
- const {dirname, basename, resolve} = require('path')
2
+ const { dirname, basename, resolve } = require('path')
3
3
 
4
4
  // use sha1 because it's faster, and collisions extremely unlikely anyway
5
5
  const pathSafeHash = s =>
package/lib/shrinkwrap.js CHANGED
@@ -35,7 +35,7 @@ const mismatch = (a, b) => a && b && a !== b
35
35
 
36
36
  const procLog = require('proc-log')
37
37
  const YarnLock = require('./yarn-lock.js')
38
- const {promisify} = require('util')
38
+ const { promisify } = require('util')
39
39
  const rimraf = promisify(require('rimraf'))
40
40
  const fs = require('fs')
41
41
  const readFile = promisify(fs.readFile)
@@ -180,7 +180,7 @@ const assertNoNewer = async (path, data, lockTime, dir = path, seen = null) => {
180
180
 
181
181
  const parent = isParent ? dir : resolve(dir, 'node_modules')
182
182
  const children = dir === path
183
- ? Promise.resolve([{name: 'node_modules', isDirectory: () => true }])
183
+ ? Promise.resolve([{ name: 'node_modules', isDirectory: () => true }])
184
184
  : readdir(parent, { withFileTypes: true })
185
185
 
186
186
  return children.catch(() => [])
@@ -366,7 +366,7 @@ class Shrinkwrap {
366
366
  if (fromYarn && fromYarn.version) {
367
367
  // if it's the yarn or npm default registry, use the version as
368
368
  // our effective spec. if it's any other kind of thing, use that.
369
- const {resolved, version, integrity} = fromYarn
369
+ const { resolved, version, integrity } = fromYarn
370
370
  const isYarnReg = spec.registry && yarnRegRe.test(resolved)
371
371
  const isnpmReg = spec.registry && !isYarnReg && npmRegRe.test(resolved)
372
372
  const isReg = isnpmReg || isYarnReg
@@ -1062,7 +1062,7 @@ class Shrinkwrap {
1062
1062
  }
1063
1063
 
1064
1064
  // now we walk the children, putting them in the 'dependencies' object
1065
- const {children} = node.target
1065
+ const { children } = node.target
1066
1066
  if (!children.size) {
1067
1067
  delete lock.dependencies
1068
1068
  } else {
@@ -1,7 +1,7 @@
1
1
  /* eslint node/no-deprecated-api: "off" */
2
2
  const semver = require('semver')
3
- const {basename} = require('path')
4
- const {parse} = require('url')
3
+ const { basename } = require('path')
4
+ const { parse } = require('url')
5
5
  module.exports = (name, tgz) => {
6
6
  const base = basename(tgz)
7
7
  if (!base.endsWith('.tgz')) {
package/lib/vuln.js CHANGED
@@ -11,7 +11,7 @@
11
11
  // @npmcli/metavuln-calculator
12
12
  // - via: dependency vulns which cause this one
13
13
 
14
- const {satisfies, simplifyRange} = require('semver')
14
+ const { satisfies, simplifyRange } = require('semver')
15
15
  const semverOpt = { loose: true, includePrerelease: true }
16
16
 
17
17
  const localeCompare = require('@isaacs/string-locale-compare')('en')
package/lib/yarn-lock.js CHANGED
@@ -30,8 +30,8 @@
30
30
 
31
31
  const localeCompare = require('@isaacs/string-locale-compare')('en')
32
32
  const consistentResolve = require('./consistent-resolve.js')
33
- const {dirname} = require('path')
34
- const {breadth} = require('treeverse')
33
+ const { dirname } = require('path')
34
+ const { breadth } = require('treeverse')
35
35
 
36
36
  // sort a key/value object into a string of JSON stringified keys and vals
37
37
  const sortKV = obj => Object.keys(obj)
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@npmcli/arborist",
3
- "version": "4.0.3",
3
+ "version": "4.1.1",
4
4
  "description": "Manage node_modules trees",
5
5
  "dependencies": {
6
- "@isaacs/string-locale-compare": "^1.0.1",
6
+ "@isaacs/string-locale-compare": "^1.1.0",
7
7
  "@npmcli/installed-package-contents": "^1.0.7",
8
8
  "@npmcli/map-workspaces": "^2.0.0",
9
9
  "@npmcli/metavuln-calculator": "^2.0.0",
10
10
  "@npmcli/move-file": "^1.1.0",
11
11
  "@npmcli/name-from-folder": "^1.0.1",
12
- "@npmcli/node-gyp": "^1.0.1",
12
+ "@npmcli/node-gyp": "^1.0.3",
13
13
  "@npmcli/package-json": "^1.0.1",
14
14
  "@npmcli/run-script": "^2.0.0",
15
15
  "bin-links": "^2.3.0",
@@ -23,8 +23,8 @@
23
23
  "npm-package-arg": "^8.1.5",
24
24
  "npm-pick-manifest": "^6.1.0",
25
25
  "npm-registry-fetch": "^11.0.0",
26
- "pacote": "^12.0.0",
27
- "parse-conflict-json": "^1.1.1",
26
+ "pacote": "^12.0.2",
27
+ "parse-conflict-json": "^2.0.1",
28
28
  "proc-log": "^1.0.0",
29
29
  "promise-all-reject-late": "^1.0.0",
30
30
  "promise-call-limit": "^1.0.1",
@@ -37,11 +37,12 @@
37
37
  "walk-up-path": "^1.0.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@npmcli/lint": "^1.0.2",
40
+ "@npmcli/template-oss": "^2.3.1",
41
41
  "benchmark": "^2.1.4",
42
42
  "chalk": "^4.1.0",
43
43
  "minify-registry-metadata": "^2.1.0",
44
- "tap": "^15.0.9",
44
+ "nock": "^13.2.0",
45
+ "tap": "^15.1.2",
45
46
  "tcompare": "^5.0.6"
46
47
  },
47
48
  "scripts": {
@@ -54,21 +55,22 @@
54
55
  "postversion": "npm publish",
55
56
  "prepublishOnly": "git push origin --follow-tags",
56
57
  "eslint": "eslint",
57
- "lint": "npm run npmclilint -- \"lib/**/*.*js\" \"bin/**/*.*js\" \"test/*.*js\" \"test/arborist/*.*js\"",
58
+ "lint": "eslint '**/*.js'",
58
59
  "lintfix": "npm run lint -- --fix",
59
60
  "benchmark": "node scripts/benchmark.js",
60
61
  "benchclean": "rm -rf scripts/benchmark/*/",
61
- "npmclilint": "npmcli-lint"
62
+ "npmclilint": "npmcli-lint",
63
+ "postlint": "npm-template-check"
62
64
  },
63
65
  "repository": {
64
66
  "type": "git",
65
67
  "url": "https://github.com/npm/arborist"
66
68
  },
67
- "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
69
+ "author": "GitHub Inc.",
68
70
  "license": "ISC",
69
71
  "files": [
70
- "lib/**/*.js",
71
- "bin/**/*.js"
72
+ "bin",
73
+ "lib"
72
74
  ],
73
75
  "main": "lib/index.js",
74
76
  "bin": {
@@ -91,5 +93,10 @@
91
93
  },
92
94
  "engines": {
93
95
  "node": "^12.13.0 || ^14.15.0 || >=16"
94
- }
96
+ },
97
+ "templateVersion": "2.3.1",
98
+ "eslintIgnore": [
99
+ "test/fixtures/",
100
+ "!test/fixtures/*.js"
101
+ ]
95
102
  }
package/LICENSE DELETED
@@ -1,22 +0,0 @@
1
- The ISC License
2
-
3
- Copyright npm, Inc.
4
-
5
- Permission to use, copy, modify, and/or distribute this software for any
6
- purpose with or without fee is hereby granted, provided that the above
7
- copyright notice and this permission notice appear in all copies.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL WARRANTIES WITH
10
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
- AND FITNESS. IN NO EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
12
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
- PERFORMANCE OF THIS SOFTWARE.
16
-
17
- ---
18
-
19
- Files and metadata contained in `test/fixtures/registry-mocks/content` are
20
- downloaded from the public npm registry. These are the property of their
21
- respective owners. The use and distribution of said artifacts are covered by
22
- their associated licenses.