@npmcli/arborist 2.3.0 → 2.4.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/bin/lib/logging.js +10 -2
- package/bin/lib/timers.js +6 -2
- package/bin/virtual.js +2 -1
- package/lib/arborist/build-ideal-tree.js +10 -0
- package/lib/arborist/index.js +1 -1
- package/lib/arborist/load-virtual.js +9 -6
- package/lib/arborist/rebuild.js +5 -4
- package/lib/arborist/reify.js +34 -19
- package/lib/debug.js +8 -1
- package/lib/diff.js +19 -9
- package/lib/index.js +1 -0
- package/package.json +4 -7
package/bin/lib/logging.js
CHANGED
|
@@ -20,13 +20,21 @@ const levelMap = new Map(levels.reduce((set, level, index) => {
|
|
|
20
20
|
}, []))
|
|
21
21
|
|
|
22
22
|
const { inspect, format } = require('util')
|
|
23
|
+
const colors = process.stderr.isTTY
|
|
24
|
+
const magenta = colors ? msg => `\x1B[35m${msg}\x1B[39m` : m => m
|
|
23
25
|
if (loglevel !== 'silent') {
|
|
24
26
|
process.on('log', (level, ...args) => {
|
|
25
27
|
if (levelMap.get(level) < levelMap.get(loglevel))
|
|
26
28
|
return
|
|
27
|
-
const pref = `${process.pid} ${level} `
|
|
29
|
+
const pref = `${process.pid} ${magenta(level)} `
|
|
28
30
|
if (level === 'warn' && args[0] === 'ERESOLVE')
|
|
29
|
-
args[2] = inspect(args[2], { depth: 10 })
|
|
31
|
+
args[2] = inspect(args[2], { depth: 10, colors })
|
|
32
|
+
else {
|
|
33
|
+
args = args.map(a => {
|
|
34
|
+
return typeof a === 'string' ? a
|
|
35
|
+
: inspect(a, { depth: 10, colors })
|
|
36
|
+
})
|
|
37
|
+
}
|
|
30
38
|
const msg = pref + format(...args).trim().split('\n').join(`\n${pref}`)
|
|
31
39
|
console.error(msg)
|
|
32
40
|
})
|
package/bin/lib/timers.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const timers = Object.create(null)
|
|
2
|
+
const { format } = require('util')
|
|
2
3
|
|
|
3
4
|
process.on('time', name => {
|
|
4
5
|
if (timers[name])
|
|
@@ -6,17 +7,20 @@ process.on('time', name => {
|
|
|
6
7
|
timers[name] = process.hrtime()
|
|
7
8
|
})
|
|
8
9
|
|
|
10
|
+
const dim = process.stderr.isTTY ? msg => `\x1B[2m${msg}\x1B[22m` : m => m
|
|
11
|
+
const red = process.stderr.isTTY ? msg => `\x1B[31m${msg}\x1B[39m` : m => m
|
|
9
12
|
process.on('timeEnd', name => {
|
|
10
13
|
if (!timers[name])
|
|
11
14
|
throw new Error('timer not started! ' + name)
|
|
12
15
|
const res = process.hrtime(timers[name])
|
|
13
16
|
delete timers[name]
|
|
14
|
-
|
|
17
|
+
const msg = format(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6)
|
|
18
|
+
console.error(dim(msg))
|
|
15
19
|
})
|
|
16
20
|
|
|
17
21
|
process.on('exit', () => {
|
|
18
22
|
for (const name of Object.keys(timers)) {
|
|
19
|
-
console.error('Dangling timer:
|
|
23
|
+
console.error(red('Dangling timer:'), name)
|
|
20
24
|
process.exitCode = 1
|
|
21
25
|
}
|
|
22
26
|
})
|
package/bin/virtual.js
CHANGED
|
@@ -8,7 +8,8 @@ require('./lib/timers.js')
|
|
|
8
8
|
const start = process.hrtime()
|
|
9
9
|
new Arborist(options).loadVirtual().then(tree => {
|
|
10
10
|
const end = process.hrtime(start)
|
|
11
|
-
|
|
11
|
+
if (!options.quiet)
|
|
12
|
+
print(tree)
|
|
12
13
|
if (options.save)
|
|
13
14
|
tree.meta.save()
|
|
14
15
|
console.error(`read ${tree.inventory.size} deps in ${end[0] * 1000 + end[1] / 1e6}ms`)
|
|
@@ -1188,6 +1188,16 @@ This is a one-time fix-up, please be patient...
|
|
|
1188
1188
|
}
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
|
+
// There is something present already, and we're not happy about it
|
|
1192
|
+
// See if the thing we WOULD be happy with is also going to satisfy
|
|
1193
|
+
// the other dependents on the current node.
|
|
1194
|
+
const current = edge.to
|
|
1195
|
+
const dep = await this[_nodeFromEdge](edge, null, null, required)
|
|
1196
|
+
if (dep.canReplace(current)) {
|
|
1197
|
+
await this[_nodeFromEdge](edge, node.parent, null, required)
|
|
1198
|
+
continue
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1191
1201
|
// at this point we know that there is a dep there, and
|
|
1192
1202
|
// we don't like it. always fail strictly, always allow forcibly or
|
|
1193
1203
|
// in non-strict mode if it's not our fault. don't warn here, because
|
package/lib/arborist/index.js
CHANGED
|
@@ -54,7 +54,7 @@ class Arborist extends Base {
|
|
|
54
54
|
...options,
|
|
55
55
|
path: options.path || '.',
|
|
56
56
|
cache: options.cache || `${homedir()}/.npm/_cacache`,
|
|
57
|
-
packumentCache: new Map(),
|
|
57
|
+
packumentCache: options.packumentCache || new Map(),
|
|
58
58
|
log: options.log || procLog,
|
|
59
59
|
}
|
|
60
60
|
this.cache = resolve(this.options.cache)
|
|
@@ -93,7 +93,8 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
93
93
|
this.virtualTree = root
|
|
94
94
|
const {links, nodes} = this[resolveNodes](s, root)
|
|
95
95
|
await this[resolveLinks](links, nodes)
|
|
96
|
-
|
|
96
|
+
if (!(s.originalLockfileVersion >= 2))
|
|
97
|
+
this[assignBundles](nodes)
|
|
97
98
|
if (this[flagsSuspect])
|
|
98
99
|
this[reCalcDepFlags](nodes.values())
|
|
99
100
|
return root
|
|
@@ -220,22 +221,24 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
220
221
|
[assignBundles] (nodes) {
|
|
221
222
|
for (const [location, node] of nodes) {
|
|
222
223
|
// Skip assignment of parentage for the root package
|
|
223
|
-
if (!location)
|
|
224
|
+
if (!location || node.target && !node.target.location)
|
|
224
225
|
continue
|
|
225
226
|
const { name, parent, package: { inBundle }} = node
|
|
227
|
+
|
|
226
228
|
if (!parent)
|
|
227
229
|
continue
|
|
228
230
|
|
|
229
231
|
// read inBundle from package because 'package' here is
|
|
230
232
|
// actually a v2 lockfile metadata entry.
|
|
231
|
-
// If the *parent* is also bundled, though,
|
|
232
|
-
// that it's being pulled in
|
|
233
|
+
// If the *parent* is also bundled, though, or if the parent has
|
|
234
|
+
// no dependency on it, then we assume that it's being pulled in
|
|
235
|
+
// just by virtue of its parent or a transitive dep being bundled.
|
|
233
236
|
const { package: ppkg } = parent
|
|
234
237
|
const { inBundle: parentBundled } = ppkg
|
|
235
|
-
if (inBundle && !parentBundled) {
|
|
238
|
+
if (inBundle && !parentBundled && parent.edgesOut.has(node.name)) {
|
|
236
239
|
if (!ppkg.bundleDependencies)
|
|
237
240
|
ppkg.bundleDependencies = [name]
|
|
238
|
-
else
|
|
241
|
+
else
|
|
239
242
|
ppkg.bundleDependencies.push(name)
|
|
240
243
|
}
|
|
241
244
|
}
|
package/lib/arborist/rebuild.js
CHANGED
|
@@ -115,10 +115,6 @@ module.exports = cls => class Builder extends cls {
|
|
|
115
115
|
await this[_runScripts]('preinstall')
|
|
116
116
|
if (this[_binLinks] && type !== 'links')
|
|
117
117
|
await this[_linkAllBins]()
|
|
118
|
-
if (!this[_ignoreScripts]) {
|
|
119
|
-
await this[_runScripts]('install')
|
|
120
|
-
await this[_runScripts]('postinstall')
|
|
121
|
-
}
|
|
122
118
|
|
|
123
119
|
// links should also run prepare scripts and only link bins after that
|
|
124
120
|
if (type === 'links') {
|
|
@@ -128,6 +124,11 @@ module.exports = cls => class Builder extends cls {
|
|
|
128
124
|
await this[_linkAllBins]()
|
|
129
125
|
}
|
|
130
126
|
|
|
127
|
+
if (!this[_ignoreScripts]) {
|
|
128
|
+
await this[_runScripts]('install')
|
|
129
|
+
await this[_runScripts]('postinstall')
|
|
130
|
+
}
|
|
131
|
+
|
|
131
132
|
process.emit('timeEnd', `build:${type}`)
|
|
132
133
|
}
|
|
133
134
|
|
package/lib/arborist/reify.js
CHANGED
|
@@ -49,7 +49,8 @@ const _loadTrees = Symbol.for('loadTrees')
|
|
|
49
49
|
const _diffTrees = Symbol.for('diffTrees')
|
|
50
50
|
const _createSparseTree = Symbol.for('createSparseTree')
|
|
51
51
|
const _loadShrinkwrapsAndUpdateTrees = Symbol.for('loadShrinkwrapsAndUpdateTrees')
|
|
52
|
-
const
|
|
52
|
+
const _shrinkwrapInflated = Symbol('shrinkwrapInflated')
|
|
53
|
+
const _bundleUnpacked = Symbol('bundleUnpacked')
|
|
53
54
|
const _reifyNode = Symbol.for('reifyNode')
|
|
54
55
|
const _extractOrLink = Symbol('extractOrLink')
|
|
55
56
|
// defined by rebuild mixin
|
|
@@ -108,7 +109,7 @@ module.exports = cls => class Reifier extends cls {
|
|
|
108
109
|
|
|
109
110
|
this.diff = null
|
|
110
111
|
this[_retiredPaths] = {}
|
|
111
|
-
this[
|
|
112
|
+
this[_shrinkwrapInflated] = new Set()
|
|
112
113
|
this[_retiredUnchanged] = {}
|
|
113
114
|
this[_sparseTreeDirs] = new Set()
|
|
114
115
|
this[_sparseTreeRoots] = new Set()
|
|
@@ -316,6 +317,7 @@ module.exports = cls => class Reifier extends cls {
|
|
|
316
317
|
// find all the nodes that need to change between the actual
|
|
317
318
|
// and ideal trees.
|
|
318
319
|
this.diff = Diff.calculate({
|
|
320
|
+
shrinkwrapInflated: this[_shrinkwrapInflated],
|
|
319
321
|
filterNodes,
|
|
320
322
|
actual: this.actualTree,
|
|
321
323
|
ideal: this.idealTree,
|
|
@@ -423,7 +425,8 @@ module.exports = cls => class Reifier extends cls {
|
|
|
423
425
|
const dirs = this.diff.leaves
|
|
424
426
|
.filter(diff => {
|
|
425
427
|
return (diff.action === 'ADD' || diff.action === 'CHANGE') &&
|
|
426
|
-
!this[_sparseTreeDirs].has(diff.ideal.path)
|
|
428
|
+
!this[_sparseTreeDirs].has(diff.ideal.path) &&
|
|
429
|
+
!diff.ideal.isLink
|
|
427
430
|
})
|
|
428
431
|
.map(diff => diff.ideal.path)
|
|
429
432
|
|
|
@@ -457,9 +460,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
457
460
|
// we need to unpack them, read that shrinkwrap file, and then update
|
|
458
461
|
// the tree by calling loadVirtual with the node as the root.
|
|
459
462
|
[_loadShrinkwrapsAndUpdateTrees] () {
|
|
460
|
-
const seen = this[
|
|
463
|
+
const seen = this[_shrinkwrapInflated]
|
|
461
464
|
const shrinkwraps = this.diff.leaves
|
|
462
|
-
.filter(d => (d.action === 'CHANGE' || d.action === 'ADD') &&
|
|
465
|
+
.filter(d => (d.action === 'CHANGE' || d.action === 'ADD' || !d.action) &&
|
|
463
466
|
d.ideal.hasShrinkwrap && !seen.has(d.ideal) &&
|
|
464
467
|
!this[_trashList].has(d.ideal.path))
|
|
465
468
|
|
|
@@ -472,7 +475,7 @@ module.exports = cls => class Reifier extends cls {
|
|
|
472
475
|
return promiseAllRejectLate(shrinkwraps.map(diff => {
|
|
473
476
|
const node = diff.ideal
|
|
474
477
|
seen.add(node)
|
|
475
|
-
return this[_reifyNode](node)
|
|
478
|
+
return diff.action ? this[_reifyNode](node) : node
|
|
476
479
|
}))
|
|
477
480
|
.then(nodes => promiseAllRejectLate(nodes.map(node => new Arborist({
|
|
478
481
|
...this.options,
|
|
@@ -503,7 +506,7 @@ module.exports = cls => class Reifier extends cls {
|
|
|
503
506
|
|
|
504
507
|
const { npmVersion, nodeVersion } = this.options
|
|
505
508
|
const p = Promise.resolve()
|
|
506
|
-
.then(() => {
|
|
509
|
+
.then(async () => {
|
|
507
510
|
// when we reify an optional node, check the engine and platform
|
|
508
511
|
// first. be sure to ignore the --force and --engine-strict flags,
|
|
509
512
|
// since we always want to skip any optional packages we can't install.
|
|
@@ -513,11 +516,11 @@ module.exports = cls => class Reifier extends cls {
|
|
|
513
516
|
checkEngine(node.package, npmVersion, nodeVersion, false)
|
|
514
517
|
checkPlatform(node.package, false)
|
|
515
518
|
}
|
|
519
|
+
await this[_checkBins](node)
|
|
520
|
+
await this[_extractOrLink](node)
|
|
521
|
+
await this[_warnDeprecated](node)
|
|
522
|
+
await this[_loadAncientPackageDetails](node)
|
|
516
523
|
})
|
|
517
|
-
.then(() => this[_checkBins](node))
|
|
518
|
-
.then(() => this[_extractOrLink](node))
|
|
519
|
-
.then(() => this[_warnDeprecated](node))
|
|
520
|
-
.then(() => this[_loadAncientPackageDetails](node))
|
|
521
524
|
|
|
522
525
|
return this[_handleOptionalFailure](node, p)
|
|
523
526
|
.then(() => {
|
|
@@ -563,10 +566,11 @@ module.exports = cls => class Reifier extends cls {
|
|
|
563
566
|
})
|
|
564
567
|
}
|
|
565
568
|
|
|
566
|
-
[_symlink] (node) {
|
|
569
|
+
async [_symlink] (node) {
|
|
567
570
|
const dir = dirname(node.path)
|
|
568
571
|
const target = node.realpath
|
|
569
572
|
const rel = relative(dir, target)
|
|
573
|
+
await mkdirp(dir)
|
|
570
574
|
return symlink(rel, node.path, 'junction')
|
|
571
575
|
}
|
|
572
576
|
|
|
@@ -633,8 +637,10 @@ module.exports = cls => class Reifier extends cls {
|
|
|
633
637
|
[_loadBundlesAndUpdateTrees] (
|
|
634
638
|
depth = 0, bundlesByDepth = this[_getBundlesByDepth]()
|
|
635
639
|
) {
|
|
636
|
-
if (depth === 0)
|
|
640
|
+
if (depth === 0) {
|
|
641
|
+
this[_bundleUnpacked] = new Set()
|
|
637
642
|
process.emit('time', 'reify:loadBundles')
|
|
643
|
+
}
|
|
638
644
|
const maxBundleDepth = bundlesByDepth.get('maxBundleDepth')
|
|
639
645
|
if (depth > maxBundleDepth) {
|
|
640
646
|
// if we did something, then prune the tree and update the diffs
|
|
@@ -650,13 +656,17 @@ module.exports = cls => class Reifier extends cls {
|
|
|
650
656
|
// shallower bundle overwriting them with a bundled meta-dep.
|
|
651
657
|
const set = (bundlesByDepth.get(depth) || [])
|
|
652
658
|
.filter(node => node.root === this.idealTree &&
|
|
659
|
+
node.target !== node.root &&
|
|
653
660
|
!this[_trashList].has(node.path))
|
|
654
661
|
|
|
655
662
|
if (!set.length)
|
|
656
663
|
return this[_loadBundlesAndUpdateTrees](depth + 1, bundlesByDepth)
|
|
657
664
|
|
|
658
665
|
// extract all the nodes with bundles
|
|
659
|
-
return promiseAllRejectLate(set.map(node =>
|
|
666
|
+
return promiseAllRejectLate(set.map(node => {
|
|
667
|
+
this[_bundleUnpacked].add(node)
|
|
668
|
+
return this[_reifyNode](node)
|
|
669
|
+
}))
|
|
660
670
|
// then load their unpacked children and move into the ideal tree
|
|
661
671
|
.then(nodes =>
|
|
662
672
|
promiseAllRejectLate(nodes.map(node => new this.constructor({
|
|
@@ -678,8 +688,13 @@ module.exports = cls => class Reifier extends cls {
|
|
|
678
688
|
tree: this.diff,
|
|
679
689
|
visit: diff => {
|
|
680
690
|
const node = diff.ideal
|
|
681
|
-
if (
|
|
682
|
-
|
|
691
|
+
if (!node)
|
|
692
|
+
return
|
|
693
|
+
if (node.isProjectRoot || (node.target && node.target.isProjectRoot))
|
|
694
|
+
return
|
|
695
|
+
|
|
696
|
+
const { bundleDependencies } = node.package
|
|
697
|
+
if (bundleDependencies && bundleDependencies.length) {
|
|
683
698
|
maxBundleDepth = Math.max(maxBundleDepth, node.depth)
|
|
684
699
|
if (!bundlesByDepth.has(node.depth))
|
|
685
700
|
bundlesByDepth.set(node.depth, [node])
|
|
@@ -784,14 +799,14 @@ module.exports = cls => class Reifier extends cls {
|
|
|
784
799
|
return
|
|
785
800
|
|
|
786
801
|
const node = diff.ideal
|
|
787
|
-
const bd = node
|
|
788
|
-
const sw = this[
|
|
802
|
+
const bd = this[_bundleUnpacked].has(node)
|
|
803
|
+
const sw = this[_shrinkwrapInflated].has(node)
|
|
789
804
|
|
|
790
805
|
// check whether we still need to unpack this one.
|
|
791
806
|
// test the inDepBundle last, since that's potentially a tree walk.
|
|
792
807
|
const doUnpack = node && // can't unpack if removed!
|
|
793
808
|
!node.isRoot && // root node already exists
|
|
794
|
-
!
|
|
809
|
+
!bd && // already unpacked to read bundle
|
|
795
810
|
!sw && // already unpacked to read sw
|
|
796
811
|
!node.inDepBundle // already unpacked by another dep's bundle
|
|
797
812
|
|
package/lib/debug.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
// run in debug mode if explicitly requested, running arborist tests,
|
|
14
14
|
// or working in the arborist project directory.
|
|
15
|
+
|
|
15
16
|
const debug = process.env.ARBORIST_DEBUG !== '0' && (
|
|
16
17
|
process.env.ARBORIST_DEBUG === '1' ||
|
|
17
18
|
/\barborist\b/.test(process.env.NODE_DEBUG || '') ||
|
|
@@ -21,4 +22,10 @@ const debug = process.env.ARBORIST_DEBUG !== '0' && (
|
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
module.exports = debug ? fn => fn() : () => {}
|
|
24
|
-
|
|
25
|
+
const red = process.stderr.isTTY ? msg => `\x1B[31m${msg}\x1B[39m` : m => m
|
|
26
|
+
module.exports.log = (...msg) => module.exports(() => {
|
|
27
|
+
const { format } = require('util')
|
|
28
|
+
const prefix = `\n${process.pid} ${red(format(msg.shift()))} `
|
|
29
|
+
msg = (prefix + format(...msg).trim().split('\n').join(prefix)).trim()
|
|
30
|
+
console.error(msg)
|
|
31
|
+
})
|
package/lib/diff.js
CHANGED
|
@@ -11,8 +11,9 @@ const {existsSync} = require('fs')
|
|
|
11
11
|
const ssri = require('ssri')
|
|
12
12
|
|
|
13
13
|
class Diff {
|
|
14
|
-
constructor ({actual, ideal, filterSet}) {
|
|
14
|
+
constructor ({actual, ideal, filterSet, shrinkwrapInflated}) {
|
|
15
15
|
this.filterSet = filterSet
|
|
16
|
+
this.shrinkwrapInflated = shrinkwrapInflated
|
|
16
17
|
this.children = []
|
|
17
18
|
this.actual = actual
|
|
18
19
|
this.ideal = ideal
|
|
@@ -30,7 +31,7 @@ class Diff {
|
|
|
30
31
|
this.removed = []
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
static calculate ({actual, ideal, filterNodes = []}) {
|
|
34
|
+
static calculate ({actual, ideal, filterNodes = [], shrinkwrapInflated = new Set()}) {
|
|
34
35
|
// if there's a filterNode, then:
|
|
35
36
|
// - get the path from the root to the filterNode. The root or
|
|
36
37
|
// root.target should have an edge either to the filterNode or
|
|
@@ -77,7 +78,7 @@ class Diff {
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
return depth({
|
|
80
|
-
tree: new Diff({actual, ideal, filterSet}),
|
|
81
|
+
tree: new Diff({actual, ideal, filterSet, shrinkwrapInflated}),
|
|
81
82
|
getChildren,
|
|
82
83
|
leave,
|
|
83
84
|
})
|
|
@@ -135,7 +136,7 @@ const allChildren = node => {
|
|
|
135
136
|
// to create the diff tree
|
|
136
137
|
const getChildren = diff => {
|
|
137
138
|
const children = []
|
|
138
|
-
const {actual, ideal, unchanged, removed, filterSet} = diff
|
|
139
|
+
const {actual, ideal, unchanged, removed, filterSet, shrinkwrapInflated} = diff
|
|
139
140
|
|
|
140
141
|
// Note: we DON'T diff fsChildren themselves, because they are either
|
|
141
142
|
// included in the package contents, or part of some other project, and
|
|
@@ -144,11 +145,20 @@ const getChildren = diff => {
|
|
|
144
145
|
// responsible for installing.
|
|
145
146
|
const actualKids = allChildren(actual)
|
|
146
147
|
const idealKids = allChildren(ideal)
|
|
148
|
+
|
|
149
|
+
if (ideal && ideal.hasShrinkwrap && !shrinkwrapInflated.has(ideal)) {
|
|
150
|
+
// Guaranteed to get a diff.leaves here, because we always
|
|
151
|
+
// be called with a proper Diff object when ideal has a shrinkwrap
|
|
152
|
+
// that has not been inflated.
|
|
153
|
+
diff.leaves.push(diff)
|
|
154
|
+
return children
|
|
155
|
+
}
|
|
156
|
+
|
|
147
157
|
const paths = new Set([...actualKids.keys(), ...idealKids.keys()])
|
|
148
158
|
for (const path of paths) {
|
|
149
159
|
const actual = actualKids.get(path)
|
|
150
160
|
const ideal = idealKids.get(path)
|
|
151
|
-
diffNode(actual, ideal, children, unchanged, removed, filterSet)
|
|
161
|
+
diffNode(actual, ideal, children, unchanged, removed, filterSet, shrinkwrapInflated)
|
|
152
162
|
}
|
|
153
163
|
|
|
154
164
|
if (diff.leaves && !children.length)
|
|
@@ -157,7 +167,7 @@ const getChildren = diff => {
|
|
|
157
167
|
return children
|
|
158
168
|
}
|
|
159
169
|
|
|
160
|
-
const diffNode = (actual, ideal, children, unchanged, removed, filterSet) => {
|
|
170
|
+
const diffNode = (actual, ideal, children, unchanged, removed, filterSet, shrinkwrapInflated) => {
|
|
161
171
|
if (filterSet.size && !(filterSet.has(ideal) || filterSet.has(actual)))
|
|
162
172
|
return
|
|
163
173
|
|
|
@@ -165,10 +175,10 @@ const diffNode = (actual, ideal, children, unchanged, removed, filterSet) => {
|
|
|
165
175
|
|
|
166
176
|
// if it's a match, then get its children
|
|
167
177
|
// otherwise, this is the child diff node
|
|
168
|
-
if (action) {
|
|
178
|
+
if (action || (!shrinkwrapInflated.has(ideal) && ideal.hasShrinkwrap)) {
|
|
169
179
|
if (action === 'REMOVE')
|
|
170
180
|
removed.push(actual)
|
|
171
|
-
children.push(new Diff({actual, ideal, filterSet}))
|
|
181
|
+
children.push(new Diff({actual, ideal, filterSet, shrinkwrapInflated}))
|
|
172
182
|
} else {
|
|
173
183
|
unchanged.push(ideal)
|
|
174
184
|
// !*! Weird dirty hack warning !*!
|
|
@@ -199,7 +209,7 @@ const diffNode = (actual, ideal, children, unchanged, removed, filterSet) => {
|
|
|
199
209
|
for (const node of bundledChildren)
|
|
200
210
|
node.parent = ideal
|
|
201
211
|
}
|
|
202
|
-
children.push(...getChildren({actual, ideal, unchanged, removed, filterSet}))
|
|
212
|
+
children.push(...getChildren({actual, ideal, unchanged, removed, filterSet, shrinkwrapInflated}))
|
|
203
213
|
}
|
|
204
214
|
}
|
|
205
215
|
|
package/lib/index.js
CHANGED
|
@@ -3,5 +3,6 @@ module.exports.Arborist = module.exports
|
|
|
3
3
|
module.exports.Node = require('./node.js')
|
|
4
4
|
module.exports.Link = require('./link.js')
|
|
5
5
|
module.exports.Edge = require('./edge.js')
|
|
6
|
+
module.exports.Shrinkwrap = require('./shrinkwrap.js')
|
|
6
7
|
// XXX export the other classes, too. shrinkwrap, diff, etc.
|
|
7
8
|
// they're handy!
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npmcli/arborist",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Manage node_modules trees",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@npmcli/installed-package-contents": "^1.0.7",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"npm-install-checks": "^4.0.0",
|
|
20
20
|
"npm-package-arg": "^8.1.0",
|
|
21
21
|
"npm-pick-manifest": "^6.1.0",
|
|
22
|
-
"npm-registry-fetch": "^
|
|
22
|
+
"npm-registry-fetch": "^10.0.0",
|
|
23
23
|
"pacote": "^11.2.6",
|
|
24
24
|
"parse-conflict-json": "^1.1.1",
|
|
25
25
|
"promise-all-reject-late": "^1.0.0",
|
|
@@ -41,8 +41,7 @@
|
|
|
41
41
|
"eslint-plugin-standard": "^4.0.1",
|
|
42
42
|
"minify-registry-metadata": "^2.1.0",
|
|
43
43
|
"mutate-fs": "^2.1.1",
|
|
44
|
-
"
|
|
45
|
-
"tap": "^14.11.0",
|
|
44
|
+
"tap": "^15.0.4",
|
|
46
45
|
"tcompare": "^3.0.4"
|
|
47
46
|
},
|
|
48
47
|
"scripts": {
|
|
@@ -76,10 +75,8 @@
|
|
|
76
75
|
"arborist": "bin/index.js"
|
|
77
76
|
},
|
|
78
77
|
"tap": {
|
|
79
|
-
"100": true,
|
|
80
78
|
"after": "test/fixtures/cleanup.js",
|
|
81
79
|
"coverage-map": "map.js",
|
|
82
|
-
"esm": false,
|
|
83
80
|
"test-env": [
|
|
84
81
|
"NODE_OPTIONS=--no-warnings"
|
|
85
82
|
],
|
|
@@ -87,6 +84,6 @@
|
|
|
87
84
|
"--no-warnings",
|
|
88
85
|
"--no-deprecation"
|
|
89
86
|
],
|
|
90
|
-
"timeout": "
|
|
87
|
+
"timeout": "240"
|
|
91
88
|
}
|
|
92
89
|
}
|