@npmcli/arborist 5.1.0 → 5.2.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/README.md +1 -1
- package/lib/arborist/build-ideal-tree.js +2 -0
- package/lib/arborist/load-actual.js +2 -0
- package/lib/arborist/load-virtual.js +1 -0
- package/lib/arborist/rebuild.js +75 -42
- package/lib/arborist/reify.js +2 -1
- package/lib/edge.js +6 -1
- package/lib/node.js +12 -0
- package/lib/override-resolves.js +11 -0
- package/lib/shrinkwrap.js +24 -7
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Inspect and manage `node_modules` trees.
|
|
|
9
9
|

|
|
10
10
|
|
|
11
11
|
There's more documentation [in the docs
|
|
12
|
-
folder](https://github.com/npm/
|
|
12
|
+
folder](https://github.com/npm/cli/tree/latest/workspaces/arborist/docs).
|
|
13
13
|
|
|
14
14
|
## USAGE
|
|
15
15
|
|
|
@@ -329,6 +329,7 @@ Try using the package name instead, e.g:
|
|
|
329
329
|
? Shrinkwrap.reset({
|
|
330
330
|
path: this.path,
|
|
331
331
|
lockfileVersion: this.options.lockfileVersion,
|
|
332
|
+
resolveOptions: this.options,
|
|
332
333
|
}).then(meta => Object.assign(root, { meta }))
|
|
333
334
|
: this.loadVirtual({ root }))
|
|
334
335
|
|
|
@@ -388,6 +389,7 @@ Try using the package name instead, e.g:
|
|
|
388
389
|
const meta = new Shrinkwrap({
|
|
389
390
|
path: this.path,
|
|
390
391
|
lockfileVersion: this.options.lockfileVersion,
|
|
392
|
+
resolveOptions: this.options,
|
|
391
393
|
})
|
|
392
394
|
meta.reset()
|
|
393
395
|
root.meta = meta
|
|
@@ -147,6 +147,7 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
147
147
|
const meta = await Shrinkwrap.load({
|
|
148
148
|
path: this[_actualTree].path,
|
|
149
149
|
hiddenLockfile: true,
|
|
150
|
+
resolveOptions: this.options,
|
|
150
151
|
})
|
|
151
152
|
if (meta.loadedFromDisk) {
|
|
152
153
|
this[_actualTree].meta = meta
|
|
@@ -155,6 +156,7 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
155
156
|
const meta = await Shrinkwrap.load({
|
|
156
157
|
path: this[_actualTree].path,
|
|
157
158
|
lockfileVersion: this.options.lockfileVersion,
|
|
159
|
+
resolveOptions: this.options,
|
|
158
160
|
})
|
|
159
161
|
this[_actualTree].meta = meta
|
|
160
162
|
return this[_loadActualActually]({ root, ignoreMissing })
|
|
@@ -57,6 +57,7 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
57
57
|
const s = await Shrinkwrap.load({
|
|
58
58
|
path: this.path,
|
|
59
59
|
lockfileVersion: this.options.lockfileVersion,
|
|
60
|
+
resolveOptions: this.options,
|
|
60
61
|
})
|
|
61
62
|
if (!s.loadedFromDisk && !options.root) {
|
|
62
63
|
const er = new Error('loadVirtual requires existing shrinkwrap file')
|
package/lib/arborist/rebuild.js
CHANGED
|
@@ -21,6 +21,8 @@ const sortNodes = (a, b) =>
|
|
|
21
21
|
|
|
22
22
|
const _workspaces = Symbol.for('workspaces')
|
|
23
23
|
const _build = Symbol('build')
|
|
24
|
+
const _loadDefaultNodes = Symbol('loadDefaultNodes')
|
|
25
|
+
const _retrieveNodesByType = Symbol('retrieveNodesByType')
|
|
24
26
|
const _resetQueues = Symbol('resetQueues')
|
|
25
27
|
const _rebuildBundle = Symbol('rebuildBundle')
|
|
26
28
|
const _ignoreScripts = Symbol('ignoreScripts')
|
|
@@ -39,6 +41,7 @@ const _includeWorkspaceRoot = Symbol.for('includeWorkspaceRoot')
|
|
|
39
41
|
const _workspacesEnabled = Symbol.for('workspacesEnabled')
|
|
40
42
|
|
|
41
43
|
const _force = Symbol.for('force')
|
|
44
|
+
const _global = Symbol.for('global')
|
|
42
45
|
|
|
43
46
|
// defined by reify mixin
|
|
44
47
|
const _handleOptionalFailure = Symbol.for('handleOptionalFailure')
|
|
@@ -75,36 +78,60 @@ module.exports = cls => class Builder extends cls {
|
|
|
75
78
|
// running JUST a rebuild, we treat optional failures as real fails
|
|
76
79
|
this[_doHandleOptionalFailure] = handleOptionalFailure
|
|
77
80
|
|
|
78
|
-
// if we don't have a set of nodes, then just rebuild
|
|
79
|
-
// the actual tree on disk.
|
|
80
81
|
if (!nodes) {
|
|
81
|
-
|
|
82
|
-
let filterSet
|
|
83
|
-
if (!this[_workspacesEnabled]) {
|
|
84
|
-
filterSet = this.excludeWorkspacesDependencySet(tree)
|
|
85
|
-
nodes = tree.inventory.filter(node =>
|
|
86
|
-
filterSet.has(node) || node.isProjectRoot
|
|
87
|
-
)
|
|
88
|
-
} else if (this[_workspaces] && this[_workspaces].length) {
|
|
89
|
-
filterSet = this.workspaceDependencySet(
|
|
90
|
-
tree,
|
|
91
|
-
this[_workspaces],
|
|
92
|
-
this[_includeWorkspaceRoot]
|
|
93
|
-
)
|
|
94
|
-
nodes = tree.inventory.filter(node => filterSet.has(node))
|
|
95
|
-
} else {
|
|
96
|
-
nodes = tree.inventory.values()
|
|
97
|
-
}
|
|
82
|
+
nodes = await this[_loadDefaultNodes]()
|
|
98
83
|
}
|
|
99
84
|
|
|
100
85
|
// separates links nodes so that it can run
|
|
101
86
|
// prepare scripts and link bins in the expected order
|
|
102
87
|
process.emit('time', 'build')
|
|
88
|
+
|
|
89
|
+
const {
|
|
90
|
+
depNodes,
|
|
91
|
+
linkNodes,
|
|
92
|
+
} = this[_retrieveNodesByType](nodes)
|
|
93
|
+
|
|
94
|
+
// build regular deps
|
|
95
|
+
await this[_build](depNodes, {})
|
|
96
|
+
|
|
97
|
+
// build link deps
|
|
98
|
+
if (linkNodes.size) {
|
|
99
|
+
this[_resetQueues]()
|
|
100
|
+
await this[_build](linkNodes, { type: 'links' })
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
process.emit('timeEnd', 'build')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// if we don't have a set of nodes, then just rebuild
|
|
107
|
+
// the actual tree on disk.
|
|
108
|
+
async [_loadDefaultNodes] () {
|
|
109
|
+
let nodes
|
|
110
|
+
const tree = await this.loadActual()
|
|
111
|
+
let filterSet
|
|
112
|
+
if (!this[_workspacesEnabled]) {
|
|
113
|
+
filterSet = this.excludeWorkspacesDependencySet(tree)
|
|
114
|
+
nodes = tree.inventory.filter(node =>
|
|
115
|
+
filterSet.has(node) || node.isProjectRoot
|
|
116
|
+
)
|
|
117
|
+
} else if (this[_workspaces] && this[_workspaces].length) {
|
|
118
|
+
filterSet = this.workspaceDependencySet(
|
|
119
|
+
tree,
|
|
120
|
+
this[_workspaces],
|
|
121
|
+
this[_includeWorkspaceRoot]
|
|
122
|
+
)
|
|
123
|
+
nodes = tree.inventory.filter(node => filterSet.has(node))
|
|
124
|
+
} else {
|
|
125
|
+
nodes = tree.inventory.values()
|
|
126
|
+
}
|
|
127
|
+
return nodes
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
[_retrieveNodesByType] (nodes) {
|
|
103
131
|
const depNodes = new Set()
|
|
104
132
|
const linkNodes = new Set()
|
|
133
|
+
|
|
105
134
|
for (const node of nodes) {
|
|
106
|
-
// we skip the target nodes to that workspace in order to make sure
|
|
107
|
-
// we only run lifecycle scripts / place bin links once per workspace
|
|
108
135
|
if (node.isLink) {
|
|
109
136
|
linkNodes.add(node)
|
|
110
137
|
} else {
|
|
@@ -112,14 +139,22 @@ module.exports = cls => class Builder extends cls {
|
|
|
112
139
|
}
|
|
113
140
|
}
|
|
114
141
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
142
|
+
// deduplicates link nodes and their targets, avoids
|
|
143
|
+
// calling lifecycle scripts twice when running `npm rebuild`
|
|
144
|
+
// ref: https://github.com/npm/cli/issues/2905
|
|
145
|
+
//
|
|
146
|
+
// we avoid doing so if global=true since `bin-links` relies
|
|
147
|
+
// on having the target nodes available in global mode.
|
|
148
|
+
if (!this[_global]) {
|
|
149
|
+
for (const node of linkNodes) {
|
|
150
|
+
depNodes.delete(node.target)
|
|
151
|
+
}
|
|
120
152
|
}
|
|
121
153
|
|
|
122
|
-
|
|
154
|
+
return {
|
|
155
|
+
depNodes,
|
|
156
|
+
linkNodes,
|
|
157
|
+
}
|
|
123
158
|
}
|
|
124
159
|
|
|
125
160
|
[_resetQueues] () {
|
|
@@ -136,24 +171,22 @@ module.exports = cls => class Builder extends cls {
|
|
|
136
171
|
process.emit('time', `build:${type}`)
|
|
137
172
|
|
|
138
173
|
await this[_buildQueues](nodes)
|
|
174
|
+
|
|
175
|
+
if (!this[_ignoreScripts]) {
|
|
176
|
+
await this[_runScripts]('preinstall')
|
|
177
|
+
}
|
|
178
|
+
|
|
139
179
|
// links should run prepare scripts and only link bins after that
|
|
140
|
-
if (type
|
|
141
|
-
if (!this[_ignoreScripts]) {
|
|
142
|
-
await this[_runScripts]('preinstall')
|
|
143
|
-
}
|
|
144
|
-
if (this[_binLinks]) {
|
|
145
|
-
await this[_linkAllBins]()
|
|
146
|
-
}
|
|
147
|
-
if (!this[_ignoreScripts]) {
|
|
148
|
-
await this[_runScripts]('install')
|
|
149
|
-
await this[_runScripts]('postinstall')
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
180
|
+
if (type === 'links') {
|
|
152
181
|
await this[_runScripts]('prepare')
|
|
182
|
+
}
|
|
183
|
+
if (this[_binLinks]) {
|
|
184
|
+
await this[_linkAllBins]()
|
|
185
|
+
}
|
|
153
186
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
187
|
+
if (!this[_ignoreScripts]) {
|
|
188
|
+
await this[_runScripts]('install')
|
|
189
|
+
await this[_runScripts]('postinstall')
|
|
157
190
|
}
|
|
158
191
|
|
|
159
192
|
process.emit('timeEnd', `build:${type}`)
|
package/lib/arborist/reify.js
CHANGED
|
@@ -1105,7 +1105,8 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1105
1105
|
// skip links that only live within node_modules as they are most
|
|
1106
1106
|
// likely managed by packages we installed, we only want to rebuild
|
|
1107
1107
|
// unchanged links we directly manage
|
|
1108
|
-
|
|
1108
|
+
const linkedFromRoot = node.parent === tree || node.target.fsTop === tree
|
|
1109
|
+
if (node.isLink && linkedFromRoot) {
|
|
1109
1110
|
nodes.push(node)
|
|
1110
1111
|
}
|
|
1111
1112
|
}
|
package/lib/edge.js
CHANGED
|
@@ -92,7 +92,12 @@ class Edge {
|
|
|
92
92
|
return false
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
// NOTE: this condition means we explicitly do not support overriding
|
|
96
|
+
// bundled or shrinkwrapped dependencies
|
|
97
|
+
const spec = (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle)
|
|
98
|
+
? this.rawSpec
|
|
99
|
+
: this.spec
|
|
100
|
+
return depValid(node, spec, this.accept, this.from)
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
explain (seen = []) {
|
package/lib/node.js
CHANGED
|
@@ -524,6 +524,18 @@ class Node {
|
|
|
524
524
|
return this === this.root || this === this.root.target
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
+
get isRegistryDependency () {
|
|
528
|
+
if (this.edgesIn.size === 0) {
|
|
529
|
+
return false
|
|
530
|
+
}
|
|
531
|
+
for (const edge of this.edgesIn) {
|
|
532
|
+
if (!npa(edge.spec).registry) {
|
|
533
|
+
return false
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return true
|
|
537
|
+
}
|
|
538
|
+
|
|
527
539
|
* ancestry () {
|
|
528
540
|
for (let anc = this; anc; anc = anc.resolveParent) {
|
|
529
541
|
yield anc
|
package/lib/shrinkwrap.js
CHANGED
|
@@ -95,6 +95,7 @@ const specFromResolved = resolved => {
|
|
|
95
95
|
const relpath = require('./relpath.js')
|
|
96
96
|
|
|
97
97
|
const consistentResolve = require('./consistent-resolve.js')
|
|
98
|
+
const { overrideResolves } = require('./override-resolves.js')
|
|
98
99
|
|
|
99
100
|
const maybeReadFile = file => {
|
|
100
101
|
return readFile(file, 'utf8').then(d => d, er => {
|
|
@@ -265,7 +266,7 @@ class Shrinkwrap {
|
|
|
265
266
|
return s
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
static metaFromNode (node, path) {
|
|
269
|
+
static metaFromNode (node, path, options = {}) {
|
|
269
270
|
if (node.isLink) {
|
|
270
271
|
return {
|
|
271
272
|
resolved: relpath(path, node.realpath),
|
|
@@ -299,7 +300,12 @@ class Shrinkwrap {
|
|
|
299
300
|
})
|
|
300
301
|
|
|
301
302
|
const resolved = consistentResolve(node.resolved, node.path, path, true)
|
|
302
|
-
|
|
303
|
+
// hide resolved from registry dependencies.
|
|
304
|
+
if (!resolved) {
|
|
305
|
+
// no-op
|
|
306
|
+
} else if (node.isRegistryDependency) {
|
|
307
|
+
meta.resolved = overrideResolves(resolved, options)
|
|
308
|
+
} else {
|
|
303
309
|
meta.resolved = resolved
|
|
304
310
|
}
|
|
305
311
|
|
|
@@ -330,6 +336,7 @@ class Shrinkwrap {
|
|
|
330
336
|
shrinkwrapOnly = false,
|
|
331
337
|
hiddenLockfile = false,
|
|
332
338
|
lockfileVersion,
|
|
339
|
+
resolveOptions = {},
|
|
333
340
|
} = options
|
|
334
341
|
|
|
335
342
|
this.lockfileVersion = hiddenLockfile ? 3
|
|
@@ -347,6 +354,7 @@ class Shrinkwrap {
|
|
|
347
354
|
this.yarnLock = null
|
|
348
355
|
this.hiddenLockfile = hiddenLockfile
|
|
349
356
|
this.loadingError = null
|
|
357
|
+
this.resolveOptions = resolveOptions
|
|
350
358
|
// only load npm-shrinkwrap.json in dep trees, not package-lock
|
|
351
359
|
this.shrinkwrapOnly = shrinkwrapOnly
|
|
352
360
|
}
|
|
@@ -830,7 +838,7 @@ class Shrinkwrap {
|
|
|
830
838
|
resolved,
|
|
831
839
|
integrity,
|
|
832
840
|
hasShrinkwrap,
|
|
833
|
-
} = Shrinkwrap.metaFromNode(node, this.path)
|
|
841
|
+
} = Shrinkwrap.metaFromNode(node, this.path, this.resolveOptions)
|
|
834
842
|
node.resolved = node.resolved || resolved || null
|
|
835
843
|
node.integrity = node.integrity || integrity || null
|
|
836
844
|
node.hasShrinkwrap = node.hasShrinkwrap || hasShrinkwrap || false
|
|
@@ -886,7 +894,10 @@ class Shrinkwrap {
|
|
|
886
894
|
[_updateWaitingNode] (loc) {
|
|
887
895
|
const node = this[_awaitingUpdate].get(loc)
|
|
888
896
|
this[_awaitingUpdate].delete(loc)
|
|
889
|
-
this.data.packages[loc] = Shrinkwrap.metaFromNode(
|
|
897
|
+
this.data.packages[loc] = Shrinkwrap.metaFromNode(
|
|
898
|
+
node,
|
|
899
|
+
this.path,
|
|
900
|
+
this.resolveOptions)
|
|
890
901
|
}
|
|
891
902
|
|
|
892
903
|
commit () {
|
|
@@ -894,7 +905,10 @@ class Shrinkwrap {
|
|
|
894
905
|
if (this.yarnLock) {
|
|
895
906
|
this.yarnLock.fromTree(this.tree)
|
|
896
907
|
}
|
|
897
|
-
const root = Shrinkwrap.metaFromNode(
|
|
908
|
+
const root = Shrinkwrap.metaFromNode(
|
|
909
|
+
this.tree.target,
|
|
910
|
+
this.path,
|
|
911
|
+
this.resolveOptions)
|
|
898
912
|
this.data.packages = {}
|
|
899
913
|
if (Object.keys(root).length) {
|
|
900
914
|
this.data.packages[''] = root
|
|
@@ -905,7 +919,10 @@ class Shrinkwrap {
|
|
|
905
919
|
continue
|
|
906
920
|
}
|
|
907
921
|
const loc = relpath(this.path, node.path)
|
|
908
|
-
this.data.packages[loc] = Shrinkwrap.metaFromNode(
|
|
922
|
+
this.data.packages[loc] = Shrinkwrap.metaFromNode(
|
|
923
|
+
node,
|
|
924
|
+
this.path,
|
|
925
|
+
this.resolveOptions)
|
|
909
926
|
}
|
|
910
927
|
} else if (this[_awaitingUpdate].size > 0) {
|
|
911
928
|
for (const loc of this[_awaitingUpdate].keys()) {
|
|
@@ -1013,7 +1030,7 @@ class Shrinkwrap {
|
|
|
1013
1030
|
spec.type !== 'git' &&
|
|
1014
1031
|
spec.type !== 'file' &&
|
|
1015
1032
|
spec.type !== 'remote') {
|
|
1016
|
-
lock.resolved = node.resolved
|
|
1033
|
+
lock.resolved = overrideResolves(node.resolved, this.resolveOptions)
|
|
1017
1034
|
}
|
|
1018
1035
|
|
|
1019
1036
|
if (node.integrity) {
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npmcli/arborist",
|
|
3
|
-
"version": "5.1
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "Manage node_modules trees",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@isaacs/string-locale-compare": "^1.1.0",
|
|
7
7
|
"@npmcli/installed-package-contents": "^1.0.7",
|
|
8
|
-
"@npmcli/map-workspaces": "^2.0.
|
|
8
|
+
"@npmcli/map-workspaces": "^2.0.3",
|
|
9
9
|
"@npmcli/metavuln-calculator": "^3.0.1",
|
|
10
10
|
"@npmcli/move-file": "^2.0.0",
|
|
11
11
|
"@npmcli/name-from-folder": "^1.0.1",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@npmcli/package-json": "^2.0.0",
|
|
14
14
|
"@npmcli/run-script": "^3.0.0",
|
|
15
15
|
"bin-links": "^3.0.0",
|
|
16
|
-
"cacache": "^16.0.
|
|
16
|
+
"cacache": "^16.0.6",
|
|
17
17
|
"common-ancestor-path": "^1.0.1",
|
|
18
18
|
"json-parse-even-better-errors": "^2.3.1",
|
|
19
19
|
"json-stringify-nice": "^1.1.4",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"npm-package-arg": "^9.0.0",
|
|
25
25
|
"npm-pick-manifest": "^7.0.0",
|
|
26
26
|
"npm-registry-fetch": "^13.0.0",
|
|
27
|
-
"npmlog": "^6.0.
|
|
27
|
+
"npmlog": "^6.0.2",
|
|
28
28
|
"pacote": "^13.0.5",
|
|
29
29
|
"parse-conflict-json": "^2.0.1",
|
|
30
30
|
"proc-log": "^2.0.0",
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
"read-package-json-fast": "^2.0.2",
|
|
34
34
|
"readdir-scoped-modules": "^1.1.0",
|
|
35
35
|
"rimraf": "^3.0.2",
|
|
36
|
-
"semver": "^7.3.
|
|
36
|
+
"semver": "^7.3.7",
|
|
37
37
|
"ssri": "^9.0.0",
|
|
38
38
|
"treeverse": "^2.0.0",
|
|
39
39
|
"walk-up-path": "^1.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@npmcli/eslint-config": "^3.0.1",
|
|
43
|
-
"@npmcli/template-oss": "3.
|
|
43
|
+
"@npmcli/template-oss": "3.5.0",
|
|
44
44
|
"benchmark": "^2.1.4",
|
|
45
45
|
"chalk": "^4.1.0",
|
|
46
46
|
"minify-registry-metadata": "^2.1.0",
|
|
@@ -101,6 +101,6 @@
|
|
|
101
101
|
},
|
|
102
102
|
"templateOSS": {
|
|
103
103
|
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
|
104
|
-
"version": "3.
|
|
104
|
+
"version": "3.5.0"
|
|
105
105
|
}
|
|
106
106
|
}
|