@npmcli/arborist 2.7.1 → 2.8.3
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/actual.js +4 -2
- package/bin/audit.js +12 -6
- package/bin/dedupe.js +49 -0
- package/bin/funding.js +4 -2
- package/bin/ideal.js +2 -1
- package/bin/lib/logging.js +4 -3
- package/bin/lib/options.js +14 -12
- package/bin/lib/timers.js +6 -3
- package/bin/license.js +9 -5
- package/bin/prune.js +6 -3
- package/bin/reify.js +6 -3
- package/bin/virtual.js +4 -2
- package/lib/add-rm-pkg-deps.js +25 -14
- package/lib/arborist/audit.js +2 -1
- package/lib/arborist/build-ideal-tree.js +246 -757
- package/lib/arborist/deduper.js +2 -1
- package/lib/arborist/index.js +8 -4
- package/lib/arborist/load-actual.js +32 -15
- package/lib/arborist/load-virtual.js +34 -18
- package/lib/arborist/load-workspaces.js +4 -2
- package/lib/arborist/rebuild.js +31 -16
- package/lib/arborist/reify.js +332 -119
- package/lib/audit-report.js +42 -22
- package/lib/calc-dep-flags.js +18 -9
- package/lib/can-place-dep.js +430 -0
- package/lib/case-insensitive-map.js +50 -0
- package/lib/consistent-resolve.js +2 -1
- package/lib/deepest-nesting-target.js +18 -0
- package/lib/dep-valid.js +8 -4
- package/lib/diff.js +74 -22
- package/lib/edge.js +29 -14
- package/lib/gather-dep-set.js +2 -1
- package/lib/inventory.js +12 -6
- package/lib/link.js +14 -9
- package/lib/node.js +269 -118
- package/lib/optional-set.js +4 -2
- package/lib/peer-entry-sets.js +77 -0
- package/lib/place-dep.js +578 -0
- package/lib/printable.js +48 -18
- package/lib/realpath.js +12 -6
- package/lib/shrinkwrap.js +168 -91
- package/lib/signal-handling.js +6 -3
- package/lib/spec-from-lock.js +7 -4
- package/lib/tracker.js +24 -18
- package/lib/tree-check.js +12 -6
- package/lib/version-from-tgz.js +4 -2
- package/lib/vuln.js +28 -16
- package/lib/yarn-lock.js +27 -15
- package/package.json +9 -13
- package/lib/peer-set.js +0 -25
package/lib/shrinkwrap.js
CHANGED
|
@@ -47,8 +47,9 @@ const readlink = promisify(fs.readlink)
|
|
|
47
47
|
const lstat = promisify(fs.lstat)
|
|
48
48
|
/* istanbul ignore next - version specific polyfill */
|
|
49
49
|
const readdir = async (path, opt) => {
|
|
50
|
-
if (!opt || !opt.withFileTypes)
|
|
50
|
+
if (!opt || !opt.withFileTypes) {
|
|
51
51
|
return readdir_(path, opt)
|
|
52
|
+
}
|
|
52
53
|
const ents = await readdir_(path, opt)
|
|
53
54
|
if (typeof ents[0] === 'string') {
|
|
54
55
|
return Promise.all(ents.map(async ent => {
|
|
@@ -97,20 +98,22 @@ const consistentResolve = require('./consistent-resolve.js')
|
|
|
97
98
|
const maybeReadFile = file => {
|
|
98
99
|
return readFile(file, 'utf8').then(d => d, er => {
|
|
99
100
|
/* istanbul ignore else - can't test without breaking module itself */
|
|
100
|
-
if (er.code === 'ENOENT')
|
|
101
|
+
if (er.code === 'ENOENT') {
|
|
101
102
|
return ''
|
|
102
|
-
else
|
|
103
|
+
} else {
|
|
103
104
|
throw er
|
|
105
|
+
}
|
|
104
106
|
})
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
const maybeStatFile = file => {
|
|
108
110
|
return stat(file).then(st => st.isFile(), er => {
|
|
109
111
|
/* istanbul ignore else - can't test without breaking module itself */
|
|
110
|
-
if (er.code === 'ENOENT')
|
|
112
|
+
if (er.code === 'ENOENT') {
|
|
111
113
|
return null
|
|
112
|
-
else
|
|
114
|
+
} else {
|
|
113
115
|
throw er
|
|
116
|
+
}
|
|
114
117
|
})
|
|
115
118
|
}
|
|
116
119
|
|
|
@@ -163,13 +166,16 @@ const assertNoNewer = async (path, data, lockTime, dir = path, seen = null) => {
|
|
|
163
166
|
const rel = relpath(path, dir)
|
|
164
167
|
if (dir !== path) {
|
|
165
168
|
const dirTime = (await stat(dir)).mtime
|
|
166
|
-
if (dirTime > lockTime)
|
|
169
|
+
if (dirTime > lockTime) {
|
|
167
170
|
throw 'out of date, updated: ' + rel
|
|
168
|
-
|
|
171
|
+
}
|
|
172
|
+
if (!isScope && !isNM && !data.packages[rel]) {
|
|
169
173
|
throw 'missing from lockfile: ' + rel
|
|
174
|
+
}
|
|
170
175
|
seen.add(rel)
|
|
171
|
-
} else
|
|
176
|
+
} else {
|
|
172
177
|
seen = new Set([rel])
|
|
178
|
+
}
|
|
173
179
|
|
|
174
180
|
const parent = isParent ? dir : resolve(dir, 'node_modules')
|
|
175
181
|
const children = dir === path
|
|
@@ -179,24 +185,29 @@ const assertNoNewer = async (path, data, lockTime, dir = path, seen = null) => {
|
|
|
179
185
|
return children.catch(() => [])
|
|
180
186
|
.then(ents => Promise.all(ents.map(async ent => {
|
|
181
187
|
const child = resolve(parent, ent.name)
|
|
182
|
-
if (ent.isDirectory() && !/^\./.test(ent.name))
|
|
188
|
+
if (ent.isDirectory() && !/^\./.test(ent.name)) {
|
|
183
189
|
await assertNoNewer(path, data, lockTime, child, seen)
|
|
184
|
-
else if (ent.isSymbolicLink()) {
|
|
190
|
+
} else if (ent.isSymbolicLink()) {
|
|
185
191
|
const target = resolve(parent, await readlink(child))
|
|
186
|
-
const tstat = await stat(target).catch(
|
|
192
|
+
const tstat = await stat(target).catch(
|
|
193
|
+
/* istanbul ignore next - windows */ () => null)
|
|
187
194
|
seen.add(relpath(path, child))
|
|
188
|
-
|
|
195
|
+
/* istanbul ignore next - windows cannot do this */
|
|
196
|
+
if (tstat && tstat.isDirectory() && !seen.has(relpath(path, target))) {
|
|
189
197
|
await assertNoNewer(path, data, lockTime, target, seen)
|
|
198
|
+
}
|
|
190
199
|
}
|
|
191
200
|
})))
|
|
192
201
|
.then(() => {
|
|
193
|
-
if (dir !== path)
|
|
202
|
+
if (dir !== path) {
|
|
194
203
|
return
|
|
204
|
+
}
|
|
195
205
|
|
|
196
206
|
// assert that all the entries in the lockfile were seen
|
|
197
207
|
for (const loc of new Set(Object.keys(data.packages))) {
|
|
198
|
-
if (!seen.has(loc))
|
|
208
|
+
if (!seen.has(loc)) {
|
|
199
209
|
throw 'missing from node_modules: ' + loc
|
|
210
|
+
}
|
|
200
211
|
}
|
|
201
212
|
})
|
|
202
213
|
}
|
|
@@ -250,37 +261,48 @@ class Shrinkwrap {
|
|
|
250
261
|
const meta = {}
|
|
251
262
|
pkgMetaKeys.forEach(key => {
|
|
252
263
|
const val = metaFieldFromPkg(node.package, key)
|
|
253
|
-
if (val)
|
|
264
|
+
if (val) {
|
|
254
265
|
meta[key.replace(/^_/, '')] = val
|
|
266
|
+
}
|
|
255
267
|
})
|
|
256
|
-
// we only include name if different from the node path name
|
|
268
|
+
// we only include name if different from the node path name, and for the
|
|
269
|
+
// root to help prevent churn based on the name of the directory the
|
|
270
|
+
// project is in
|
|
257
271
|
const pname = node.packageName
|
|
258
|
-
if (pname && pname !== node.name)
|
|
272
|
+
if (pname && (node === node.root || pname !== node.name)) {
|
|
259
273
|
meta.name = pname
|
|
274
|
+
}
|
|
260
275
|
|
|
261
|
-
if (node.isTop && node.package.devDependencies)
|
|
276
|
+
if (node.isTop && node.package.devDependencies) {
|
|
262
277
|
meta.devDependencies = node.package.devDependencies
|
|
278
|
+
}
|
|
263
279
|
|
|
264
280
|
nodeMetaKeys.forEach(key => {
|
|
265
|
-
if (node[key])
|
|
281
|
+
if (node[key]) {
|
|
266
282
|
meta[key] = node[key]
|
|
283
|
+
}
|
|
267
284
|
})
|
|
268
285
|
|
|
269
286
|
const resolved = consistentResolve(node.resolved, node.path, path, true)
|
|
270
|
-
if (resolved)
|
|
287
|
+
if (resolved) {
|
|
271
288
|
meta.resolved = resolved
|
|
289
|
+
}
|
|
272
290
|
|
|
273
|
-
if (node.extraneous)
|
|
291
|
+
if (node.extraneous) {
|
|
274
292
|
meta.extraneous = true
|
|
275
|
-
else {
|
|
276
|
-
if (node.peer)
|
|
293
|
+
} else {
|
|
294
|
+
if (node.peer) {
|
|
277
295
|
meta.peer = true
|
|
278
|
-
|
|
296
|
+
}
|
|
297
|
+
if (node.dev) {
|
|
279
298
|
meta.dev = true
|
|
280
|
-
|
|
299
|
+
}
|
|
300
|
+
if (node.optional) {
|
|
281
301
|
meta.optional = true
|
|
282
|
-
|
|
302
|
+
}
|
|
303
|
+
if (node.devOptional && !node.dev && !node.optional) {
|
|
283
304
|
meta.devOptional = true
|
|
305
|
+
}
|
|
284
306
|
}
|
|
285
307
|
return meta
|
|
286
308
|
}
|
|
@@ -419,8 +441,9 @@ class Shrinkwrap {
|
|
|
419
441
|
this.indent = indent !== undefined ? indent : this.indent
|
|
420
442
|
this.newline = newline !== undefined ? newline : this.newline
|
|
421
443
|
|
|
422
|
-
if (!this.hiddenLockfile || !data.packages)
|
|
444
|
+
if (!this.hiddenLockfile || !data.packages) {
|
|
423
445
|
return data
|
|
446
|
+
}
|
|
424
447
|
|
|
425
448
|
// add a few ms just to account for jitter
|
|
426
449
|
const lockTime = +(await stat(this.filename)).mtime + 10
|
|
@@ -463,8 +486,9 @@ class Shrinkwrap {
|
|
|
463
486
|
// migrate a v1 package lock to the new format.
|
|
464
487
|
const meta = this[_metaFromLock](location, name, lock)
|
|
465
488
|
// dependencies nested under a link are actually under the link target
|
|
466
|
-
if (meta.link)
|
|
489
|
+
if (meta.link) {
|
|
467
490
|
location = meta.resolved
|
|
491
|
+
}
|
|
468
492
|
if (lock.dependencies) {
|
|
469
493
|
for (const [name, dep] of Object.entries(lock.dependencies)) {
|
|
470
494
|
const loc = location + (location ? '/' : '') + 'node_modules/' + name
|
|
@@ -484,13 +508,15 @@ class Shrinkwrap {
|
|
|
484
508
|
pkgMetaKeys.forEach(key => {
|
|
485
509
|
const val = metaFieldFromPkg(pkg, key)
|
|
486
510
|
const k = key.replace(/^_/, '')
|
|
487
|
-
if (val)
|
|
511
|
+
if (val) {
|
|
488
512
|
root[k] = val
|
|
513
|
+
}
|
|
489
514
|
})
|
|
490
515
|
|
|
491
516
|
for (const [loc, meta] of Object.entries(this.data.packages)) {
|
|
492
|
-
if (!meta.requires || !loc)
|
|
517
|
+
if (!meta.requires || !loc) {
|
|
493
518
|
continue
|
|
519
|
+
}
|
|
494
520
|
|
|
495
521
|
// resolve each require to a meta entry
|
|
496
522
|
// if this node isn't optional, but the dep is, then it's an optionalDep
|
|
@@ -519,27 +545,33 @@ class Shrinkwrap {
|
|
|
519
545
|
[_resolveMetaNode] (loc, name) {
|
|
520
546
|
for (let path = loc; true; path = path.replace(/(^|\/)[^/]*$/, '')) {
|
|
521
547
|
const check = `${path}${path ? '/' : ''}node_modules/${name}`
|
|
522
|
-
if (this.data.packages[check])
|
|
548
|
+
if (this.data.packages[check]) {
|
|
523
549
|
return this.data.packages[check]
|
|
550
|
+
}
|
|
524
551
|
|
|
525
|
-
if (!path)
|
|
552
|
+
if (!path) {
|
|
526
553
|
break
|
|
554
|
+
}
|
|
527
555
|
}
|
|
528
556
|
return null
|
|
529
557
|
}
|
|
530
558
|
|
|
531
559
|
[_lockFromLoc] (lock, path, i = 0) {
|
|
532
|
-
if (!lock)
|
|
560
|
+
if (!lock) {
|
|
533
561
|
return null
|
|
562
|
+
}
|
|
534
563
|
|
|
535
|
-
if (path[i] === '')
|
|
564
|
+
if (path[i] === '') {
|
|
536
565
|
i++
|
|
566
|
+
}
|
|
537
567
|
|
|
538
|
-
if (i >= path.length)
|
|
568
|
+
if (i >= path.length) {
|
|
539
569
|
return lock
|
|
570
|
+
}
|
|
540
571
|
|
|
541
|
-
if (!lock.dependencies)
|
|
572
|
+
if (!lock.dependencies) {
|
|
542
573
|
return null
|
|
574
|
+
}
|
|
543
575
|
|
|
544
576
|
return this[_lockFromLoc](lock.dependencies[path[i]], path, i + 1)
|
|
545
577
|
}
|
|
@@ -551,8 +583,9 @@ class Shrinkwrap {
|
|
|
551
583
|
}
|
|
552
584
|
|
|
553
585
|
delete (nodePath) {
|
|
554
|
-
if (!this.data)
|
|
586
|
+
if (!this.data) {
|
|
555
587
|
throw new Error('run load() before getting or setting data')
|
|
588
|
+
}
|
|
556
589
|
const location = this[_pathToLoc](nodePath)
|
|
557
590
|
this[_awaitingUpdate].delete(location)
|
|
558
591
|
|
|
@@ -560,22 +593,26 @@ class Shrinkwrap {
|
|
|
560
593
|
const path = location.split(/(?:^|\/)node_modules\//)
|
|
561
594
|
const name = path.pop()
|
|
562
595
|
const pLock = this[_lockFromLoc](this.data, path)
|
|
563
|
-
if (pLock && pLock.dependencies)
|
|
596
|
+
if (pLock && pLock.dependencies) {
|
|
564
597
|
delete pLock.dependencies[name]
|
|
598
|
+
}
|
|
565
599
|
}
|
|
566
600
|
|
|
567
601
|
get (nodePath) {
|
|
568
|
-
if (!this.data)
|
|
602
|
+
if (!this.data) {
|
|
569
603
|
throw new Error('run load() before getting or setting data')
|
|
604
|
+
}
|
|
570
605
|
|
|
571
606
|
const location = this[_pathToLoc](nodePath)
|
|
572
|
-
if (this[_awaitingUpdate].has(location))
|
|
607
|
+
if (this[_awaitingUpdate].has(location)) {
|
|
573
608
|
this[_updateWaitingNode](location)
|
|
609
|
+
}
|
|
574
610
|
|
|
575
611
|
// first try to get from the newer spot, which we know has
|
|
576
612
|
// all the things we need.
|
|
577
|
-
if (this.data.packages[location])
|
|
613
|
+
if (this.data.packages[location]) {
|
|
578
614
|
return this.data.packages[location]
|
|
615
|
+
}
|
|
579
616
|
|
|
580
617
|
// otherwise, fall back to the legacy metadata, and hope for the best
|
|
581
618
|
// get the node in the shrinkwrap corresponding to this spot
|
|
@@ -591,8 +628,9 @@ class Shrinkwrap {
|
|
|
591
628
|
// from a lockfile which may be outdated or incomplete. Since v1
|
|
592
629
|
// lockfiles used the "version" field to contain a variety of
|
|
593
630
|
// different possible types of data, this gets a little complicated.
|
|
594
|
-
if (!lock)
|
|
631
|
+
if (!lock) {
|
|
595
632
|
return {}
|
|
633
|
+
}
|
|
596
634
|
|
|
597
635
|
// try to figure out a npm-package-arg spec from the lockfile entry
|
|
598
636
|
// This will return null if we could not get anything valid out of it.
|
|
@@ -609,29 +647,35 @@ class Shrinkwrap {
|
|
|
609
647
|
}
|
|
610
648
|
// also save the link target, omitting version since we don't know
|
|
611
649
|
// what it is, but we know it isn't a link to itself!
|
|
612
|
-
if (!this.data.packages[target])
|
|
650
|
+
if (!this.data.packages[target]) {
|
|
613
651
|
this[_metaFromLock](target, name, { ...lock, version: null })
|
|
652
|
+
}
|
|
614
653
|
return this.data.packages[location]
|
|
615
654
|
}
|
|
616
655
|
|
|
617
656
|
const meta = {}
|
|
618
657
|
// when calling loadAll we'll change these into proper dep objects
|
|
619
|
-
if (lock.requires && typeof lock.requires === 'object')
|
|
658
|
+
if (lock.requires && typeof lock.requires === 'object') {
|
|
620
659
|
meta.requires = lock.requires
|
|
660
|
+
}
|
|
621
661
|
|
|
622
|
-
if (lock.optional)
|
|
662
|
+
if (lock.optional) {
|
|
623
663
|
meta.optional = true
|
|
624
|
-
|
|
664
|
+
}
|
|
665
|
+
if (lock.dev) {
|
|
625
666
|
meta.dev = true
|
|
667
|
+
}
|
|
626
668
|
|
|
627
669
|
// the root will typically have a name from the root project's
|
|
628
670
|
// package.json file.
|
|
629
|
-
if (location === '')
|
|
671
|
+
if (location === '') {
|
|
630
672
|
meta.name = lock.name
|
|
673
|
+
}
|
|
631
674
|
|
|
632
675
|
// if we have integrity, save it now.
|
|
633
|
-
if (lock.integrity)
|
|
676
|
+
if (lock.integrity) {
|
|
634
677
|
meta.integrity = lock.integrity
|
|
678
|
+
}
|
|
635
679
|
|
|
636
680
|
if (lock.version && !lock.integrity) {
|
|
637
681
|
// this is usually going to be a git url or symlink, but it could
|
|
@@ -664,12 +708,13 @@ class Shrinkwrap {
|
|
|
664
708
|
// have a fetchSpec equal to the fully resolved thing.
|
|
665
709
|
// Registry deps, we take what's in the lockfile.
|
|
666
710
|
if (lock.resolved || (spec.type && !spec.registry)) {
|
|
667
|
-
if (spec.registry)
|
|
711
|
+
if (spec.registry) {
|
|
668
712
|
meta.resolved = lock.resolved
|
|
669
|
-
else if (spec.type === 'file')
|
|
713
|
+
} else if (spec.type === 'file') {
|
|
670
714
|
meta.resolved = consistentResolve(spec, this.path, this.path, true)
|
|
671
|
-
else if (spec.fetchSpec)
|
|
715
|
+
} else if (spec.fetchSpec) {
|
|
672
716
|
meta.resolved = spec.fetchSpec
|
|
717
|
+
}
|
|
673
718
|
}
|
|
674
719
|
|
|
675
720
|
// at this point, if still we don't have a version, do our best to
|
|
@@ -681,32 +726,37 @@ class Shrinkwrap {
|
|
|
681
726
|
versionFromTgz(spec.name, meta.resolved)
|
|
682
727
|
if (fromTgz) {
|
|
683
728
|
meta.version = fromTgz.version
|
|
684
|
-
if (fromTgz.name !== name)
|
|
729
|
+
if (fromTgz.name !== name) {
|
|
685
730
|
meta.name = fromTgz.name
|
|
731
|
+
}
|
|
686
732
|
}
|
|
687
733
|
} else if (spec.type === 'alias') {
|
|
688
734
|
meta.name = spec.subSpec.name
|
|
689
735
|
meta.version = spec.subSpec.fetchSpec
|
|
690
|
-
} else if (spec.type === 'version')
|
|
736
|
+
} else if (spec.type === 'version') {
|
|
691
737
|
meta.version = spec.fetchSpec
|
|
738
|
+
}
|
|
692
739
|
// ok, I did my best! good luck!
|
|
693
740
|
}
|
|
694
741
|
|
|
695
|
-
if (lock.bundled)
|
|
742
|
+
if (lock.bundled) {
|
|
696
743
|
meta.inBundle = true
|
|
744
|
+
}
|
|
697
745
|
|
|
698
746
|
// save it for next time
|
|
699
747
|
return this.data.packages[location] = meta
|
|
700
748
|
}
|
|
701
749
|
|
|
702
750
|
add (node) {
|
|
703
|
-
if (!this.data)
|
|
751
|
+
if (!this.data) {
|
|
704
752
|
throw new Error('run load() before getting or setting data')
|
|
753
|
+
}
|
|
705
754
|
|
|
706
755
|
// will be actually updated on read
|
|
707
756
|
const loc = relpath(this.path, node.path)
|
|
708
|
-
if (node.path === this.path)
|
|
757
|
+
if (node.path === this.path) {
|
|
709
758
|
this.tree = node
|
|
759
|
+
}
|
|
710
760
|
|
|
711
761
|
// if we have metadata about this node, and it's a match, then
|
|
712
762
|
// try to decorate it.
|
|
@@ -754,18 +804,21 @@ class Shrinkwrap {
|
|
|
754
804
|
}
|
|
755
805
|
|
|
756
806
|
addEdge (edge) {
|
|
757
|
-
if (!this.yarnLock || !edge.valid)
|
|
807
|
+
if (!this.yarnLock || !edge.valid) {
|
|
758
808
|
return
|
|
809
|
+
}
|
|
759
810
|
|
|
760
811
|
const { to: node } = edge
|
|
761
812
|
|
|
762
813
|
// if it's already set up, nothing to do
|
|
763
|
-
if (node.resolved !== null && node.integrity !== null)
|
|
814
|
+
if (node.resolved !== null && node.integrity !== null) {
|
|
764
815
|
return
|
|
816
|
+
}
|
|
765
817
|
|
|
766
818
|
// if the yarn lock is empty, nothing to do
|
|
767
|
-
if (!this.yarnLock.entries || !this.yarnLock.entries.size)
|
|
819
|
+
if (!this.yarnLock.entries || !this.yarnLock.entries.size) {
|
|
768
820
|
return
|
|
821
|
+
}
|
|
769
822
|
|
|
770
823
|
// we relativize the path here because that's how it shows up in the lock
|
|
771
824
|
// XXX how is this different from pathFixed above??
|
|
@@ -779,11 +832,13 @@ class Shrinkwrap {
|
|
|
779
832
|
if (!entry ||
|
|
780
833
|
mismatch(node.version, entry.version) ||
|
|
781
834
|
mismatch(node.integrity, entry.integrity) ||
|
|
782
|
-
mismatch(pathFixed, entry.resolved))
|
|
835
|
+
mismatch(pathFixed, entry.resolved)) {
|
|
783
836
|
return
|
|
837
|
+
}
|
|
784
838
|
|
|
785
|
-
if (entry.resolved && yarnRegRe.test(entry.resolved) && spec.registry)
|
|
839
|
+
if (entry.resolved && yarnRegRe.test(entry.resolved) && spec.registry) {
|
|
786
840
|
entry.resolved = entry.resolved.replace(yarnRegRe, 'https://registry.npmjs.org/')
|
|
841
|
+
}
|
|
787
842
|
|
|
788
843
|
node.integrity = node.integrity || entry.integrity || null
|
|
789
844
|
node.resolved = node.resolved ||
|
|
@@ -800,30 +855,35 @@ class Shrinkwrap {
|
|
|
800
855
|
|
|
801
856
|
commit () {
|
|
802
857
|
if (this.tree) {
|
|
803
|
-
if (this.yarnLock)
|
|
858
|
+
if (this.yarnLock) {
|
|
804
859
|
this.yarnLock.fromTree(this.tree)
|
|
860
|
+
}
|
|
805
861
|
const root = Shrinkwrap.metaFromNode(this.tree.target, this.path)
|
|
806
862
|
this.data.packages = {}
|
|
807
|
-
if (Object.keys(root).length)
|
|
863
|
+
if (Object.keys(root).length) {
|
|
808
864
|
this.data.packages[''] = root
|
|
865
|
+
}
|
|
809
866
|
for (const node of this.tree.root.inventory.values()) {
|
|
810
867
|
// only way this.tree is not root is if the root is a link to it
|
|
811
|
-
if (node === this.tree || node.isRoot || node.location === '')
|
|
868
|
+
if (node === this.tree || node.isRoot || node.location === '') {
|
|
812
869
|
continue
|
|
870
|
+
}
|
|
813
871
|
const loc = relpath(this.path, node.path)
|
|
814
872
|
this.data.packages[loc] = Shrinkwrap.metaFromNode(node, this.path)
|
|
815
873
|
}
|
|
816
874
|
} else if (this[_awaitingUpdate].size > 0) {
|
|
817
|
-
for (const loc of this[_awaitingUpdate].keys())
|
|
875
|
+
for (const loc of this[_awaitingUpdate].keys()) {
|
|
818
876
|
this[_updateWaitingNode](loc)
|
|
877
|
+
}
|
|
819
878
|
}
|
|
820
879
|
|
|
821
880
|
// hidden lockfiles don't include legacy metadata or a root entry
|
|
822
881
|
if (this.hiddenLockfile) {
|
|
823
882
|
delete this.data.packages['']
|
|
824
883
|
delete this.data.dependencies
|
|
825
|
-
} else if (this.tree)
|
|
884
|
+
} else if (this.tree) {
|
|
826
885
|
this[_buildLegacyLockfile](this.tree, this.data)
|
|
886
|
+
}
|
|
827
887
|
|
|
828
888
|
return this.data
|
|
829
889
|
}
|
|
@@ -832,8 +892,9 @@ class Shrinkwrap {
|
|
|
832
892
|
if (node === this.tree) {
|
|
833
893
|
// the root node
|
|
834
894
|
lock.name = node.packageName || node.name
|
|
835
|
-
if (node.version)
|
|
895
|
+
if (node.version) {
|
|
836
896
|
lock.version = node.version
|
|
897
|
+
}
|
|
837
898
|
}
|
|
838
899
|
|
|
839
900
|
// npm v6 and before tracked 'from', meaning "the request that led
|
|
@@ -864,26 +925,29 @@ class Shrinkwrap {
|
|
|
864
925
|
const spec = !edge ? rSpec
|
|
865
926
|
: npa.resolve(node.name, edge.spec, edge.from.realpath)
|
|
866
927
|
|
|
867
|
-
if (node.isLink)
|
|
928
|
+
if (node.isLink) {
|
|
868
929
|
lock.version = `file:${relpath(this.path, node.realpath)}`
|
|
869
|
-
else if (spec && (spec.type === 'file' || spec.type === 'remote'))
|
|
930
|
+
} else if (spec && (spec.type === 'file' || spec.type === 'remote')) {
|
|
870
931
|
lock.version = spec.saveSpec
|
|
871
|
-
else if (spec && spec.type === 'git' || rSpec.type === 'git') {
|
|
932
|
+
} else if (spec && spec.type === 'git' || rSpec.type === 'git') {
|
|
872
933
|
lock.version = node.resolved
|
|
873
934
|
/* istanbul ignore else - don't think there are any cases where a git
|
|
874
935
|
* spec (or indeed, ANY npa spec) doesn't have a .raw member */
|
|
875
|
-
if (spec.raw)
|
|
936
|
+
if (spec.raw) {
|
|
876
937
|
lock.from = spec.raw
|
|
938
|
+
}
|
|
877
939
|
} else if (!node.isRoot &&
|
|
878
940
|
node.package &&
|
|
879
941
|
node.packageName &&
|
|
880
|
-
node.packageName !== node.name)
|
|
942
|
+
node.packageName !== node.name) {
|
|
881
943
|
lock.version = `npm:${node.packageName}@${node.version}`
|
|
882
|
-
else if (node.package && node.version)
|
|
944
|
+
} else if (node.package && node.version) {
|
|
883
945
|
lock.version = node.version
|
|
946
|
+
}
|
|
884
947
|
|
|
885
|
-
if (node.inDepBundle)
|
|
948
|
+
if (node.inDepBundle) {
|
|
886
949
|
lock.bundled = true
|
|
950
|
+
}
|
|
887
951
|
|
|
888
952
|
// when we didn't resolve to git, file, or dir, and didn't request
|
|
889
953
|
// git, file, dir, or remote, then the resolved value is necessary.
|
|
@@ -895,77 +959,90 @@ class Shrinkwrap {
|
|
|
895
959
|
spec.type !== 'directory' &&
|
|
896
960
|
spec.type !== 'git' &&
|
|
897
961
|
spec.type !== 'file' &&
|
|
898
|
-
spec.type !== 'remote')
|
|
962
|
+
spec.type !== 'remote') {
|
|
899
963
|
lock.resolved = node.resolved
|
|
964
|
+
}
|
|
900
965
|
|
|
901
|
-
if (node.integrity)
|
|
966
|
+
if (node.integrity) {
|
|
902
967
|
lock.integrity = node.integrity
|
|
968
|
+
}
|
|
903
969
|
|
|
904
|
-
if (node.extraneous)
|
|
970
|
+
if (node.extraneous) {
|
|
905
971
|
lock.extraneous = true
|
|
906
|
-
else if (!node.isLink) {
|
|
907
|
-
if (node.peer)
|
|
972
|
+
} else if (!node.isLink) {
|
|
973
|
+
if (node.peer) {
|
|
908
974
|
lock.peer = true
|
|
975
|
+
}
|
|
909
976
|
|
|
910
|
-
if (node.devOptional && !node.dev && !node.optional)
|
|
977
|
+
if (node.devOptional && !node.dev && !node.optional) {
|
|
911
978
|
lock.devOptional = true
|
|
979
|
+
}
|
|
912
980
|
|
|
913
|
-
if (node.dev)
|
|
981
|
+
if (node.dev) {
|
|
914
982
|
lock.dev = true
|
|
983
|
+
}
|
|
915
984
|
|
|
916
|
-
if (node.optional)
|
|
985
|
+
if (node.optional) {
|
|
917
986
|
lock.optional = true
|
|
987
|
+
}
|
|
918
988
|
}
|
|
919
989
|
|
|
920
990
|
const depender = node.target
|
|
921
991
|
if (depender.edgesOut.size > 0) {
|
|
922
992
|
if (node !== this.tree) {
|
|
923
|
-
|
|
993
|
+
const entries = [...depender.edgesOut.entries()]
|
|
994
|
+
lock.requires = entries.reduce((set, [k, v]) => {
|
|
924
995
|
// omit peer deps from legacy lockfile requires field, because
|
|
925
996
|
// npm v6 doesn't handle peer deps, and this triggers some bad
|
|
926
997
|
// behavior if the dep can't be found in the dependencies list.
|
|
927
998
|
const { spec, peer } = v
|
|
928
|
-
if (peer)
|
|
999
|
+
if (peer) {
|
|
929
1000
|
return set
|
|
1001
|
+
}
|
|
930
1002
|
if (spec.startsWith('file:')) {
|
|
931
1003
|
// turn absolute file: paths into relative paths from the node
|
|
932
1004
|
// this especially shows up with workspace edges when the root
|
|
933
1005
|
// node is also a workspace in the set.
|
|
934
1006
|
const p = resolve(node.realpath, spec.substr('file:'.length))
|
|
935
1007
|
set[k] = `file:${relpath(node.realpath, p)}`
|
|
936
|
-
} else
|
|
1008
|
+
} else {
|
|
937
1009
|
set[k] = spec
|
|
1010
|
+
}
|
|
938
1011
|
return set
|
|
939
1012
|
}, {})
|
|
940
|
-
} else
|
|
1013
|
+
} else {
|
|
941
1014
|
lock.requires = true
|
|
1015
|
+
}
|
|
942
1016
|
}
|
|
943
1017
|
|
|
944
1018
|
// now we walk the children, putting them in the 'dependencies' object
|
|
945
1019
|
const {children} = node.target
|
|
946
|
-
if (!children.size)
|
|
1020
|
+
if (!children.size) {
|
|
947
1021
|
delete lock.dependencies
|
|
948
|
-
else {
|
|
1022
|
+
} else {
|
|
949
1023
|
const kidPath = [...path, node.realpath]
|
|
950
1024
|
const dependencies = {}
|
|
951
1025
|
// skip any that are already in the descent path, so cyclical link
|
|
952
1026
|
// dependencies don't blow up with ELOOP.
|
|
953
1027
|
let found = false
|
|
954
1028
|
for (const [name, kid] of children.entries()) {
|
|
955
|
-
if (path.includes(kid.realpath))
|
|
1029
|
+
if (path.includes(kid.realpath)) {
|
|
956
1030
|
continue
|
|
1031
|
+
}
|
|
957
1032
|
dependencies[name] = this[_buildLegacyLockfile](kid, {}, kidPath)
|
|
958
1033
|
found = true
|
|
959
1034
|
}
|
|
960
|
-
if (found)
|
|
1035
|
+
if (found) {
|
|
961
1036
|
lock.dependencies = dependencies
|
|
1037
|
+
}
|
|
962
1038
|
}
|
|
963
1039
|
return lock
|
|
964
1040
|
}
|
|
965
1041
|
|
|
966
1042
|
save (options = {}) {
|
|
967
|
-
if (!this.data)
|
|
1043
|
+
if (!this.data) {
|
|
968
1044
|
throw new Error('run load() before saving data')
|
|
1045
|
+
}
|
|
969
1046
|
|
|
970
1047
|
const { format = true } = options
|
|
971
1048
|
const defaultIndent = this.indent || 2
|
package/lib/signal-handling.js
CHANGED
|
@@ -13,8 +13,9 @@ const setup = fn => {
|
|
|
13
13
|
const sigListeners = { loaded: false }
|
|
14
14
|
|
|
15
15
|
const unload = () => {
|
|
16
|
-
if (!sigListeners.loaded)
|
|
16
|
+
if (!sigListeners.loaded) {
|
|
17
17
|
return
|
|
18
|
+
}
|
|
18
19
|
for (const sig of signals) {
|
|
19
20
|
try {
|
|
20
21
|
process.removeListener(sig, sigListeners[sig])
|
|
@@ -43,8 +44,9 @@ const setup = fn => {
|
|
|
43
44
|
// if we exit normally, but caught a signal which would have been fatal,
|
|
44
45
|
// then re-send it once we're done with whatever cleanup we have to do.
|
|
45
46
|
unload()
|
|
46
|
-
if (process.listeners(sig).length < 1)
|
|
47
|
+
if (process.listeners(sig).length < 1) {
|
|
47
48
|
process.once('beforeExit', onBeforeExit)
|
|
49
|
+
}
|
|
48
50
|
|
|
49
51
|
fn({ signal: sig })
|
|
50
52
|
}
|
|
@@ -56,8 +58,9 @@ const setup = fn => {
|
|
|
56
58
|
try {
|
|
57
59
|
// if we call this a bunch of times, avoid triggering the warning
|
|
58
60
|
const { length } = process.listeners(sig)
|
|
59
|
-
if (length >= max)
|
|
61
|
+
if (length >= max) {
|
|
60
62
|
process.setMaxListeners(length + 1)
|
|
63
|
+
}
|
|
61
64
|
process.on(sig, sigListeners[sig])
|
|
62
65
|
} catch (er) {}
|
|
63
66
|
}
|
package/lib/spec-from-lock.js
CHANGED
|
@@ -5,19 +5,22 @@ const specFromLock = (name, lock, where) => {
|
|
|
5
5
|
try {
|
|
6
6
|
if (lock.version) {
|
|
7
7
|
const spec = npa.resolve(name, lock.version, where)
|
|
8
|
-
if (lock.integrity || spec.type === 'git')
|
|
8
|
+
if (lock.integrity || spec.type === 'git') {
|
|
9
9
|
return spec
|
|
10
|
+
}
|
|
10
11
|
}
|
|
11
12
|
if (lock.from) {
|
|
12
13
|
// legacy metadata includes "from", but not integrity
|
|
13
14
|
const spec = npa.resolve(name, lock.from, where)
|
|
14
|
-
if (spec.registry && lock.version)
|
|
15
|
+
if (spec.registry && lock.version) {
|
|
15
16
|
return npa.resolve(name, lock.version, where)
|
|
16
|
-
else if (!lock.resolved)
|
|
17
|
+
} else if (!lock.resolved) {
|
|
17
18
|
return spec
|
|
19
|
+
}
|
|
18
20
|
}
|
|
19
|
-
if (lock.resolved)
|
|
21
|
+
if (lock.resolved) {
|
|
20
22
|
return npa.resolve(name, lock.resolved, where)
|
|
23
|
+
}
|
|
21
24
|
} catch (_) { }
|
|
22
25
|
try {
|
|
23
26
|
return npa.resolve(name, lock.version, where)
|