@npmcli/arborist 2.8.2 → 2.9.0

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