@npmcli/arborist 9.1.5 → 9.1.7
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/bin/index.js +1 -1
- package/lib/arborist/build-ideal-tree.js +43 -54
- package/lib/arborist/index.js +30 -0
- package/lib/arborist/isolated-reifier.js +6 -7
- package/lib/arborist/load-actual.js +1 -14
- package/lib/arborist/load-virtual.js +25 -54
- package/lib/arborist/rebuild.js +13 -18
- package/lib/arborist/reify.js +25 -56
- package/lib/calc-dep-flags.js +86 -128
- package/lib/diff.js +17 -21
- package/lib/edge.js +9 -3
- package/lib/gather-dep-set.js +1 -1
- package/lib/node.js +22 -6
- package/lib/optional-set.js +2 -8
- package/lib/override-set.js +76 -2
- package/lib/packument-cache.js +1 -1
- package/lib/place-dep.js +3 -3
- package/lib/query-selector-all.js +1 -1
- package/lib/reset-dep-flags.js +1 -5
- package/lib/shrinkwrap.js +3 -18
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Inspect and manage `node_modules` trees.
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|
|
|
11
11
|
There's more documentation [in the docs
|
|
12
12
|
folder](https://github.com/npm/cli/tree/latest/workspaces/arborist/docs).
|
package/bin/index.js
CHANGED
|
@@ -37,7 +37,7 @@ ${message && '\n' + message + '\n'}
|
|
|
37
37
|
|
|
38
38
|
Additionally:
|
|
39
39
|
|
|
40
|
-
* --loglevel=warn|--quiet will
|
|
40
|
+
* --loglevel=warn|--quiet will suppress the printing of package trees
|
|
41
41
|
* --logfile <file|bool> will output logs to a file
|
|
42
42
|
* --timing will show timing information
|
|
43
43
|
* Instead of 'npm install <pkg>', use 'arborist reify --add=<pkg>'.
|
|
@@ -42,7 +42,6 @@ const _flagsSuspect = Symbol.for('flagsSuspect')
|
|
|
42
42
|
const _setWorkspaces = Symbol.for('setWorkspaces')
|
|
43
43
|
const _updateNames = Symbol.for('updateNames')
|
|
44
44
|
const _resolvedAdd = Symbol.for('resolvedAdd')
|
|
45
|
-
const _usePackageLock = Symbol.for('usePackageLock')
|
|
46
45
|
const _rpcache = Symbol.for('realpathCache')
|
|
47
46
|
const _stcache = Symbol.for('statCache')
|
|
48
47
|
|
|
@@ -101,39 +100,28 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
101
100
|
constructor (options) {
|
|
102
101
|
super(options)
|
|
103
102
|
|
|
104
|
-
// normalize trailing slash
|
|
105
|
-
const registry = options.registry || 'https://registry.npmjs.org'
|
|
106
|
-
options.registry = this.registry = registry.replace(/\/+$/, '') + '/'
|
|
107
|
-
|
|
108
103
|
const {
|
|
109
104
|
follow = false,
|
|
110
105
|
installStrategy = 'hoisted',
|
|
111
|
-
idealTree = null,
|
|
112
|
-
installLinks = false,
|
|
113
|
-
legacyPeerDeps = false,
|
|
114
|
-
packageLock = true,
|
|
115
106
|
strictPeerDeps = false,
|
|
116
|
-
workspaces,
|
|
117
107
|
global,
|
|
118
108
|
} = options
|
|
119
109
|
|
|
120
110
|
this.#strictPeerDeps = !!strictPeerDeps
|
|
121
111
|
|
|
122
|
-
this.idealTree = idealTree
|
|
123
|
-
this.installLinks = installLinks
|
|
124
|
-
this.legacyPeerDeps = legacyPeerDeps
|
|
125
|
-
|
|
126
|
-
this[_usePackageLock] = packageLock
|
|
127
112
|
this.#installStrategy = global ? 'shallow' : installStrategy
|
|
128
113
|
this.#follow = !!follow
|
|
129
114
|
|
|
130
|
-
if (workspaces?.length && global) {
|
|
131
|
-
throw new Error('Cannot operate on workspaces in global mode')
|
|
132
|
-
}
|
|
133
|
-
|
|
134
115
|
this[_updateAll] = false
|
|
135
116
|
this[_updateNames] = []
|
|
136
117
|
this[_resolvedAdd] = []
|
|
118
|
+
|
|
119
|
+
// caches for cached realpath calls
|
|
120
|
+
const cwd = process.cwd()
|
|
121
|
+
// assume that the cwd is real enough for our purposes
|
|
122
|
+
this[_rpcache] = new Map([[cwd, cwd]])
|
|
123
|
+
this[_stcache] = new Map()
|
|
124
|
+
this[_flagsSuspect] = false
|
|
137
125
|
}
|
|
138
126
|
|
|
139
127
|
get explicitRequests () {
|
|
@@ -192,7 +180,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
192
180
|
}
|
|
193
181
|
|
|
194
182
|
async #checkEngineAndPlatform () {
|
|
195
|
-
const { engineStrict, npmVersion, nodeVersion, omit = [] } = this.options
|
|
183
|
+
const { engineStrict, npmVersion, nodeVersion, omit = [], cpu, os, libc } = this.options
|
|
196
184
|
const omitSet = new Set(omit)
|
|
197
185
|
|
|
198
186
|
for (const node of this.idealTree.inventory.values()) {
|
|
@@ -214,6 +202,19 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
214
202
|
}
|
|
215
203
|
checkPlatform(node.package, this.options.force)
|
|
216
204
|
}
|
|
205
|
+
if (node.optional && !node.inert) {
|
|
206
|
+
// Mark any optional packages we can't install as inert.
|
|
207
|
+
// We ignore the --force and --engine-strict flags.
|
|
208
|
+
try {
|
|
209
|
+
checkEngine(node.package, npmVersion, nodeVersion, false)
|
|
210
|
+
checkPlatform(node.package, false, { cpu, os, libc })
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const set = optionalSet(node)
|
|
213
|
+
for (const node of set) {
|
|
214
|
+
node.inert = true
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
|
|
@@ -285,7 +286,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
285
286
|
.then(root => {
|
|
286
287
|
if (this.options.global) {
|
|
287
288
|
return root
|
|
288
|
-
} else if (!this
|
|
289
|
+
} else if (!this.options.usePackageLock || this[_updateAll]) {
|
|
289
290
|
return Shrinkwrap.reset({
|
|
290
291
|
path: this.path,
|
|
291
292
|
lockfileVersion: this.options.lockfileVersion,
|
|
@@ -324,7 +325,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
324
325
|
})
|
|
325
326
|
|
|
326
327
|
.then(tree => {
|
|
327
|
-
// search the virtual tree for invalid edges, if any are found add their source to
|
|
328
|
+
// search the virtual tree for missing/invalid edges, if any are found add their source to
|
|
328
329
|
// the depsQueue so that we'll fix it later
|
|
329
330
|
depth({
|
|
330
331
|
tree,
|
|
@@ -338,7 +339,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
338
339
|
filter: node => node,
|
|
339
340
|
visit: node => {
|
|
340
341
|
for (const edge of node.edgesOut.values()) {
|
|
341
|
-
if (!edge.valid) {
|
|
342
|
+
if ((!edge.to && edge.type !== 'peerOptional') || !edge.valid) {
|
|
342
343
|
this.#depsQueue.push(node)
|
|
343
344
|
break // no need to continue the loop after the first hit
|
|
344
345
|
}
|
|
@@ -741,6 +742,7 @@ This is a one-time fix-up, please be patient...
|
|
|
741
742
|
|
|
742
743
|
// have to re-calc dep flags, because the nodes don't have edges
|
|
743
744
|
// until their packages get assigned, so everything looks extraneous
|
|
745
|
+
resetDepFlags(this.idealTree)
|
|
744
746
|
calcDepFlags(this.idealTree)
|
|
745
747
|
|
|
746
748
|
// yes, yes, this isn't the "original" version, but now that it's been
|
|
@@ -811,7 +813,7 @@ This is a one-time fix-up, please be patient...
|
|
|
811
813
|
node !== this.idealTree &&
|
|
812
814
|
node.resolved &&
|
|
813
815
|
(hasBundle || hasShrinkwrap) &&
|
|
814
|
-
!node.
|
|
816
|
+
!node.inert
|
|
815
817
|
if (crackOpen) {
|
|
816
818
|
const Arborist = this.constructor
|
|
817
819
|
const opt = { ...this.options }
|
|
@@ -1011,7 +1013,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1011
1013
|
}
|
|
1012
1014
|
|
|
1013
1015
|
// pre-fetch any problem edges, since we'll need these soon
|
|
1014
|
-
// if it fails at this point, though,
|
|
1016
|
+
// if it fails at this point, though, don't worry because it
|
|
1015
1017
|
// may well be an optional dep that has gone missing. it'll
|
|
1016
1018
|
// fail later anyway.
|
|
1017
1019
|
for (const e of this.#problemEdges(placed)) {
|
|
@@ -1067,7 +1069,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1067
1069
|
? await this.#nodeFromSpec(edge.name, spec2, parent, secondEdge)
|
|
1068
1070
|
: null
|
|
1069
1071
|
|
|
1070
|
-
// pick the second one if they're both happy with that
|
|
1072
|
+
// pick the second one if they're both happy with that; otherwise, first
|
|
1071
1073
|
const node = second && edge.valid ? second : first
|
|
1072
1074
|
// ensure the one we want is the one that's placed
|
|
1073
1075
|
node.parent = parent
|
|
@@ -1217,7 +1219,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1217
1219
|
}
|
|
1218
1220
|
}
|
|
1219
1221
|
|
|
1220
|
-
#nodeFromSpec (name, spec, parent, edge) {
|
|
1222
|
+
async #nodeFromSpec (name, spec, parent, edge) {
|
|
1221
1223
|
// pacote will slap integrity on its options, so we have to clone
|
|
1222
1224
|
// the object so it doesn't get mutated.
|
|
1223
1225
|
// Don't bother to load the manifest for link deps, because the target
|
|
@@ -1246,7 +1248,13 @@ This is a one-time fix-up, please be patient...
|
|
|
1246
1248
|
// Decide whether to link or copy the dependency
|
|
1247
1249
|
const shouldLink = (isWorkspace || isProjectInternalFileSpec || !installLinks) && !isTransitiveFileDep
|
|
1248
1250
|
if (spec.type === 'directory' && shouldLink) {
|
|
1249
|
-
|
|
1251
|
+
const realpath = spec.fetchSpec
|
|
1252
|
+
const { content: pkg } = await PackageJson.normalize(realpath).catch(() => {
|
|
1253
|
+
return { content: {} }
|
|
1254
|
+
})
|
|
1255
|
+
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
|
|
1256
|
+
this.#linkNodes.add(link)
|
|
1257
|
+
return link
|
|
1250
1258
|
}
|
|
1251
1259
|
|
|
1252
1260
|
// if the spec matches a workspace name, then see if the workspace node will satisfy the edge. if it does, we return the workspace node to make sure it takes priority.
|
|
@@ -1274,7 +1282,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1274
1282
|
|
|
1275
1283
|
// failed to load the spec, either because of enotarget or
|
|
1276
1284
|
// fetch failure of some other sort. save it so we can verify
|
|
1277
|
-
// later that it's optional
|
|
1285
|
+
// later that it's optional; otherwise, the error is fatal.
|
|
1278
1286
|
const n = new Node({
|
|
1279
1287
|
name,
|
|
1280
1288
|
parent,
|
|
@@ -1287,17 +1295,6 @@ This is a one-time fix-up, please be patient...
|
|
|
1287
1295
|
})
|
|
1288
1296
|
}
|
|
1289
1297
|
|
|
1290
|
-
async #linkFromSpec (name, spec, parent) {
|
|
1291
|
-
const realpath = spec.fetchSpec
|
|
1292
|
-
const { installLinks, legacyPeerDeps } = this
|
|
1293
|
-
const { content: pkg } = await PackageJson.normalize(realpath).catch(() => {
|
|
1294
|
-
return { content: {} }
|
|
1295
|
-
})
|
|
1296
|
-
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
|
|
1297
|
-
this.#linkNodes.add(link)
|
|
1298
|
-
return link
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
1298
|
// load all peer deps and meta-peer deps into the node's parent
|
|
1302
1299
|
// At the end of this, the node's peer-type outward edges are all
|
|
1303
1300
|
// resolved, and so are all of theirs, but other dep types are not.
|
|
@@ -1431,7 +1428,8 @@ This is a one-time fix-up, please be patient...
|
|
|
1431
1428
|
// - if a path under an existing node, then assign that as the fsParent,
|
|
1432
1429
|
// and add it to the _depsQueue
|
|
1433
1430
|
//
|
|
1434
|
-
// call buildDepStep if anything was added to the queue
|
|
1431
|
+
// call buildDepStep if anything was added to the queue; otherwise, we're done
|
|
1432
|
+
// XXX load-virtual also has a #resolveLinks, is there overlap?
|
|
1435
1433
|
#resolveLinks () {
|
|
1436
1434
|
for (const link of this.#linkNodes) {
|
|
1437
1435
|
this.#linkNodes.delete(link)
|
|
@@ -1495,11 +1493,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1495
1493
|
} else {
|
|
1496
1494
|
// otherwise just unset all the flags on the root node
|
|
1497
1495
|
// since they will sometimes have the default value
|
|
1498
|
-
this.idealTree.
|
|
1499
|
-
this.idealTree.dev = false
|
|
1500
|
-
this.idealTree.optional = false
|
|
1501
|
-
this.idealTree.devOptional = false
|
|
1502
|
-
this.idealTree.peer = false
|
|
1496
|
+
this.idealTree.unsetDepFlags()
|
|
1503
1497
|
}
|
|
1504
1498
|
|
|
1505
1499
|
// at this point, any node marked as extraneous should be pruned.
|
|
@@ -1542,12 +1536,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1542
1536
|
|
|
1543
1537
|
#idealTreePrune () {
|
|
1544
1538
|
for (const node of this.idealTree.inventory.values()) {
|
|
1545
|
-
|
|
1546
|
-
// through an explicit required dependency (most commonly in the
|
|
1547
|
-
// root package.json), at which point they won't be optional so
|
|
1548
|
-
// any dependencies still marked as both optional and peer at
|
|
1549
|
-
// this point can be pruned as a special kind of extraneous
|
|
1550
|
-
if (node.extraneous || (node.peer && node.optional)) {
|
|
1539
|
+
if (node.extraneous) {
|
|
1551
1540
|
node.parent = null
|
|
1552
1541
|
}
|
|
1553
1542
|
}
|
|
@@ -1561,7 +1550,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1561
1550
|
|
|
1562
1551
|
const set = optionalSet(node)
|
|
1563
1552
|
for (const node of set) {
|
|
1564
|
-
node.
|
|
1553
|
+
node.inert = true
|
|
1565
1554
|
}
|
|
1566
1555
|
}
|
|
1567
1556
|
}
|
|
@@ -1582,7 +1571,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1582
1571
|
node.parent !== null
|
|
1583
1572
|
&& !node.isProjectRoot
|
|
1584
1573
|
&& !excludeNodes.has(node)
|
|
1585
|
-
&& !node.
|
|
1574
|
+
&& !node.inert
|
|
1586
1575
|
) {
|
|
1587
1576
|
this[_addNodeToTrashList](node)
|
|
1588
1577
|
}
|
package/lib/arborist/index.js
CHANGED
|
@@ -68,6 +68,34 @@ class Arborist extends Base {
|
|
|
68
68
|
constructor (options = {}) {
|
|
69
69
|
const timeEnd = time.start('arborist:ctor')
|
|
70
70
|
super(options)
|
|
71
|
+
|
|
72
|
+
// normalize trailing slash
|
|
73
|
+
const registry = options.registry || 'https://registry.npmjs.org'
|
|
74
|
+
options.registry = this.registry = registry.replace(/(?<!\/)\/+$/, '') + '/'
|
|
75
|
+
|
|
76
|
+
// TODO as we consolidate constructors it's more apparent that we are not parsing options and using this.options consistently
|
|
77
|
+
const {
|
|
78
|
+
actualTree,
|
|
79
|
+
global,
|
|
80
|
+
idealTree = null,
|
|
81
|
+
installLinks = false,
|
|
82
|
+
legacyPeerDeps = false,
|
|
83
|
+
virtualTree,
|
|
84
|
+
workspaces,
|
|
85
|
+
} = options
|
|
86
|
+
|
|
87
|
+
if (workspaces?.length && global) {
|
|
88
|
+
throw new Error('Cannot operate on workspaces in global mode')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// the tree of nodes on disk
|
|
92
|
+
this.actualTree = actualTree
|
|
93
|
+
this.idealTree = idealTree
|
|
94
|
+
this.installLinks = installLinks
|
|
95
|
+
this.legacyPeerDeps = legacyPeerDeps
|
|
96
|
+
// the virtual tree we load from a shrinkwrap
|
|
97
|
+
this.virtualTree = virtualTree
|
|
98
|
+
|
|
71
99
|
this.options = {
|
|
72
100
|
nodeVersion: process.version,
|
|
73
101
|
...options,
|
|
@@ -88,6 +116,7 @@ class Arborist extends Base {
|
|
|
88
116
|
replaceRegistryHost: options.replaceRegistryHost,
|
|
89
117
|
savePrefix: 'savePrefix' in options ? options.savePrefix : '^',
|
|
90
118
|
scriptShell: options.scriptShell,
|
|
119
|
+
usePackageLock: 'packageLock' in options ? options.packageLock : true,
|
|
91
120
|
workspaces: options.workspaces || [],
|
|
92
121
|
workspacesEnabled: options.workspacesEnabled !== false,
|
|
93
122
|
}
|
|
@@ -104,6 +133,7 @@ class Arborist extends Base {
|
|
|
104
133
|
this.cache = resolve(this.options.cache)
|
|
105
134
|
this.diff = null
|
|
106
135
|
this.path = resolve(this.options.path)
|
|
136
|
+
this.scriptsRun = new Set()
|
|
107
137
|
timeEnd()
|
|
108
138
|
}
|
|
109
139
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const _makeIdealGraph = Symbol('makeIdealGraph')
|
|
2
2
|
const _createIsolatedTree = Symbol.for('createIsolatedTree')
|
|
3
|
-
const _createBundledTree = Symbol('createBundledTree')
|
|
4
3
|
const { mkdirSync } = require('node:fs')
|
|
5
4
|
const pacote = require('pacote')
|
|
6
5
|
const { join } = require('node:path')
|
|
@@ -81,7 +80,7 @@ module.exports = cls => class IsolatedReifier extends cls {
|
|
|
81
80
|
}
|
|
82
81
|
queue.push(e.to)
|
|
83
82
|
})
|
|
84
|
-
if (!next.isProjectRoot && !next.isWorkspace && !next.
|
|
83
|
+
if (!next.isProjectRoot && !next.isWorkspace && !next.inert) {
|
|
85
84
|
root.external.push(await this.externalProxyMemo(next))
|
|
86
85
|
}
|
|
87
86
|
}
|
|
@@ -140,15 +139,15 @@ module.exports = cls => class IsolatedReifier extends cls {
|
|
|
140
139
|
|
|
141
140
|
async assignCommonProperties (node, result) {
|
|
142
141
|
function validEdgesOut (node) {
|
|
143
|
-
return [...node.edgesOut.values()].filter(e => e.to && e.to.target && !(node.package.
|
|
142
|
+
return [...node.edgesOut.values()].filter(e => e.to && e.to.target && !(node.package.bundledDependencies || node.package.bundleDependencies || []).includes(e.to.name))
|
|
144
143
|
}
|
|
145
144
|
const edges = validEdgesOut(node)
|
|
146
145
|
const optionalDeps = edges.filter(e => e.optional).map(e => e.to.target)
|
|
147
146
|
const nonOptionalDeps = edges.filter(e => !e.optional).map(e => e.to.target)
|
|
148
147
|
|
|
149
148
|
result.localDependencies = await Promise.all(nonOptionalDeps.filter(n => n.isWorkspace).map(this.workspaceProxyMemo))
|
|
150
|
-
result.externalDependencies = await Promise.all(nonOptionalDeps.filter(n => !n.isWorkspace && !n.
|
|
151
|
-
result.externalOptionalDependencies = await Promise.all(optionalDeps.filter(n => !n.
|
|
149
|
+
result.externalDependencies = await Promise.all(nonOptionalDeps.filter(n => !n.isWorkspace && !n.inert).map(this.externalProxyMemo))
|
|
150
|
+
result.externalOptionalDependencies = await Promise.all(optionalDeps.filter(n => !n.inert).map(this.externalProxyMemo))
|
|
152
151
|
result.dependencies = [
|
|
153
152
|
...result.externalDependencies,
|
|
154
153
|
...result.localDependencies,
|
|
@@ -162,7 +161,7 @@ module.exports = cls => class IsolatedReifier extends cls {
|
|
|
162
161
|
result.hasInstallScript = node.hasInstallScript
|
|
163
162
|
}
|
|
164
163
|
|
|
165
|
-
async
|
|
164
|
+
async #createBundledTree () {
|
|
166
165
|
// TODO: make sure that idealTree object exists
|
|
167
166
|
const idealTree = this.idealTree
|
|
168
167
|
// TODO: test workspaces having bundled deps
|
|
@@ -217,7 +216,7 @@ module.exports = cls => class IsolatedReifier extends cls {
|
|
|
217
216
|
|
|
218
217
|
const proxiedIdealTree = this.idealGraph
|
|
219
218
|
|
|
220
|
-
const bundledTree = await this
|
|
219
|
+
const bundledTree = await this.#createBundledTree()
|
|
221
220
|
|
|
222
221
|
const treeHash = (startNode) => {
|
|
223
222
|
// generate short hash based on the dependency tree
|
|
@@ -36,24 +36,11 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
36
36
|
// We don't do fsParent as a magic getter/setter, because it'd be too costly
|
|
37
37
|
// to keep up to date along the walk.
|
|
38
38
|
// And, we know that it can ONLY be relevant when the node is a target of a
|
|
39
|
-
// link
|
|
39
|
+
// link; otherwise, it'd be in a node_modules folder, so take advantage of
|
|
40
40
|
// that to limit the scans later.
|
|
41
41
|
#topNodes = new Set()
|
|
42
42
|
#transplantFilter
|
|
43
43
|
|
|
44
|
-
constructor (options) {
|
|
45
|
-
super(options)
|
|
46
|
-
|
|
47
|
-
// the tree of nodes on disk
|
|
48
|
-
this.actualTree = options.actualTree
|
|
49
|
-
|
|
50
|
-
// caches for cached realpath calls
|
|
51
|
-
const cwd = process.cwd()
|
|
52
|
-
// assume that the cwd is real enough for our purposes
|
|
53
|
-
this[_rpcache] = new Map([[cwd, cwd]])
|
|
54
|
-
this[_stcache] = new Map()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
44
|
// public method
|
|
58
45
|
// TODO remove options param in next semver major
|
|
59
46
|
async loadActual (options = {}) {
|
|
@@ -18,14 +18,6 @@ const setWorkspaces = Symbol.for('setWorkspaces')
|
|
|
18
18
|
module.exports = cls => class VirtualLoader extends cls {
|
|
19
19
|
#rootOptionProvided
|
|
20
20
|
|
|
21
|
-
constructor (options) {
|
|
22
|
-
super(options)
|
|
23
|
-
|
|
24
|
-
// the virtual tree we load from a shrinkwrap
|
|
25
|
-
this.virtualTree = options.virtualTree
|
|
26
|
-
this[flagsSuspect] = false
|
|
27
|
-
}
|
|
28
|
-
|
|
29
21
|
// public method
|
|
30
22
|
async loadVirtual (options = {}) {
|
|
31
23
|
if (this.virtualTree) {
|
|
@@ -69,11 +61,7 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
69
61
|
if (!this.#rootOptionProvided) {
|
|
70
62
|
// root is never any of these things, but might be a brand new
|
|
71
63
|
// baby Node object that never had its dep flags calculated.
|
|
72
|
-
root.
|
|
73
|
-
root.dev = false
|
|
74
|
-
root.optional = false
|
|
75
|
-
root.devOptional = false
|
|
76
|
-
root.peer = false
|
|
64
|
+
root.unsetDepFlags()
|
|
77
65
|
} else {
|
|
78
66
|
this[flagsSuspect] = true
|
|
79
67
|
}
|
|
@@ -81,7 +69,21 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
81
69
|
this.#checkRootEdges(s, root)
|
|
82
70
|
root.meta = s
|
|
83
71
|
this.virtualTree = root
|
|
84
|
-
|
|
72
|
+
// separate out link metadata, and create Node objects for nodes
|
|
73
|
+
const links = new Map()
|
|
74
|
+
const nodes = new Map([['', root]])
|
|
75
|
+
for (const [location, meta] of Object.entries(s.data.packages)) {
|
|
76
|
+
// skip the root because we already got it
|
|
77
|
+
if (!location) {
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (meta.link) {
|
|
82
|
+
links.set(location, meta)
|
|
83
|
+
} else {
|
|
84
|
+
nodes.set(location, this.#loadNode(location, meta))
|
|
85
|
+
}
|
|
86
|
+
}
|
|
85
87
|
await this.#resolveLinks(links, nodes)
|
|
86
88
|
if (!(s.originalLockfileVersion >= 2)) {
|
|
87
89
|
this.#assignBundles(nodes)
|
|
@@ -93,11 +95,7 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
93
95
|
if (node.isRoot || node === this.#rootOptionProvided) {
|
|
94
96
|
continue
|
|
95
97
|
}
|
|
96
|
-
node.
|
|
97
|
-
node.dev = true
|
|
98
|
-
node.optional = true
|
|
99
|
-
node.devOptional = true
|
|
100
|
-
node.peer = true
|
|
98
|
+
node.resetDepFlags()
|
|
101
99
|
}
|
|
102
100
|
calcDepFlags(this.virtualTree, !this.#rootOptionProvided)
|
|
103
101
|
}
|
|
@@ -168,27 +166,9 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
168
166
|
}
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
// separate out link metadatas, and create Node objects for nodes
|
|
172
|
-
#resolveNodes (s, root) {
|
|
173
|
-
const links = new Map()
|
|
174
|
-
const nodes = new Map([['', root]])
|
|
175
|
-
for (const [location, meta] of Object.entries(s.data.packages)) {
|
|
176
|
-
// skip the root because we already got it
|
|
177
|
-
if (!location) {
|
|
178
|
-
continue
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (meta.link) {
|
|
182
|
-
links.set(location, meta)
|
|
183
|
-
} else {
|
|
184
|
-
nodes.set(location, this.#loadNode(location, meta))
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return { links, nodes }
|
|
188
|
-
}
|
|
189
|
-
|
|
190
169
|
// links is the set of metadata, and nodes is the map of non-Link nodes
|
|
191
170
|
// Set the targets to nodes in the set, if we have them (we might not)
|
|
171
|
+
// XXX build-ideal-tree also has a #resolveLinks, is there overlap?
|
|
192
172
|
async #resolveLinks (links, nodes) {
|
|
193
173
|
for (const [location, meta] of links.entries()) {
|
|
194
174
|
const targetPath = resolve(this.path, meta.resolved)
|
|
@@ -255,11 +235,6 @@ To fix:
|
|
|
255
235
|
sw.name = nameFromFolder(path)
|
|
256
236
|
}
|
|
257
237
|
|
|
258
|
-
const dev = sw.dev
|
|
259
|
-
const optional = sw.optional
|
|
260
|
-
const devOptional = dev || optional || sw.devOptional
|
|
261
|
-
const peer = sw.peer
|
|
262
|
-
|
|
263
238
|
const node = new Node({
|
|
264
239
|
installLinks: this.installLinks,
|
|
265
240
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
@@ -269,20 +244,16 @@ To fix:
|
|
|
269
244
|
integrity: sw.integrity,
|
|
270
245
|
resolved: consistentResolve(sw.resolved, this.path, path),
|
|
271
246
|
pkg: sw,
|
|
272
|
-
ideallyInert: sw.ideallyInert,
|
|
273
247
|
hasShrinkwrap: sw.hasShrinkwrap,
|
|
274
|
-
dev,
|
|
275
|
-
optional,
|
|
276
|
-
devOptional,
|
|
277
|
-
peer,
|
|
278
248
|
loadOverrides,
|
|
249
|
+
// cast to boolean because they're undefined in the lock file when false
|
|
250
|
+
extraneous: !!sw.extraneous,
|
|
251
|
+
devOptional: !!(sw.devOptional || sw.dev || sw.optional),
|
|
252
|
+
peer: !!sw.peer,
|
|
253
|
+
optional: !!sw.optional,
|
|
254
|
+
dev: !!sw.dev,
|
|
279
255
|
})
|
|
280
|
-
|
|
281
|
-
node.extraneous = !!sw.extraneous
|
|
282
|
-
node.devOptional = !!(sw.devOptional || sw.dev || sw.optional)
|
|
283
|
-
node.peer = !!sw.peer
|
|
284
|
-
node.optional = !!sw.optional
|
|
285
|
-
node.dev = !!sw.dev
|
|
256
|
+
|
|
286
257
|
return node
|
|
287
258
|
}
|
|
288
259
|
|
package/lib/arborist/rebuild.js
CHANGED
|
@@ -24,13 +24,12 @@ const _trashList = Symbol.for('trashList')
|
|
|
24
24
|
module.exports = cls => class Builder extends cls {
|
|
25
25
|
#doHandleOptionalFailure
|
|
26
26
|
#oldMeta = null
|
|
27
|
-
#queues
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.#resetQueues()
|
|
27
|
+
#queues = {
|
|
28
|
+
preinstall: [],
|
|
29
|
+
install: [],
|
|
30
|
+
postinstall: [],
|
|
31
|
+
prepare: [],
|
|
32
|
+
bin: [],
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
async rebuild ({ nodes, handleOptionalFailure = false } = {}) {
|
|
@@ -62,7 +61,13 @@ module.exports = cls => class Builder extends cls {
|
|
|
62
61
|
|
|
63
62
|
// build link deps
|
|
64
63
|
if (linkNodes.size) {
|
|
65
|
-
this.#
|
|
64
|
+
this.#queues = {
|
|
65
|
+
preinstall: [],
|
|
66
|
+
install: [],
|
|
67
|
+
postinstall: [],
|
|
68
|
+
prepare: [],
|
|
69
|
+
bin: [],
|
|
70
|
+
}
|
|
66
71
|
await this.#build(linkNodes, { type: 'links' })
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -132,16 +137,6 @@ module.exports = cls => class Builder extends cls {
|
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
|
|
135
|
-
#resetQueues () {
|
|
136
|
-
this.#queues = {
|
|
137
|
-
preinstall: [],
|
|
138
|
-
install: [],
|
|
139
|
-
postinstall: [],
|
|
140
|
-
prepare: [],
|
|
141
|
-
bin: [],
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
140
|
async #build (nodes, { type = 'deps' }) {
|
|
146
141
|
const timeEnd = time.start(`build:${type}`)
|
|
147
142
|
|