@npmcli/arborist 4.0.0 → 4.0.4

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.
@@ -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 {
@@ -145,7 +145,12 @@ class CanPlaceDep {
145
145
  return CONFLICT
146
146
  }
147
147
 
148
- if (targetEdge && !dep.satisfies(targetEdge) && targetEdge !== this.edge) {
148
+ // skip this test if there's a current node, because we might be able
149
+ // to dedupe against it anyway
150
+ if (!current &&
151
+ targetEdge &&
152
+ !dep.satisfies(targetEdge) &&
153
+ targetEdge !== this.edge) {
149
154
  return CONFLICT
150
155
  }
151
156
 
@@ -167,10 +172,10 @@ class CanPlaceDep {
167
172
  const { version: newVer } = dep
168
173
  const tryReplace = curVer && newVer && semver.gte(newVer, curVer)
169
174
  if (tryReplace && dep.canReplace(current)) {
170
- /* XXX-istanbul ignore else - It's extremely rare that a replaceable
171
- * node would be a conflict, if the current one wasn't a conflict,
172
- * but it is theoretically possible if peer deps are pinned. In
173
- * that case we treat it like any other conflict, and keep trying */
175
+ // It's extremely rare that a replaceable node would be a conflict, if
176
+ // the current one wasn't a conflict, but it is theoretically possible
177
+ // if peer deps are pinned. In that case we treat it like any other
178
+ // conflict, and keep trying.
174
179
  const cpp = this.canPlacePeers(REPLACE)
175
180
  if (cpp !== CONFLICT) {
176
181
  return cpp
package/lib/place-dep.js CHANGED
@@ -407,11 +407,12 @@ class PlaceDep {
407
407
  for (const entryEdge of peerEntrySets(edge.from).keys()) {
408
408
  // either this one needs to be pruned and re-evaluated, or marked
409
409
  // 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.
410
+ // the root or a workspace, then we have to leave it alone, and in that
411
+ // case, it will have already warned or crashed by getting to this point
412
412
  const entryNode = entryEdge.to
413
413
  const deepestTarget = deepestNestingTarget(entryNode)
414
- if (deepestTarget !== target && !entryEdge.from.isRoot) {
414
+ if (deepestTarget !== target &&
415
+ !(entryEdge.from.isProjectRoot || entryEdge.from.isWorkspace)) {
415
416
  prunePeerSets.push(...gatherDepSet([entryNode], e => {
416
417
  return e.to !== entryNode && !e.peerConflicted
417
418
  }))
package/lib/shrinkwrap.js CHANGED
@@ -238,21 +238,31 @@ class Shrinkwrap {
238
238
  return swKeyOrder
239
239
  }
240
240
 
241
- static reset (options) {
241
+ static async reset (options) {
242
242
  // still need to know if it was loaded from the disk, but don't
243
243
  // bother reading it if we're gonna just throw it away.
244
244
  const s = new Shrinkwrap(options)
245
245
  s.reset()
246
246
 
247
- return s[_maybeStat]().then(([sw, lock]) => {
248
- s.filename = resolve(s.path,
249
- (s.hiddenLockfile ? 'node_modules/.package-lock'
250
- : s.shrinkwrapOnly || sw ? 'npm-shrinkwrap'
251
- : 'package-lock') + '.json')
252
- s.loadedFromDisk = !!(sw || lock)
253
- s.type = basename(s.filename)
254
- return s
255
- })
247
+ const [sw, lock] = await s[_maybeStat]()
248
+
249
+ s.filename = resolve(s.path,
250
+ (s.hiddenLockfile ? 'node_modules/.package-lock'
251
+ : s.shrinkwrapOnly || sw ? 'npm-shrinkwrap'
252
+ : 'package-lock') + '.json')
253
+ s.loadedFromDisk = !!(sw || lock)
254
+ s.type = basename(s.filename)
255
+
256
+ try {
257
+ if (s.loadedFromDisk && !s.lockfileVersion) {
258
+ const json = parseJSON(await maybeReadFile(s.filename))
259
+ if (json.lockfileVersion > defaultLockfileVersion) {
260
+ s.lockfileVersion = json.lockfileVersion
261
+ }
262
+ }
263
+ } catch (e) {}
264
+
265
+ return s
256
266
  }
257
267
 
258
268
  static metaFromNode (node, path) {
@@ -380,9 +390,10 @@ class Shrinkwrap {
380
390
  reset () {
381
391
  this.tree = null
382
392
  this[_awaitingUpdate] = new Map()
383
- this.originalLockfileVersion = this.lockfileVersion
393
+ const lockfileVersion = this.lockfileVersion || defaultLockfileVersion
394
+ this.originalLockfileVersion = lockfileVersion
384
395
  this.data = {
385
- lockfileVersion: this.lockfileVersion || defaultLockfileVersion,
396
+ lockfileVersion,
386
397
  requires: true,
387
398
  packages: {},
388
399
  dependencies: {},
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@npmcli/arborist",
3
- "version": "4.0.0",
3
+ "version": "4.0.4",
4
4
  "description": "Manage node_modules trees",
5
5
  "dependencies": {
6
6
  "@isaacs/string-locale-compare": "^1.0.1",
7
7
  "@npmcli/installed-package-contents": "^1.0.7",
8
- "@npmcli/map-workspaces": "^1.0.2",
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
12
  "@npmcli/node-gyp": "^1.0.1",
13
13
  "@npmcli/package-json": "^1.0.1",
14
14
  "@npmcli/run-script": "^2.0.0",
15
- "bin-links": "^2.2.1",
15
+ "bin-links": "^2.3.0",
16
16
  "cacache": "^15.0.3",
17
17
  "common-ancestor-path": "^1.0.1",
18
18
  "json-parse-even-better-errors": "^2.3.1",
@@ -45,11 +45,10 @@
45
45
  "tcompare": "^5.0.6"
46
46
  },
47
47
  "scripts": {
48
- "test": "npm run test-only --",
49
- "test-only": "tap",
50
- "posttest": "npm run lint --",
48
+ "test": "tap",
49
+ "posttest": "npm run lint",
51
50
  "snap": "tap",
52
- "postsnap": "npm run lintfix --",
51
+ "postsnap": "npm run lintfix",
53
52
  "test-proxy": "ARBORIST_TEST_PROXY=1 tap --snapshot",
54
53
  "preversion": "npm test",
55
54
  "postversion": "npm publish",
@@ -88,7 +87,7 @@
88
87
  "--no-warnings",
89
88
  "--no-deprecation"
90
89
  ],
91
- "timeout": "240"
90
+ "timeout": "360"
92
91
  },
93
92
  "engines": {
94
93
  "node": "^12.13.0 || ^14.15.0 || >=16"
package/bin/dedupe.js DELETED
@@ -1,49 +0,0 @@
1
- const Arborist = require('../')
2
-
3
- const options = require('./lib/options.js')
4
- const print = require('./lib/print-tree.js')
5
- require('./lib/logging.js')
6
- require('./lib/timers.js')
7
-
8
- const printDiff = diff => {
9
- const {depth} = require('treeverse')
10
- depth({
11
- tree: diff,
12
- visit: d => {
13
- if (d.location === '') {
14
- return
15
- }
16
- switch (d.action) {
17
- case 'REMOVE':
18
- console.error('REMOVE', d.actual.location)
19
- break
20
- case 'ADD':
21
- console.error('ADD', d.ideal.location, d.ideal.resolved)
22
- break
23
- case 'CHANGE':
24
- console.error('CHANGE', d.actual.location, {
25
- from: d.actual.resolved,
26
- to: d.ideal.resolved,
27
- })
28
- break
29
- }
30
- },
31
- getChildren: d => d.children,
32
- })
33
- }
34
-
35
- const start = process.hrtime()
36
- process.emit('time', 'install')
37
- const arb = new Arborist(options)
38
- arb.dedupe(options).then(tree => {
39
- process.emit('timeEnd', 'install')
40
- const end = process.hrtime(start)
41
- print(tree)
42
- if (options.dryRun) {
43
- printDiff(arb.diff)
44
- }
45
- console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 1e9}s`)
46
- if (tree.meta && options.save) {
47
- tree.meta.save()
48
- }
49
- }).catch(er => console.error(require('util').inspect(er, { depth: Infinity })))