@npmcli/arborist 9.0.2 → 9.1.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/README.md CHANGED
@@ -267,53 +267,19 @@ are updated by arborist when necessary whenever the tree is modified in
267
267
  such a way that the dependency graph can change, and are relevant when
268
268
  pruning nodes from the tree.
269
269
 
270
- ```
271
- | extraneous | peer | dev | optional | devOptional | meaning | prune? |
272
- |------------+------+-----+----------+-------------+---------------------+-------------------|
273
- | | | | | | production dep | never |
274
- |------------+------+-----+----------+-------------+---------------------+-------------------|
275
- | X | N/A | N/A | N/A | N/A | nothing depends on | always |
276
- | | | | | | this, it is trash | |
277
- |------------+------+-----+----------+-------------+---------------------+-------------------|
278
- | | | X | | X | devDependency, or | if pruning dev |
279
- | | | | | not in lock | only depended upon | |
280
- | | | | | | by devDependencies | |
281
- |------------+------+-----+----------+-------------+---------------------+-------------------|
282
- | | | | X | X | optionalDependency, | if pruning |
283
- | | | | | not in lock | or only depended on | optional |
284
- | | | | | | by optionalDeps | |
285
- |------------+------+-----+----------+-------------+---------------------+-------------------|
286
- | | | X | X | X | Optional dependency | if pruning EITHER |
287
- | | | | | not in lock | of dep(s) in the | dev OR optional |
288
- | | | | | | dev hierarchy | |
289
- |------------+------+-----+----------+-------------+---------------------+-------------------|
290
- | | | | | X | BOTH a non-optional | if pruning BOTH |
291
- | | | | | in lock | dep within the dev | dev AND optional |
292
- | | | | | | hierarchy, AND a | |
293
- | | | | | | dep within the | |
294
- | | | | | | optional hierarchy | |
295
- |------------+------+-----+----------+-------------+---------------------+-------------------|
296
- | | X | | | | peer dependency, or | if pruning peers |
297
- | | | | | | only depended on by | |
298
- | | | | | | peer dependencies | |
299
- |------------+------+-----+----------+-------------+---------------------+-------------------|
300
- | | X | X | | X | peer dependency of | if pruning peer |
301
- | | | | | not in lock | dev node hierarchy | OR dev deps |
302
- |------------+------+-----+----------+-------------+---------------------+-------------------|
303
- | | X | | X | X | peer dependency of | if pruning peer |
304
- | | | | | not in lock | optional nodes, or | OR optional deps |
305
- | | | | | | peerOptional dep | |
306
- |------------+------+-----+----------+-------------+---------------------+-------------------|
307
- | | X | X | X | X | peer optional deps | if pruning peer |
308
- | | | | | not in lock | of the dev dep | OR optional OR |
309
- | | | | | | hierarchy | dev |
310
- |------------+------+-----+----------+-------------+---------------------+-------------------|
311
- | | X | | | X | BOTH a non-optional | if pruning peers |
312
- | | | | | in lock | peer dep within the | OR: |
313
- | | | | | | dev hierarchy, AND | BOTH optional |
314
- | | | | | | a peer optional dep | AND dev deps |
315
- +------------+------+-----+----------+-------------+---------------------+-------------------+
316
- ```
270
+ | extraneous | peer | dev | optional | devOptional | meaning | prune? |
271
+ |:----------:|:----:|:---:|:--------:|:----------------:|:-------------------------------------------------------------------------------------------------|:-------------------------------------------------------|
272
+ | | | | | | production dep | never |
273
+ | X | N/A | N/A | N/A | N/A | nothing depends on this, it is trash | always |
274
+ | | | X | | X<br>not in lock | devDependency, or only depended<br>on by devDependencies | if pruning dev |
275
+ | | | | X | X<br>not in lock | optionalDependency, or only depended<br>on by optionalDeps | if pruning optional |
276
+ | | | X | X | X<br>not in lock | Optional dependency of dep(s) in the<br>dev hierarchy | if pruning EITHER<br>dev OR optional |
277
+ | | | | | X<br>in lock | BOTH a non-optional dep within the<br>dev hierarchy, AND a dep within<br>the optional hierarchy | if pruning BOTH<br>dev AND optional |
278
+ | | X | | | | peer dependency, or only depended<br>on by peer dependencies | if pruning peers |
279
+ | | X | X | | X<br>not in lock | peer dependency of dev node hierarchy | if pruning peer OR<br>dev deps |
280
+ | | X | | X | X<br>not in lock | peer dependency of optional nodes, or<br>peerOptional dep | if pruning peer OR<br>optional deps |
281
+ | | X | X | X | X<br>not in lock | peer optional deps of the dev dep hierarchy | if pruning peer OR<br>optional OR dev |
282
+ | | X | | | X<br>in lock | BOTH a non-optional peer dep within the<br>dev hierarchy, AND a peer optional dep | if pruning peer deps OR:<br>BOTH optional AND dev deps |
317
283
 
318
284
  * If none of these flags are set, then the node is required by the
319
285
  dependency and/or peerDependency hierarchy. It should not be pruned.
@@ -200,6 +200,18 @@ module.exports = cls => class VirtualLoader extends cls {
200
200
  const targetPath = resolve(this.path, meta.resolved)
201
201
  const targetLoc = relpath(this.path, targetPath)
202
202
  const target = nodes.get(targetLoc)
203
+
204
+ if (!target) {
205
+ const err = new Error(
206
+ `Missing target in lock file: "${targetLoc}" is referenced by "${location}" but does not exist.
207
+ To fix:
208
+ 1. rm package-lock.json
209
+ 2. npm install`
210
+ )
211
+ err.code = 'EMISSINGTARGET'
212
+ throw err
213
+ }
214
+
203
215
  const link = this.#loadLink(location, targetLoc, target, meta)
204
216
  nodes.set(location, link)
205
217
  nodes.set(targetLoc, link.target)
@@ -825,7 +825,14 @@ module.exports = cls => class Reifier extends cls {
825
825
  // symlink
826
826
  const dir = dirname(node.path)
827
827
  const target = node.realpath
828
- const rel = relative(dir, target)
828
+
829
+ let rel
830
+ if (node.resolved?.startsWith('file:')) {
831
+ rel = this.#calculateRelativePath(node, dir, target, nm)
832
+ } else {
833
+ rel = relative(dir, target)
834
+ }
835
+
829
836
  await mkdir(dir, { recursive: true })
830
837
  return symlink(rel, node.path, 'junction')
831
838
  }
@@ -843,6 +850,32 @@ module.exports = cls => class Reifier extends cls {
843
850
  }) : p).then(() => node)
844
851
  }
845
852
 
853
+ #calculateRelativePath (node, dir, target) {
854
+ // Check if the node is affected by a root override
855
+ let hasRootOverride = [...node.edgesIn].some(edge => edge.from.isRoot && edge.overrides)
856
+ // If not set via edges, see if the root package.json explicitly lists an override
857
+ if (!hasRootOverride && node.root) {
858
+ const rootPackage = node.root.target
859
+ hasRootOverride = !!(rootPackage &&
860
+ rootPackage.package.overrides &&
861
+ rootPackage.package.overrides[node.name])
862
+ }
863
+ if (!hasRootOverride) {
864
+ return relative(dir, target)
865
+ }
866
+ // If an override is detected, attempt to retrieve the override spec from the root package.json
867
+ const overrideSpec = node.root?.target?.package?.overrides?.[node.name]
868
+ if (typeof overrideSpec === 'string' && overrideSpec.startsWith('file:')) {
869
+ const overridePath = overrideSpec.replace(/^file:/, '')
870
+ const rootDir = node.root.target.path
871
+ return relative(dir, resolve(rootDir, overridePath))
872
+ }
873
+
874
+ // Fallback: derive the file path from node.resolved in a platform-agnostic way
875
+ const filePath = node.resolved.replace(/^file:/, '')
876
+ return join(filePath)
877
+ }
878
+
846
879
  #registryResolved (resolved) {
847
880
  // the default registry url is a magic value meaning "the currently
848
881
  // configured registry".
@@ -858,9 +891,19 @@ module.exports = cls => class Reifier extends cls {
858
891
  if ((this.options.replaceRegistryHost === resolvedURL.hostname) ||
859
892
  this.options.replaceRegistryHost === 'always') {
860
893
  const registryURL = new URL(this.registry)
894
+
861
895
  // Replace the host with the registry host while keeping the path intact
862
896
  resolvedURL.hostname = registryURL.hostname
863
897
  resolvedURL.port = registryURL.port
898
+
899
+ // Make sure we don't double-include the path if it's already there
900
+ const registryPath = registryURL.pathname.replace(/\/$/, '')
901
+
902
+ if (registryPath && registryPath !== '/' && !resolvedURL.pathname.startsWith(registryPath)) {
903
+ // Since hostname is changed, we need to ensure the registry path is included
904
+ resolvedURL.pathname = registryPath + resolvedURL.pathname
905
+ }
906
+
864
907
  return resolvedURL.toString()
865
908
  }
866
909
  return resolved
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@npmcli/arborist",
3
- "version": "9.0.2",
3
+ "version": "9.1.1",
4
4
  "description": "Manage node_modules trees",
5
5
  "dependencies": {
6
6
  "@isaacs/string-locale-compare": "^1.1.0",