@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.
Files changed (50) hide show
  1. package/bin/actual.js +4 -2
  2. package/bin/audit.js +12 -6
  3. package/bin/dedupe.js +49 -0
  4. package/bin/funding.js +4 -2
  5. package/bin/ideal.js +2 -1
  6. package/bin/lib/logging.js +4 -3
  7. package/bin/lib/options.js +14 -12
  8. package/bin/lib/timers.js +6 -3
  9. package/bin/license.js +9 -5
  10. package/bin/prune.js +6 -3
  11. package/bin/reify.js +6 -3
  12. package/bin/virtual.js +4 -2
  13. package/lib/add-rm-pkg-deps.js +25 -14
  14. package/lib/arborist/audit.js +2 -1
  15. package/lib/arborist/build-ideal-tree.js +246 -757
  16. package/lib/arborist/deduper.js +2 -1
  17. package/lib/arborist/index.js +8 -4
  18. package/lib/arborist/load-actual.js +32 -15
  19. package/lib/arborist/load-virtual.js +34 -18
  20. package/lib/arborist/load-workspaces.js +4 -2
  21. package/lib/arborist/rebuild.js +31 -16
  22. package/lib/arborist/reify.js +332 -119
  23. package/lib/audit-report.js +42 -22
  24. package/lib/calc-dep-flags.js +18 -9
  25. package/lib/can-place-dep.js +430 -0
  26. package/lib/case-insensitive-map.js +50 -0
  27. package/lib/consistent-resolve.js +2 -1
  28. package/lib/deepest-nesting-target.js +18 -0
  29. package/lib/dep-valid.js +8 -4
  30. package/lib/diff.js +74 -22
  31. package/lib/edge.js +29 -14
  32. package/lib/gather-dep-set.js +2 -1
  33. package/lib/inventory.js +12 -6
  34. package/lib/link.js +14 -9
  35. package/lib/node.js +269 -118
  36. package/lib/optional-set.js +4 -2
  37. package/lib/peer-entry-sets.js +77 -0
  38. package/lib/place-dep.js +578 -0
  39. package/lib/printable.js +48 -18
  40. package/lib/realpath.js +12 -6
  41. package/lib/shrinkwrap.js +168 -91
  42. package/lib/signal-handling.js +6 -3
  43. package/lib/spec-from-lock.js +7 -4
  44. package/lib/tracker.js +24 -18
  45. package/lib/tree-check.js +12 -6
  46. package/lib/version-from-tgz.js +4 -2
  47. package/lib/vuln.js +28 -16
  48. package/lib/yarn-lock.js +27 -15
  49. package/package.json +9 -13
  50. 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
- if (!isScope && !isNM && !data.packages[rel])
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(() => null)
192
+ const tstat = await stat(target).catch(
193
+ /* istanbul ignore next - windows */ () => null)
187
194
  seen.add(relpath(path, child))
188
- if (tstat && tstat.isDirectory() && !seen.has(relpath(path, target)))
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
- if (node.dev)
296
+ }
297
+ if (node.dev) {
279
298
  meta.dev = true
280
- if (node.optional)
299
+ }
300
+ if (node.optional) {
281
301
  meta.optional = true
282
- if (node.devOptional && !node.dev && !node.optional)
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
- if (lock.dev)
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
- lock.requires = [...depender.edgesOut.entries()].reduce((set, [k, v]) => {
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
@@ -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
  }
@@ -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)