@npmcli/arborist 2.2.5 → 2.2.9

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.
@@ -71,7 +71,7 @@ const addSingle = ({pkg, spec, saveBundle, saveType}) => {
71
71
  pkg.devDependencies[name] = pkg.peerDependencies[name]
72
72
  }
73
73
 
74
- if (saveBundle) {
74
+ if (saveBundle && saveType !== 'peer' && saveType !== 'peerOptional') {
75
75
  // keep it sorted, keep it unique
76
76
  const bd = new Set(pkg.bundleDependencies || [])
77
77
  bd.add(spec.name)
@@ -431,11 +431,13 @@ module.exports = cls => class IdealTreeBuilder extends cls {
431
431
  // ie, doing `foo@bar` we just return foo
432
432
  // but if it's a url or git, we don't know the name until we
433
433
  // fetch it and look in its manifest.
434
- return Promise.all(add.map(rawSpec =>
435
- this[_retrieveSpecName](npa(rawSpec))
434
+ return Promise.all(add.map(rawSpec => {
435
+ // We do NOT provide the path here, because user-additions need
436
+ // to be resolved relative to the CWD the user is in.
437
+ return this[_retrieveSpecName](npa(rawSpec))
436
438
  .then(add => this[_updateFilePath](add))
437
439
  .then(add => this[_followSymlinkPath](add))
438
- )).then(add => {
440
+ })).then(add => {
439
441
  this[_resolvedAdd] = add
440
442
  // now add is a list of spec objects with names.
441
443
  // find a home for each of them!
@@ -881,6 +883,8 @@ This is a one-time fix-up, please be patient...
881
883
  // create a virtual root node with the same deps as the node that
882
884
  // is requesting this one, so that we can get all the peer deps in
883
885
  // a context where they're likely to be resolvable.
886
+ // Note that the virtual root will also have virtual copies of the
887
+ // targets of any child Links, so that they resolve appropriately.
884
888
  const parent = parent_ || this[_virtualRoot](edge.from)
885
889
  const realParent = edge.peer ? edge.from.resolveParent : edge.from
886
890
 
@@ -934,11 +938,23 @@ This is a one-time fix-up, please be patient...
934
938
  return this[_virtualRoots].get(node)
935
939
 
936
940
  const vr = new Node({
937
- path: '/virtual-root',
941
+ path: node.realpath,
938
942
  sourceReference: node,
939
943
  legacyPeerDeps: this.legacyPeerDeps,
940
944
  })
941
945
 
946
+ // also need to set up any targets from any link deps, so that
947
+ // they are properly reflected in the virtual environment
948
+ for (const child of node.children.values()) {
949
+ if (child.isLink) {
950
+ new Node({
951
+ path: child.realpath,
952
+ sourceReference: child.target,
953
+ root: vr,
954
+ })
955
+ }
956
+ }
957
+
942
958
  this[_virtualRoots].set(node, vr)
943
959
  return vr
944
960
  }
@@ -6,6 +6,7 @@ const rpj = require('read-package-json-fast')
6
6
  const { updateDepSpec } = require('../dep-spec.js')
7
7
  const AuditReport = require('../audit-report.js')
8
8
  const {subset} = require('semver')
9
+ const npa = require('npm-package-arg')
9
10
 
10
11
  const {dirname, resolve, relative} = require('path')
11
12
  const {depth: dfwalk} = require('treeverse')
@@ -881,11 +882,17 @@ module.exports = cls => class Reifier extends cls {
881
882
 
882
883
  process.emit('time', 'reify:save')
883
884
 
885
+ // resolvedAdd is the list of user add requests, but with names added
886
+ // to things like git repos and tarball file/urls. However, if the
887
+ // user requested 'foo@', and we have a foo@file:../foo, then we should
888
+ // end up saving the spec we actually used, not whatever they gave us.
884
889
  if (this[_resolvedAdd]) {
885
890
  const root = this.idealTree
886
891
  const pkg = root.package
887
- for (const req of this[_resolvedAdd]) {
888
- const {name, rawSpec, subSpec} = req
892
+ for (const { name } of this[_resolvedAdd]) {
893
+ const req = npa.resolve(name, root.edgesOut.get(name).spec, root.realpath)
894
+ const {rawSpec, subSpec} = req
895
+
889
896
  const spec = subSpec ? subSpec.rawSpec : rawSpec
890
897
  const child = root.children.get(name)
891
898
 
@@ -910,6 +917,15 @@ module.exports = cls => class Reifier extends cls {
910
917
  const save = h.https && h.auth ? `git+${h.https(opt)}`
911
918
  : h.shortcut(opt)
912
919
  updateDepSpec(pkg, name, save)
920
+ } else if (req.type === 'directory' || req.type === 'file') {
921
+ // save the relative path in package.json
922
+ // Normally saveSpec is updated with the proper relative
923
+ // path already, but it's possible to specify a full absolute
924
+ // path initially, in which case we can end up with the wrong
925
+ // thing, so just get the ultimate fetchSpec and relativize it.
926
+ const p = req.fetchSpec.replace(/^file:/, '')
927
+ const rel = relpath(root.realpath, p)
928
+ updateDepSpec(pkg, name, `file:${rel}`)
913
929
  } else
914
930
  updateDepSpec(pkg, name, req.saveSpec)
915
931
  }
package/lib/edge.js CHANGED
@@ -87,16 +87,24 @@ class Edge {
87
87
 
88
88
  // return the edge data, and an explanation of how that edge came to be here
89
89
  [_explain] (seen) {
90
- const { error, from } = this
90
+ const { error, from, bundled } = this
91
91
  return {
92
92
  type: this.type,
93
93
  name: this.name,
94
94
  spec: this.spec,
95
+ ...(bundled ? { bundled } : {}),
95
96
  ...(error ? { error } : {}),
96
97
  ...(from ? { from: from.explain(null, seen) } : {}),
97
98
  }
98
99
  }
99
100
 
101
+ get bundled () {
102
+ if (!this.from)
103
+ return false
104
+ const { package: { bundleDependencies = [] } } = this.from
105
+ return bundleDependencies.includes(this.name)
106
+ }
107
+
100
108
  get workspace () {
101
109
  return this[_type] === 'workspace'
102
110
  }
package/lib/printable.js CHANGED
@@ -63,6 +63,13 @@ class ArboristNode {
63
63
  }
64
64
  }
65
65
 
66
+ class ArboristVirtualNode extends ArboristNode {
67
+ constructor (tree, path) {
68
+ super(tree, path)
69
+ this.sourceReference = printableTree(tree.sourceReference, path)
70
+ }
71
+ }
72
+
66
73
  class ArboristLink extends ArboristNode {
67
74
  constructor (tree, path) {
68
75
  super(tree, path)
@@ -119,10 +126,14 @@ class EdgeIn extends Edge {
119
126
  }
120
127
 
121
128
  const printableTree = (tree, path = []) => {
122
- if (path.includes(tree))
123
- return { location: tree.location }
129
+ const Cls = tree.isLink ? ArboristLink
130
+ : tree.sourceReference ? ArboristVirtualNode
131
+ : ArboristNode
132
+ if (path.includes(tree)) {
133
+ const obj = Object.create(Cls.prototype)
134
+ return Object.assign(obj, { location: tree.location })
135
+ }
124
136
  path.push(tree)
125
- const Cls = tree.isLink ? ArboristLink : ArboristNode
126
137
  return new Cls(tree, path)
127
138
  }
128
139
 
package/lib/shrinkwrap.js CHANGED
@@ -41,6 +41,7 @@ const readFile = promisify(fs.readFile)
41
41
  const writeFile = promisify(fs.writeFile)
42
42
  const stat = promisify(fs.stat)
43
43
  const readdir_ = promisify(fs.readdir)
44
+ const readlink = promisify(fs.readlink)
44
45
 
45
46
  // XXX remove when drop support for node v10
46
47
  const lstat = promisify(fs.lstat)
@@ -176,10 +177,19 @@ const assertNoNewer = async (path, data, lockTime, dir = path, seen = null) => {
176
177
  : readdir(parent, { withFileTypes: true })
177
178
 
178
179
  return children.catch(() => [])
179
- .then(ents => Promise.all(
180
- ents.filter(ent => ent.isDirectory() && !/^\./.test(ent.name))
181
- .map(ent => assertNoNewer(path, data, lockTime, resolve(parent, ent.name), seen))
182
- )).then(() => {
180
+ .then(ents => Promise.all(ents.map(async ent => {
181
+ const child = resolve(parent, ent.name)
182
+ if (ent.isDirectory() && !/^\./.test(ent.name))
183
+ await assertNoNewer(path, data, lockTime, child, seen)
184
+ else if (ent.isSymbolicLink()) {
185
+ const target = resolve(parent, await readlink(child))
186
+ const tstat = await stat(target).catch(() => null)
187
+ seen.add(relpath(path, child))
188
+ if (tstat && tstat.isDirectory() && !seen.has(relpath(path, target)))
189
+ await assertNoNewer(path, data, lockTime, target, seen)
190
+ }
191
+ })))
192
+ .then(() => {
183
193
  if (dir !== path)
184
194
  return
185
195
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@npmcli/arborist",
3
- "version": "2.2.5",
3
+ "version": "2.2.9",
4
4
  "description": "Manage node_modules trees",
5
5
  "dependencies": {
6
6
  "@npmcli/installed-package-contents": "^1.0.7",
@@ -26,7 +26,7 @@
26
26
  "promise-call-limit": "^1.0.1",
27
27
  "read-package-json-fast": "^2.0.2",
28
28
  "readdir-scoped-modules": "^1.1.0",
29
- "semver": "^7.3.4",
29
+ "semver": "^7.3.5",
30
30
  "tar": "^6.1.0",
31
31
  "treeverse": "^1.0.4",
32
32
  "walk-up-path": "^1.0.0"