@npmcli/arborist 2.6.2 → 2.7.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/bin/lib/timers.js +3 -1
- package/lib/arborist/build-ideal-tree.js +24 -17
- package/lib/arborist/index.js +2 -2
- package/lib/arborist/load-actual.js +17 -5
- package/lib/arborist/load-virtual.js +1 -1
- package/lib/arborist/rebuild.js +3 -3
- package/lib/arborist/reify.js +38 -43
- package/lib/audit-report.js +1 -1
- package/lib/calc-dep-flags.js +17 -5
- package/lib/diff.js +5 -7
- package/lib/inventory.js +17 -1
- package/lib/node.js +27 -5
- package/lib/shrinkwrap.js +7 -6
- package/lib/tracker.js +1 -1
- package/package.json +6 -1
- package/lib/proc-log.js +0 -21
- package/lib/update-root-package-json.js +0 -95
package/bin/lib/timers.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const timers = Object.create(null)
|
|
2
2
|
const { format } = require('util')
|
|
3
|
+
const options = require('./options.js')
|
|
3
4
|
|
|
4
5
|
process.on('time', name => {
|
|
5
6
|
if (timers[name])
|
|
@@ -15,7 +16,8 @@ process.on('timeEnd', name => {
|
|
|
15
16
|
const res = process.hrtime(timers[name])
|
|
16
17
|
delete timers[name]
|
|
17
18
|
const msg = format(`${process.pid} ${name}`, res[0] * 1e3 + res[1] / 1e6)
|
|
18
|
-
|
|
19
|
+
if (options.timers !== false)
|
|
20
|
+
console.error(dim(msg))
|
|
19
21
|
})
|
|
20
22
|
|
|
21
23
|
process.on('exit', () => {
|
|
@@ -7,7 +7,7 @@ const semver = require('semver')
|
|
|
7
7
|
const promiseCallLimit = require('promise-call-limit')
|
|
8
8
|
const getPeerSet = require('../peer-set.js')
|
|
9
9
|
const realpath = require('../../lib/realpath.js')
|
|
10
|
-
const { resolve } = require('path')
|
|
10
|
+
const { resolve, dirname } = require('path')
|
|
11
11
|
const { promisify } = require('util')
|
|
12
12
|
const treeCheck = require('../tree-check.js')
|
|
13
13
|
const readdir = promisify(require('readdir-scoped-modules'))
|
|
@@ -324,7 +324,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
324
324
|
.then(async root => {
|
|
325
325
|
if (!this[_updateAll] && !this[_global] && !root.meta.loadedFromDisk) {
|
|
326
326
|
await new this.constructor(this.options).loadActual({ root })
|
|
327
|
-
const tree = root.target
|
|
327
|
+
const tree = root.target
|
|
328
328
|
// even though we didn't load it from a package-lock.json FILE,
|
|
329
329
|
// we still loaded it "from disk", meaning we have to reset
|
|
330
330
|
// dep flags before assuming that any mutations were reflected.
|
|
@@ -396,7 +396,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
396
396
|
// update.names request by queueing nodes dependent on those named.
|
|
397
397
|
async [_applyUserRequests] (options) {
|
|
398
398
|
process.emit('time', 'idealTree:userRequests')
|
|
399
|
-
const tree = this.idealTree.target
|
|
399
|
+
const tree = this.idealTree.target
|
|
400
400
|
|
|
401
401
|
if (!this[_workspaces].length)
|
|
402
402
|
await this[_applyUserRequestsToNode](tree, options)
|
|
@@ -532,7 +532,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
532
532
|
/* istanbul ignore else - should also be covered by realpath failure */
|
|
533
533
|
if (filepath) {
|
|
534
534
|
const { name } = spec
|
|
535
|
-
const tree = this.idealTree.target
|
|
535
|
+
const tree = this.idealTree.target
|
|
536
536
|
spec = npa(`file:${relpath(tree.path, filepath)}`, tree.path)
|
|
537
537
|
spec.name = name
|
|
538
538
|
}
|
|
@@ -661,7 +661,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
661
661
|
const ancient = meta.ancientLockfile
|
|
662
662
|
const old = meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2)
|
|
663
663
|
|
|
664
|
-
if (inventory.size === 0 || !ancient && !
|
|
664
|
+
if (inventory.size === 0 || !ancient && !old)
|
|
665
665
|
return
|
|
666
666
|
|
|
667
667
|
// if the lockfile is from node v5 or earlier, then we'll have to reload
|
|
@@ -688,10 +688,12 @@ This is a one-time fix-up, please be patient...
|
|
|
688
688
|
this.log.silly('inflate', node.location)
|
|
689
689
|
const { resolved, version, path, name, location, integrity } = node
|
|
690
690
|
// don't try to hit the registry for linked deps
|
|
691
|
-
const useResolved =
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
const
|
|
691
|
+
const useResolved = resolved && (
|
|
692
|
+
!version || resolved.startsWith('file:')
|
|
693
|
+
)
|
|
694
|
+
const id = useResolved ? resolved
|
|
695
|
+
: version || `file:${node.path}`
|
|
696
|
+
const spec = npa.resolve(name, id, dirname(path))
|
|
695
697
|
const sloc = location.substr('node_modules/'.length)
|
|
696
698
|
const t = `idealTree:inflate:${sloc}`
|
|
697
699
|
this.addTracker(t)
|
|
@@ -728,7 +730,7 @@ This is a one-time fix-up, please be patient...
|
|
|
728
730
|
// or extraneous.
|
|
729
731
|
[_buildDeps] () {
|
|
730
732
|
process.emit('time', 'idealTree:buildDeps')
|
|
731
|
-
const tree = this.idealTree.target
|
|
733
|
+
const tree = this.idealTree.target
|
|
732
734
|
this[_depsQueue].push(tree)
|
|
733
735
|
this.log.silly('idealTree', 'buildDeps')
|
|
734
736
|
this.addTracker('idealTree', tree.name, '')
|
|
@@ -786,7 +788,11 @@ This is a one-time fix-up, please be patient...
|
|
|
786
788
|
const Arborist = this.constructor
|
|
787
789
|
const opt = { ...this.options }
|
|
788
790
|
await cacache.tmp.withTmp(this.cache, opt, async path => {
|
|
789
|
-
await pacote.extract(node.resolved, path,
|
|
791
|
+
await pacote.extract(node.resolved, path, {
|
|
792
|
+
...opt,
|
|
793
|
+
resolved: node.resolved,
|
|
794
|
+
integrity: node.integrity,
|
|
795
|
+
})
|
|
790
796
|
|
|
791
797
|
if (hasShrinkwrap) {
|
|
792
798
|
await new Arborist({ ...this.options, path })
|
|
@@ -912,7 +918,7 @@ This is a one-time fix-up, please be patient...
|
|
|
912
918
|
await Promise.all(promises)
|
|
913
919
|
|
|
914
920
|
for (const { to } of node.edgesOut.values()) {
|
|
915
|
-
if (to && to.isLink)
|
|
921
|
+
if (to && to.isLink && to.target)
|
|
916
922
|
this[_linkNodes].add(to)
|
|
917
923
|
}
|
|
918
924
|
|
|
@@ -1291,7 +1297,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1291
1297
|
|
|
1292
1298
|
// when installing globally, or just in global style, we never place
|
|
1293
1299
|
// deps above the first level.
|
|
1294
|
-
const tree = this.idealTree && this.idealTree.target
|
|
1300
|
+
const tree = this.idealTree && this.idealTree.target
|
|
1295
1301
|
if (this[_globalStyle] && check.resolveParent === tree)
|
|
1296
1302
|
break
|
|
1297
1303
|
}
|
|
@@ -1360,7 +1366,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1360
1366
|
integrity: dep.integrity,
|
|
1361
1367
|
legacyPeerDeps: this.legacyPeerDeps,
|
|
1362
1368
|
error: dep.errors[0],
|
|
1363
|
-
...(dep.
|
|
1369
|
+
...(dep.isLink ? { target: dep.target, realpath: dep.target.path } : {}),
|
|
1364
1370
|
})
|
|
1365
1371
|
if (this[_loadFailures].has(dep))
|
|
1366
1372
|
this[_loadFailures].add(newDep)
|
|
@@ -1419,7 +1425,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1419
1425
|
// prune anything deeper in the tree that can be replaced by this
|
|
1420
1426
|
if (this.idealTree) {
|
|
1421
1427
|
for (const node of this.idealTree.inventory.query('name', newDep.name)) {
|
|
1422
|
-
if (node.isDescendantOf(target))
|
|
1428
|
+
if (!node.isTop && node.isDescendantOf(target))
|
|
1423
1429
|
this[_pruneDedupable](node, false)
|
|
1424
1430
|
}
|
|
1425
1431
|
}
|
|
@@ -1817,7 +1823,7 @@ This is a one-time fix-up, please be patient...
|
|
|
1817
1823
|
const current = target !== entryEdge.from && target.resolve(dep.name)
|
|
1818
1824
|
if (current) {
|
|
1819
1825
|
for (const edge of current.edgesIn.values()) {
|
|
1820
|
-
if (edge.from.isDescendantOf(target) && edge.valid) {
|
|
1826
|
+
if (!edge.from.isTop && edge.from.isDescendantOf(target) && edge.valid) {
|
|
1821
1827
|
if (!edge.satisfiedBy(dep))
|
|
1822
1828
|
return CONFLICT
|
|
1823
1829
|
}
|
|
@@ -1874,7 +1880,8 @@ This is a one-time fix-up, please be patient...
|
|
|
1874
1880
|
if (link.root !== this.idealTree)
|
|
1875
1881
|
continue
|
|
1876
1882
|
|
|
1877
|
-
const
|
|
1883
|
+
const tree = this.idealTree.target
|
|
1884
|
+
const external = !link.target.isDescendantOf(tree)
|
|
1878
1885
|
|
|
1879
1886
|
// outside the root, somebody else's problem, ignore it
|
|
1880
1887
|
if (external && !this[_follow])
|
package/lib/arborist/index.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
const {resolve} = require('path')
|
|
30
30
|
const {homedir} = require('os')
|
|
31
|
-
const procLog = require('
|
|
31
|
+
const procLog = require('proc-log')
|
|
32
32
|
const { saveTypeMap } = require('../add-rm-pkg-deps.js')
|
|
33
33
|
|
|
34
34
|
const mixins = [
|
|
@@ -81,7 +81,7 @@ class Arborist extends Base {
|
|
|
81
81
|
const dep = edge.to
|
|
82
82
|
if (dep) {
|
|
83
83
|
set.add(dep)
|
|
84
|
-
if (dep.
|
|
84
|
+
if (dep.isLink)
|
|
85
85
|
set.add(dep.target)
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -22,6 +22,7 @@ const _loadFSTree = Symbol('loadFSTree')
|
|
|
22
22
|
const _loadFSChildren = Symbol('loadFSChildren')
|
|
23
23
|
const _findMissingEdges = Symbol('findMissingEdges')
|
|
24
24
|
const _findFSParents = Symbol('findFSParents')
|
|
25
|
+
const _resetDepFlags = Symbol('resetDepFlags')
|
|
25
26
|
|
|
26
27
|
const _actualTreeLoaded = Symbol('actualTreeLoaded')
|
|
27
28
|
const _rpcache = Symbol.for('realpathCache')
|
|
@@ -74,6 +75,19 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
74
75
|
this[_topNodes] = new Set()
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
[_resetDepFlags] (tree, root) {
|
|
79
|
+
// reset all deps to extraneous prior to recalc
|
|
80
|
+
if (!root) {
|
|
81
|
+
for (const node of tree.inventory.values())
|
|
82
|
+
node.extraneous = true
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// only reset root flags if we're not re-rooting,
|
|
86
|
+
// otherwise leave as-is
|
|
87
|
+
calcDepFlags(tree, !root)
|
|
88
|
+
return tree
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
// public method
|
|
78
92
|
async loadActual (options = {}) {
|
|
79
93
|
// allow the user to set options on the ctor as well.
|
|
@@ -88,6 +102,7 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
88
102
|
return this.actualTree ? this.actualTree
|
|
89
103
|
: this[_actualTreePromise] ? this[_actualTreePromise]
|
|
90
104
|
: this[_actualTreePromise] = this[_loadActual](options)
|
|
105
|
+
.then(tree => this[_resetDepFlags](tree, options.root))
|
|
91
106
|
.then(tree => this.actualTree = treeCheck(tree))
|
|
92
107
|
}
|
|
93
108
|
|
|
@@ -152,8 +167,7 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
152
167
|
root: this[_actualTree],
|
|
153
168
|
})
|
|
154
169
|
await this[_loadWorkspaces](this[_actualTree])
|
|
155
|
-
|
|
156
|
-
calcDepFlags(this[_actualTree], !root)
|
|
170
|
+
|
|
157
171
|
this[_transplant](root)
|
|
158
172
|
return this[_actualTree]
|
|
159
173
|
}
|
|
@@ -178,8 +192,6 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
178
192
|
dependencies[name] = dependencies[name] || '*'
|
|
179
193
|
actualRoot.package = { ...actualRoot.package, dependencies }
|
|
180
194
|
}
|
|
181
|
-
// only reset root flags if we're not re-rooting, otherwise leave as-is
|
|
182
|
-
calcDepFlags(this[_actualTree], !root)
|
|
183
195
|
return this[_actualTree]
|
|
184
196
|
}
|
|
185
197
|
|
|
@@ -303,7 +315,7 @@ module.exports = cls => class ActualLoader extends cls {
|
|
|
303
315
|
|
|
304
316
|
[_loadFSTree] (node) {
|
|
305
317
|
const did = this[_actualTreeLoaded]
|
|
306
|
-
node = node.target
|
|
318
|
+
node = node.target
|
|
307
319
|
|
|
308
320
|
// if a Link target has started, but not completed, then
|
|
309
321
|
// a Promise will be in the cache to indicate this.
|
|
@@ -221,7 +221,7 @@ module.exports = cls => class VirtualLoader extends cls {
|
|
|
221
221
|
[assignBundles] (nodes) {
|
|
222
222
|
for (const [location, node] of nodes) {
|
|
223
223
|
// Skip assignment of parentage for the root package
|
|
224
|
-
if (!location || node.
|
|
224
|
+
if (!location || node.isLink && !node.target.location)
|
|
225
225
|
continue
|
|
226
226
|
const { name, parent, package: { inBundle }} = node
|
|
227
227
|
|
package/lib/arborist/rebuild.js
CHANGED
|
@@ -169,7 +169,7 @@ module.exports = cls => class Builder extends cls {
|
|
|
169
169
|
const queue = [...set].sort(sortNodes)
|
|
170
170
|
|
|
171
171
|
for (const node of queue) {
|
|
172
|
-
const { package: { bin, scripts = {} } } = node
|
|
172
|
+
const { package: { bin, scripts = {} } } = node.target
|
|
173
173
|
const { preinstall, install, postinstall, prepare } = scripts
|
|
174
174
|
const tests = { bin, preinstall, install, postinstall, prepare }
|
|
175
175
|
for (const [key, has] of Object.entries(tests)) {
|
|
@@ -202,7 +202,7 @@ module.exports = cls => class Builder extends cls {
|
|
|
202
202
|
!(meta.originalLockfileVersion >= 2)
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
const { package: pkg, hasInstallScript } = node
|
|
205
|
+
const { package: pkg, hasInstallScript } = node.target
|
|
206
206
|
const { gypfile, bin, scripts = {} } = pkg
|
|
207
207
|
|
|
208
208
|
const { preinstall, install, postinstall, prepare } = scripts
|
|
@@ -263,7 +263,7 @@ module.exports = cls => class Builder extends cls {
|
|
|
263
263
|
devOptional,
|
|
264
264
|
package: pkg,
|
|
265
265
|
location,
|
|
266
|
-
} = node.target
|
|
266
|
+
} = node.target
|
|
267
267
|
|
|
268
268
|
// skip any that we know we'll be deleting
|
|
269
269
|
if (this[_trashList].has(path))
|
package/lib/arborist/reify.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const onExit = require('../signal-handling.js')
|
|
4
4
|
const pacote = require('pacote')
|
|
5
|
-
const rpj = require('read-package-json-fast')
|
|
6
5
|
const AuditReport = require('../audit-report.js')
|
|
7
6
|
const {subset, intersects} = require('semver')
|
|
8
7
|
const npa = require('npm-package-arg')
|
|
@@ -16,6 +15,7 @@ const mkdirp = require('mkdirp-infer-owner')
|
|
|
16
15
|
const justMkdirp = require('mkdirp')
|
|
17
16
|
const moveFile = require('@npmcli/move-file')
|
|
18
17
|
const rimraf = promisify(require('rimraf'))
|
|
18
|
+
const PackageJson = require('@npmcli/package-json')
|
|
19
19
|
const packageContents = require('@npmcli/installed-package-contents')
|
|
20
20
|
const { checkEngine, checkPlatform } = require('npm-install-checks')
|
|
21
21
|
|
|
@@ -25,7 +25,6 @@ const Diff = require('../diff.js')
|
|
|
25
25
|
const retirePath = require('../retire-path.js')
|
|
26
26
|
const promiseAllRejectLate = require('promise-all-reject-late')
|
|
27
27
|
const optionalSet = require('../optional-set.js')
|
|
28
|
-
const updateRootPackageJson = require('../update-root-package-json.js')
|
|
29
28
|
const calcDepFlags = require('../calc-dep-flags.js')
|
|
30
29
|
const { saveTypeMap, hasSubKey } = require('../add-rm-pkg-deps.js')
|
|
31
30
|
|
|
@@ -57,7 +56,6 @@ const _extractOrLink = Symbol('extractOrLink')
|
|
|
57
56
|
const _checkBins = Symbol.for('checkBins')
|
|
58
57
|
const _symlink = Symbol('symlink')
|
|
59
58
|
const _warnDeprecated = Symbol('warnDeprecated')
|
|
60
|
-
const _loadAncientPackageDetails = Symbol('loadAncientPackageDetails')
|
|
61
59
|
const _loadBundlesAndUpdateTrees = Symbol.for('loadBundlesAndUpdateTrees')
|
|
62
60
|
const _submitQuickAudit = Symbol('submitQuickAudit')
|
|
63
61
|
const _awaitQuickAudit = Symbol('awaitQuickAudit')
|
|
@@ -291,8 +289,8 @@ module.exports = cls => class Reifier extends cls {
|
|
|
291
289
|
|
|
292
290
|
const filterNodes = []
|
|
293
291
|
if (this[_global] && this.explicitRequests.size) {
|
|
294
|
-
const idealTree = this.idealTree.target
|
|
295
|
-
const actualTree = this.actualTree.target
|
|
292
|
+
const idealTree = this.idealTree.target
|
|
293
|
+
const actualTree = this.actualTree.target
|
|
296
294
|
// we ONLY are allowed to make changes in the global top-level
|
|
297
295
|
// children where there's an explicit request.
|
|
298
296
|
for (const { name } of this.explicitRequests) {
|
|
@@ -406,10 +404,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
406
404
|
return
|
|
407
405
|
|
|
408
406
|
process.emit('time', 'reify:trashOmits')
|
|
409
|
-
|
|
410
|
-
// not the parent-less top level nodes
|
|
407
|
+
|
|
411
408
|
const filter = node =>
|
|
412
|
-
node.
|
|
409
|
+
node.top.isProjectRoot &&
|
|
413
410
|
(node.peer && this[_omitPeer] ||
|
|
414
411
|
node.dev && this[_omitDev] ||
|
|
415
412
|
node.optional && this[_omitOptional] ||
|
|
@@ -522,7 +519,6 @@ module.exports = cls => class Reifier extends cls {
|
|
|
522
519
|
await this[_checkBins](node)
|
|
523
520
|
await this[_extractOrLink](node)
|
|
524
521
|
await this[_warnDeprecated](node)
|
|
525
|
-
await this[_loadAncientPackageDetails](node)
|
|
526
522
|
})
|
|
527
523
|
|
|
528
524
|
return this[_handleOptionalFailure](node, p)
|
|
@@ -583,32 +579,6 @@ module.exports = cls => class Reifier extends cls {
|
|
|
583
579
|
this.log.warn('deprecated', `${_id}: ${deprecated}`)
|
|
584
580
|
}
|
|
585
581
|
|
|
586
|
-
async [_loadAncientPackageDetails] (node, forceReload = false) {
|
|
587
|
-
// If we're loading from a v1 lockfile, load details from the package.json
|
|
588
|
-
// that weren't recorded in the old format.
|
|
589
|
-
const {meta} = this.idealTree
|
|
590
|
-
const ancient = meta.ancientLockfile
|
|
591
|
-
const old = meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2)
|
|
592
|
-
|
|
593
|
-
// already replaced with the manifest if it's truly ancient
|
|
594
|
-
if (node.path && (forceReload || (old && !ancient))) {
|
|
595
|
-
// XXX should have a shared location where package.json is read,
|
|
596
|
-
// so we don't ever read the same pj more than necessary.
|
|
597
|
-
let pkg
|
|
598
|
-
try {
|
|
599
|
-
pkg = await rpj(node.path + '/package.json')
|
|
600
|
-
} catch (err) {}
|
|
601
|
-
|
|
602
|
-
if (pkg) {
|
|
603
|
-
node.package.bin = pkg.bin
|
|
604
|
-
node.package.os = pkg.os
|
|
605
|
-
node.package.cpu = pkg.cpu
|
|
606
|
-
node.package.engines = pkg.engines
|
|
607
|
-
meta.add(node)
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
|
|
612
582
|
// if the node is optional, then the failure of the promise is nonfatal
|
|
613
583
|
// just add it and its optional set to the trash list.
|
|
614
584
|
[_handleOptionalFailure] (node, p) {
|
|
@@ -693,7 +663,7 @@ module.exports = cls => class Reifier extends cls {
|
|
|
693
663
|
const node = diff.ideal
|
|
694
664
|
if (!node)
|
|
695
665
|
return
|
|
696
|
-
if (node.isProjectRoot
|
|
666
|
+
if (node.isProjectRoot)
|
|
697
667
|
return
|
|
698
668
|
|
|
699
669
|
const { bundleDependencies } = node.package
|
|
@@ -916,6 +886,18 @@ module.exports = cls => class Reifier extends cls {
|
|
|
916
886
|
filter: diff => diff.action === 'ADD' || diff.action === 'CHANGE',
|
|
917
887
|
})
|
|
918
888
|
|
|
889
|
+
// pick up link nodes from the unchanged list as we want to run their
|
|
890
|
+
// scripts in every install despite of having a diff status change
|
|
891
|
+
for (const node of this.diff.unchanged) {
|
|
892
|
+
const tree = node.root.target
|
|
893
|
+
|
|
894
|
+
// skip links that only live within node_modules as they are most
|
|
895
|
+
// likely managed by packages we installed, we only want to rebuild
|
|
896
|
+
// unchanged links we directly manage
|
|
897
|
+
if (node.isLink && node.target.fsTop === tree)
|
|
898
|
+
nodes.push(node)
|
|
899
|
+
}
|
|
900
|
+
|
|
919
901
|
return this.rebuild({ nodes, handleOptionalFailure: true })
|
|
920
902
|
.then(() => process.emit('timeEnd', 'reify:build'))
|
|
921
903
|
}
|
|
@@ -1058,6 +1040,25 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1058
1040
|
|
|
1059
1041
|
const promises = [this[_saveLockFile](saveOpt)]
|
|
1060
1042
|
|
|
1043
|
+
const updatePackageJson = async (tree) => {
|
|
1044
|
+
const pkgJson = await PackageJson.load(tree.path)
|
|
1045
|
+
.catch(() => new PackageJson(tree.path))
|
|
1046
|
+
const {
|
|
1047
|
+
dependencies = {},
|
|
1048
|
+
devDependencies = {},
|
|
1049
|
+
optionalDependencies = {},
|
|
1050
|
+
peerDependencies = {},
|
|
1051
|
+
} = tree.package
|
|
1052
|
+
|
|
1053
|
+
pkgJson.update({
|
|
1054
|
+
dependencies,
|
|
1055
|
+
devDependencies,
|
|
1056
|
+
optionalDependencies,
|
|
1057
|
+
peerDependencies,
|
|
1058
|
+
})
|
|
1059
|
+
await pkgJson.save()
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1061
1062
|
// grab any from explicitRequests that had deps removed
|
|
1062
1063
|
for (const { from: tree } of this.explicitRequests)
|
|
1063
1064
|
updatedTrees.add(tree)
|
|
@@ -1065,7 +1066,7 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1065
1066
|
for (const tree of updatedTrees) {
|
|
1066
1067
|
// refresh the edges so they have the correct specs
|
|
1067
1068
|
tree.package = tree.package
|
|
1068
|
-
promises.push(
|
|
1069
|
+
promises.push(updatePackageJson(tree))
|
|
1069
1070
|
}
|
|
1070
1071
|
|
|
1071
1072
|
await Promise.all(promises)
|
|
@@ -1079,12 +1080,6 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1079
1080
|
|
|
1080
1081
|
const { meta } = this.idealTree
|
|
1081
1082
|
|
|
1082
|
-
// might have to update metadata for bins and stuff that gets lost
|
|
1083
|
-
if (meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2)) {
|
|
1084
|
-
for (const node of this.idealTree.inventory.values())
|
|
1085
|
-
await this[_loadAncientPackageDetails](node, true)
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
1083
|
return meta.save(saveOpt)
|
|
1089
1084
|
}
|
|
1090
1085
|
|
package/lib/audit-report.js
CHANGED
|
@@ -12,7 +12,7 @@ const _fixAvailable = Symbol('fixAvailable')
|
|
|
12
12
|
const _checkTopNode = Symbol('checkTopNode')
|
|
13
13
|
const _init = Symbol('init')
|
|
14
14
|
const _omit = Symbol('omit')
|
|
15
|
-
const procLog = require('
|
|
15
|
+
const procLog = require('proc-log')
|
|
16
16
|
|
|
17
17
|
const fetch = require('npm-registry-fetch')
|
|
18
18
|
|
package/lib/calc-dep-flags.js
CHANGED
|
@@ -22,15 +22,19 @@ const calcDepFlagsStep = (node) => {
|
|
|
22
22
|
// Since we're only walking through deps that are not already flagged
|
|
23
23
|
// as non-dev/non-optional, it's typically a very shallow traversal
|
|
24
24
|
node.extraneous = false
|
|
25
|
+
resetParents(node, 'extraneous')
|
|
26
|
+
resetParents(node, 'dev')
|
|
27
|
+
resetParents(node, 'peer')
|
|
28
|
+
resetParents(node, 'devOptional')
|
|
29
|
+
resetParents(node, 'optional')
|
|
25
30
|
|
|
26
31
|
// for links, map their hierarchy appropriately
|
|
27
|
-
if (node.
|
|
32
|
+
if (node.isLink) {
|
|
28
33
|
node.target.dev = node.dev
|
|
29
34
|
node.target.optional = node.optional
|
|
30
35
|
node.target.devOptional = node.devOptional
|
|
31
36
|
node.target.peer = node.peer
|
|
32
|
-
node.target
|
|
33
|
-
node = node.target
|
|
37
|
+
return calcDepFlagsStep(node.target)
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
node.edgesOut.forEach(({peer, optional, dev, to}) => {
|
|
@@ -71,6 +75,14 @@ const calcDepFlagsStep = (node) => {
|
|
|
71
75
|
return node
|
|
72
76
|
}
|
|
73
77
|
|
|
78
|
+
const resetParents = (node, flag) => {
|
|
79
|
+
if (node[flag])
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
for (let p = node; p && (p === node || p[flag]); p = p.resolveParent)
|
|
83
|
+
p[flag] = false
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
// typically a short walk, since it only traverses deps that
|
|
75
87
|
// have the flag set.
|
|
76
88
|
const unsetFlag = (node, flag) => {
|
|
@@ -80,10 +92,10 @@ const unsetFlag = (node, flag) => {
|
|
|
80
92
|
tree: node,
|
|
81
93
|
visit: node => {
|
|
82
94
|
node.extraneous = node[flag] = false
|
|
83
|
-
if (node.
|
|
95
|
+
if (node.isLink)
|
|
84
96
|
node.target.extraneous = node.target[flag] = false
|
|
85
97
|
},
|
|
86
|
-
getChildren: node => [...
|
|
98
|
+
getChildren: node => [...node.target.edgesOut.values()]
|
|
87
99
|
.filter(edge => edge.to && edge.to[flag] &&
|
|
88
100
|
(flag !== 'peer' && edge.type === 'peer' || edge.type === 'prod'))
|
|
89
101
|
.map(edge => edge.to),
|
package/lib/diff.js
CHANGED
|
@@ -45,8 +45,7 @@ class Diff {
|
|
|
45
45
|
const { root } = filterNode
|
|
46
46
|
if (root !== ideal && root !== actual)
|
|
47
47
|
throw new Error('invalid filterNode: outside idealTree/actualTree')
|
|
48
|
-
const
|
|
49
|
-
const rootTarget = target || root
|
|
48
|
+
const rootTarget = root.target
|
|
50
49
|
const edge = [...rootTarget.edgesOut.values()].filter(e => {
|
|
51
50
|
return e.to && (e.to === filterNode || e.to.target === filterNode)
|
|
52
51
|
})[0]
|
|
@@ -56,8 +55,7 @@ class Diff {
|
|
|
56
55
|
filterSet.add(actual)
|
|
57
56
|
if (edge && edge.to) {
|
|
58
57
|
filterSet.add(edge.to)
|
|
59
|
-
|
|
60
|
-
filterSet.add(edge.to.target)
|
|
58
|
+
filterSet.add(edge.to.target)
|
|
61
59
|
}
|
|
62
60
|
filterSet.add(filterNode)
|
|
63
61
|
|
|
@@ -65,7 +63,7 @@ class Diff {
|
|
|
65
63
|
tree: filterNode,
|
|
66
64
|
visit: node => filterSet.add(node),
|
|
67
65
|
getChildren: node => {
|
|
68
|
-
node = node.target
|
|
66
|
+
node = node.target
|
|
69
67
|
const loc = node.location
|
|
70
68
|
const idealNode = ideal.inventory.get(loc)
|
|
71
69
|
const ideals = !idealNode ? []
|
|
@@ -145,9 +143,9 @@ const allChildren = node => {
|
|
|
145
143
|
if (!node)
|
|
146
144
|
return new Map()
|
|
147
145
|
|
|
148
|
-
// if the node is
|
|
146
|
+
// if the node is root, and also a link, then what we really
|
|
149
147
|
// want is to traverse the target's children
|
|
150
|
-
if (node.
|
|
148
|
+
if (node.isRoot && node.isLink)
|
|
151
149
|
return allChildren(node.target)
|
|
152
150
|
|
|
153
151
|
const kids = new Map()
|
package/lib/inventory.js
CHANGED
|
@@ -7,6 +7,20 @@ const _index = Symbol('_index')
|
|
|
7
7
|
const defaultKeys = ['name', 'license', 'funding', 'realpath', 'packageName']
|
|
8
8
|
const { hasOwnProperty } = Object.prototype
|
|
9
9
|
const debug = require('./debug.js')
|
|
10
|
+
|
|
11
|
+
// handling for the outdated "licenses" array, just pick the first one
|
|
12
|
+
// also support the alternative spelling "licence"
|
|
13
|
+
const getLicense = pkg => {
|
|
14
|
+
if (pkg) {
|
|
15
|
+
const lic = pkg.license || pkg.licence
|
|
16
|
+
if (lic)
|
|
17
|
+
return lic
|
|
18
|
+
const lics = pkg.licenses || pkg.licences
|
|
19
|
+
if (Array.isArray(lics))
|
|
20
|
+
return lics[0]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
10
24
|
class Inventory extends Map {
|
|
11
25
|
constructor (opt = {}) {
|
|
12
26
|
const { primary, keys } = opt
|
|
@@ -56,7 +70,9 @@ class Inventory extends Map {
|
|
|
56
70
|
for (const [key, map] of this[_index].entries()) {
|
|
57
71
|
// if the node has the value, but it's false, then use that
|
|
58
72
|
const val_ = hasOwnProperty.call(node, key) ? node[key]
|
|
59
|
-
:
|
|
73
|
+
: key === 'license' ? getLicense(node.package)
|
|
74
|
+
: node[key] ? node[key]
|
|
75
|
+
: node.package && node.package[key]
|
|
60
76
|
const val = typeof val_ === 'string' ? val_
|
|
61
77
|
: !val_ || typeof val_ !== 'object' ? val_
|
|
62
78
|
: key === 'license' ? val_.type
|
package/lib/node.js
CHANGED
|
@@ -409,7 +409,7 @@ class Node {
|
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
isDescendantOf (node) {
|
|
412
|
-
for (let p = this; p; p = p.
|
|
412
|
+
for (let p = this; p; p = p.resolveParent) {
|
|
413
413
|
if (p === node)
|
|
414
414
|
return true
|
|
415
415
|
}
|
|
@@ -547,6 +547,8 @@ class Node {
|
|
|
547
547
|
|
|
548
548
|
// try to find our parent/fsParent in the new root inventory
|
|
549
549
|
for (const p of walkUp(dirname(this.path))) {
|
|
550
|
+
if (p === this.path)
|
|
551
|
+
continue
|
|
550
552
|
const ploc = relpath(root.realpath, p)
|
|
551
553
|
const parent = root.inventory.get(ploc)
|
|
552
554
|
if (parent) {
|
|
@@ -647,7 +649,7 @@ class Node {
|
|
|
647
649
|
})
|
|
648
650
|
|
|
649
651
|
if (this.isLink) {
|
|
650
|
-
const target = node.target
|
|
652
|
+
const target = node.target
|
|
651
653
|
this[_target] = target
|
|
652
654
|
this[_package] = target.package
|
|
653
655
|
target.linksIn.add(this)
|
|
@@ -783,7 +785,13 @@ class Node {
|
|
|
783
785
|
}
|
|
784
786
|
|
|
785
787
|
get fsParent () {
|
|
786
|
-
|
|
788
|
+
const parent = this[_fsParent]
|
|
789
|
+
/* istanbul ignore next - should be impossible */
|
|
790
|
+
debug(() => {
|
|
791
|
+
if (parent === this)
|
|
792
|
+
throw new Error('node set to its own fsParent')
|
|
793
|
+
})
|
|
794
|
+
return parent
|
|
787
795
|
}
|
|
788
796
|
|
|
789
797
|
set fsParent (fsParent) {
|
|
@@ -1009,7 +1017,13 @@ class Node {
|
|
|
1009
1017
|
}
|
|
1010
1018
|
|
|
1011
1019
|
get parent () {
|
|
1012
|
-
|
|
1020
|
+
const parent = this[_parent]
|
|
1021
|
+
/* istanbul ignore next - should be impossible */
|
|
1022
|
+
debug(() => {
|
|
1023
|
+
if (parent === this)
|
|
1024
|
+
throw new Error('node set to its own parent')
|
|
1025
|
+
})
|
|
1026
|
+
return parent
|
|
1013
1027
|
}
|
|
1014
1028
|
|
|
1015
1029
|
// This setter keeps everything in order when we move a node from
|
|
@@ -1160,7 +1174,7 @@ class Node {
|
|
|
1160
1174
|
}
|
|
1161
1175
|
|
|
1162
1176
|
get target () {
|
|
1163
|
-
return
|
|
1177
|
+
return this
|
|
1164
1178
|
}
|
|
1165
1179
|
|
|
1166
1180
|
set target (n) {
|
|
@@ -1183,6 +1197,14 @@ class Node {
|
|
|
1183
1197
|
return this.isTop ? this : this.parent.top
|
|
1184
1198
|
}
|
|
1185
1199
|
|
|
1200
|
+
get isFsTop () {
|
|
1201
|
+
return !this.fsParent
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
get fsTop () {
|
|
1205
|
+
return this.isFsTop ? this : this.fsParent.fsTop
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1186
1208
|
get resolveParent () {
|
|
1187
1209
|
return this.parent || this.fsParent
|
|
1188
1210
|
}
|
package/lib/shrinkwrap.js
CHANGED
|
@@ -32,7 +32,7 @@ const mismatch = (a, b) => a && b && a !== b
|
|
|
32
32
|
// After calling this.commit(), any nodes not present in the tree will have
|
|
33
33
|
// been removed from the shrinkwrap data as well.
|
|
34
34
|
|
|
35
|
-
const procLog = require('
|
|
35
|
+
const procLog = require('proc-log')
|
|
36
36
|
const YarnLock = require('./yarn-lock.js')
|
|
37
37
|
const {promisify} = require('util')
|
|
38
38
|
const rimraf = promisify(require('rimraf'))
|
|
@@ -349,6 +349,7 @@ class Shrinkwrap {
|
|
|
349
349
|
reset () {
|
|
350
350
|
this.tree = null
|
|
351
351
|
this[_awaitingUpdate] = new Map()
|
|
352
|
+
this.originalLockfileVersion = lockfileVersion
|
|
352
353
|
this.data = {
|
|
353
354
|
lockfileVersion,
|
|
354
355
|
requires: true,
|
|
@@ -801,7 +802,7 @@ class Shrinkwrap {
|
|
|
801
802
|
if (this.tree) {
|
|
802
803
|
if (this.yarnLock)
|
|
803
804
|
this.yarnLock.fromTree(this.tree)
|
|
804
|
-
const root = Shrinkwrap.metaFromNode(this.tree.target
|
|
805
|
+
const root = Shrinkwrap.metaFromNode(this.tree.target, this.path)
|
|
805
806
|
this.data.packages = {}
|
|
806
807
|
if (Object.keys(root).length)
|
|
807
808
|
this.data.packages[''] = root
|
|
@@ -863,7 +864,7 @@ class Shrinkwrap {
|
|
|
863
864
|
const spec = !edge ? rSpec
|
|
864
865
|
: npa.resolve(node.name, edge.spec, edge.from.realpath)
|
|
865
866
|
|
|
866
|
-
if (node.
|
|
867
|
+
if (node.isLink)
|
|
867
868
|
lock.version = `file:${relpath(this.path, node.realpath)}`
|
|
868
869
|
else if (spec && (spec.type === 'file' || spec.type === 'remote'))
|
|
869
870
|
lock.version = spec.saveSpec
|
|
@@ -887,7 +888,7 @@ class Shrinkwrap {
|
|
|
887
888
|
// when we didn't resolve to git, file, or dir, and didn't request
|
|
888
889
|
// git, file, dir, or remote, then the resolved value is necessary.
|
|
889
890
|
if (node.resolved &&
|
|
890
|
-
!node.
|
|
891
|
+
!node.isLink &&
|
|
891
892
|
rSpec.type !== 'git' &&
|
|
892
893
|
rSpec.type !== 'file' &&
|
|
893
894
|
rSpec.type !== 'directory' &&
|
|
@@ -916,7 +917,7 @@ class Shrinkwrap {
|
|
|
916
917
|
lock.optional = true
|
|
917
918
|
}
|
|
918
919
|
|
|
919
|
-
const depender = node.target
|
|
920
|
+
const depender = node.target
|
|
920
921
|
if (depender.edgesOut.size > 0) {
|
|
921
922
|
if (node !== this.tree) {
|
|
922
923
|
lock.requires = [...depender.edgesOut.entries()].reduce((set, [k, v]) => {
|
|
@@ -941,7 +942,7 @@ class Shrinkwrap {
|
|
|
941
942
|
}
|
|
942
943
|
|
|
943
944
|
// now we walk the children, putting them in the 'dependencies' object
|
|
944
|
-
const {children} = node.target
|
|
945
|
+
const {children} = node.target
|
|
945
946
|
if (!children.size)
|
|
946
947
|
delete lock.dependencies
|
|
947
948
|
else {
|
package/lib/tracker.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npmcli/arborist",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Manage node_modules trees",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@npmcli/installed-package-contents": "^1.0.7",
|
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
"@npmcli/move-file": "^1.1.0",
|
|
10
10
|
"@npmcli/name-from-folder": "^1.0.1",
|
|
11
11
|
"@npmcli/node-gyp": "^1.0.1",
|
|
12
|
+
"@npmcli/package-json": "^1.0.1",
|
|
12
13
|
"@npmcli/run-script": "^1.8.2",
|
|
13
14
|
"bin-links": "^2.2.1",
|
|
14
15
|
"cacache": "^15.0.3",
|
|
15
16
|
"common-ancestor-path": "^1.0.1",
|
|
16
17
|
"json-parse-even-better-errors": "^2.3.1",
|
|
17
18
|
"json-stringify-nice": "^1.1.4",
|
|
19
|
+
"mkdirp": "^1.0.4",
|
|
18
20
|
"mkdirp-infer-owner": "^2.0.0",
|
|
19
21
|
"npm-install-checks": "^4.0.0",
|
|
20
22
|
"npm-package-arg": "^8.1.0",
|
|
@@ -22,11 +24,14 @@
|
|
|
22
24
|
"npm-registry-fetch": "^11.0.0",
|
|
23
25
|
"pacote": "^11.2.6",
|
|
24
26
|
"parse-conflict-json": "^1.1.1",
|
|
27
|
+
"proc-log": "^1.0.0",
|
|
25
28
|
"promise-all-reject-late": "^1.0.0",
|
|
26
29
|
"promise-call-limit": "^1.0.1",
|
|
27
30
|
"read-package-json-fast": "^2.0.2",
|
|
28
31
|
"readdir-scoped-modules": "^1.1.0",
|
|
32
|
+
"rimraf": "^3.0.2",
|
|
29
33
|
"semver": "^7.3.5",
|
|
34
|
+
"ssri": "^8.0.1",
|
|
30
35
|
"tar": "^6.1.0",
|
|
31
36
|
"treeverse": "^1.0.4",
|
|
32
37
|
"walk-up-path": "^1.0.0"
|
package/lib/proc-log.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// default logger.
|
|
2
|
-
// emits 'log' events on the process
|
|
3
|
-
const LEVELS = [
|
|
4
|
-
'notice',
|
|
5
|
-
'error',
|
|
6
|
-
'warn',
|
|
7
|
-
'info',
|
|
8
|
-
'verbose',
|
|
9
|
-
'http',
|
|
10
|
-
'silly',
|
|
11
|
-
'pause',
|
|
12
|
-
'resume',
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
const log = level => (...args) => process.emit('log', level, ...args)
|
|
16
|
-
|
|
17
|
-
const logger = {}
|
|
18
|
-
for (const level of LEVELS)
|
|
19
|
-
logger[level] = log(level)
|
|
20
|
-
|
|
21
|
-
module.exports = logger
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const promisify = require('util').promisify
|
|
3
|
-
const readFile = promisify(fs.readFile)
|
|
4
|
-
const writeFile = promisify(fs.writeFile)
|
|
5
|
-
const {resolve} = require('path')
|
|
6
|
-
|
|
7
|
-
const parseJSON = require('json-parse-even-better-errors')
|
|
8
|
-
|
|
9
|
-
const depTypes = new Set([
|
|
10
|
-
'dependencies',
|
|
11
|
-
'optionalDependencies',
|
|
12
|
-
'devDependencies',
|
|
13
|
-
'peerDependencies',
|
|
14
|
-
])
|
|
15
|
-
|
|
16
|
-
// sort alphabetically all types of deps for a given package
|
|
17
|
-
const orderDeps = (pkg) => {
|
|
18
|
-
for (const type of depTypes) {
|
|
19
|
-
if (pkg && pkg[type]) {
|
|
20
|
-
pkg[type] = Object.keys(pkg[type])
|
|
21
|
-
.sort((a, b) => a.localeCompare(b, 'en'))
|
|
22
|
-
.reduce((res, key) => {
|
|
23
|
-
res[key] = pkg[type][key]
|
|
24
|
-
return res
|
|
25
|
-
}, {})
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return pkg
|
|
29
|
-
}
|
|
30
|
-
const parseJsonSafe = json => {
|
|
31
|
-
try {
|
|
32
|
-
return parseJSON(json)
|
|
33
|
-
} catch (er) {
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const updateRootPackageJson = async tree => {
|
|
39
|
-
const filename = resolve(tree.path, 'package.json')
|
|
40
|
-
const originalJson = await readFile(filename, 'utf8').catch(() => null)
|
|
41
|
-
const originalContent = parseJsonSafe(originalJson)
|
|
42
|
-
|
|
43
|
-
const depsData = orderDeps({
|
|
44
|
-
...tree.package,
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
// optionalDependencies don't need to be repeated in two places
|
|
48
|
-
if (depsData.dependencies) {
|
|
49
|
-
if (depsData.optionalDependencies) {
|
|
50
|
-
for (const name of Object.keys(depsData.optionalDependencies))
|
|
51
|
-
delete depsData.dependencies[name]
|
|
52
|
-
}
|
|
53
|
-
if (Object.keys(depsData.dependencies).length === 0)
|
|
54
|
-
delete depsData.dependencies
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// if there's no package.json, just use internal pkg info as source of truth
|
|
58
|
-
// clone the object though, so we can still refer to what it originally was
|
|
59
|
-
const packageJsonContent = !originalContent ? depsData
|
|
60
|
-
: Object.assign({}, originalContent)
|
|
61
|
-
|
|
62
|
-
// loop through all types of dependencies and update package json content
|
|
63
|
-
for (const type of depTypes)
|
|
64
|
-
packageJsonContent[type] = depsData[type]
|
|
65
|
-
|
|
66
|
-
// if original package.json had dep in peerDeps AND deps, preserve that.
|
|
67
|
-
const { dependencies: origProd, peerDependencies: origPeer } =
|
|
68
|
-
originalContent || {}
|
|
69
|
-
const { peerDependencies: newPeer } = packageJsonContent
|
|
70
|
-
if (origProd && origPeer && newPeer) {
|
|
71
|
-
// we have original prod/peer deps, and new peer deps
|
|
72
|
-
// copy over any that were in both in the original
|
|
73
|
-
for (const name of Object.keys(origPeer)) {
|
|
74
|
-
if (origProd[name] !== undefined && newPeer[name] !== undefined) {
|
|
75
|
-
packageJsonContent.dependencies = packageJsonContent.dependencies || {}
|
|
76
|
-
packageJsonContent.dependencies[name] = newPeer[name]
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// format content
|
|
82
|
-
const {
|
|
83
|
-
[Symbol.for('indent')]: indent,
|
|
84
|
-
[Symbol.for('newline')]: newline,
|
|
85
|
-
} = tree.package
|
|
86
|
-
const format = indent === undefined ? ' ' : indent
|
|
87
|
-
const eol = newline === undefined ? '\n' : newline
|
|
88
|
-
const content = (JSON.stringify(packageJsonContent, null, format) + '\n')
|
|
89
|
-
.replace(/\n/g, eol)
|
|
90
|
-
|
|
91
|
-
if (content !== originalJson)
|
|
92
|
-
return writeFile(filename, content)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
module.exports = updateRootPackageJson
|