@pnpm/deps.inspection.tree-builder 1101.0.7 → 1101.0.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.
@@ -18,31 +18,7 @@ export async function buildDependentsTree(packages, projectPaths, opts) {
18
18
  const registriesByScope = normalizeRegistriesByScope(opts.registriesByScope);
19
19
  const storeDir = modules?.storeDir;
20
20
  const storeIndex = storeDir ? new StoreIndex(storeDir) : undefined;
21
- const virtualStoreDir = modules?.virtualStoreDir ?? path.join(modulesDir, '.pnpm');
22
- const virtualStoreDirMaxLength = modules?.virtualStoreDirMaxLength ?? 120;
23
- const include = opts.include ?? {
24
- dependencies: true,
25
- devDependencies: true,
26
- optionalDependencies: true,
27
- };
28
- // Build root IDs from the selected project paths (respects --filter / --recursive)
29
- const allRootIds = [];
30
- for (const projectPath of projectPaths) {
31
- const importerId = getLockfileImporterId(opts.lockfileDir, projectPath);
32
- if (opts.lockfile.importers[importerId]) {
33
- allRootIds.push({ type: 'importer', importerId });
34
- }
35
- }
36
- const graph = buildDependencyGraph(allRootIds, {
37
- currentPackages: opts.lockfile.packages ?? {},
38
- importers: opts.lockfile.importers,
39
- include,
40
- lockfileDir: opts.lockfileDir,
41
- peerSatisfactionEdges: getPeerSatisfactionEdgesToSkip(opts.lockfile, {
42
- include,
43
- resolvePeersFromWorkspaceRoot: opts.resolvePeersFromWorkspaceRoot,
44
- }),
45
- });
21
+ const graph = buildSelectedProjectsGraph(projectPaths, opts);
46
22
  const reverseMap = invertGraph(graph);
47
23
  const search = createPackagesSearcher(packages, opts.finders);
48
24
  const currentPackages = opts.lockfile.packages ?? {};
@@ -50,8 +26,8 @@ export async function buildDependentsTree(packages, projectPaths, opts) {
50
26
  // graph top-down from importers. This is needed for global virtual store
51
27
  // where symlinks must be resolved through each parent's node_modules.
52
28
  const resolvedPackageNodes = resolvePackageNodes(graph, currentPackages, {
53
- virtualStoreDir,
54
- virtualStoreDirMaxLength,
29
+ virtualStoreDir: modules?.virtualStoreDir ?? path.join(modulesDir, '.pnpm'),
30
+ virtualStoreDirMaxLength: modules?.virtualStoreDirMaxLength ?? 120,
55
31
  modulesDir,
56
32
  registriesByScope,
57
33
  registriesByPrefix: opts.registriesByPrefix,
@@ -59,13 +35,7 @@ export async function buildDependentsTree(packages, projectPaths, opts) {
59
35
  storeDir,
60
36
  storeIndex,
61
37
  });
62
- // Scan all package nodes for matches.
63
- // A package matches if any of the aliases used to refer to it (from incoming
64
- // edges in the graph) or its canonical name match the search query.
65
- // Each distinct depPath (i.e. different peer dep resolutions) is kept as a
66
- // separate result so that peer variants are visible in the output.
67
- const trees = [];
68
- const ctx = {
38
+ const trees = collectMatchedTrees(search, {
69
39
  reverseMap,
70
40
  graph,
71
41
  importers: opts.lockfile.importers,
@@ -75,70 +45,109 @@ export async function buildDependentsTree(packages, projectPaths, opts) {
75
45
  nameFormatter: opts.nameFormatter,
76
46
  visited: new Set(),
77
47
  expanded: new Set(),
48
+ });
49
+ trees.sort(compareDependentsTrees);
50
+ storeIndex?.close();
51
+ return trees;
52
+ }
53
+ function buildSelectedProjectsGraph(projectPaths, opts) {
54
+ const include = opts.include ?? {
55
+ dependencies: true,
56
+ devDependencies: true,
57
+ optionalDependencies: true,
78
58
  };
79
- for (const [serialized, node] of graph.nodes) {
80
- if (node.nodeId.type !== 'package')
81
- continue;
82
- const depPath = node.nodeId.depPath;
83
- const snapshot = currentPackages[depPath];
84
- if (snapshot == null)
85
- continue;
86
- const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot);
87
- const pkgNode = resolvedPackageNodes.get(serialized);
88
- if (!pkgNode)
89
- continue;
90
- const readManifest = pkgNode.readManifest;
91
- // Check canonical name first
92
- let matched = search({ alias: name, name, version, readManifest });
93
- // Also check aliases from incoming edges (handles npm: protocol aliases)
94
- if (!matched) {
95
- const incomingEdges = reverseMap.get(serialized);
96
- if (incomingEdges) {
97
- for (const edge of incomingEdges) {
98
- if (edge.alias !== name) {
99
- matched = search({ alias: edge.alias, name, version, readManifest });
100
- if (matched)
101
- break;
102
- }
103
- }
104
- }
105
- }
106
- if (!matched)
107
- continue;
108
- ctx.visited = new Set([serialized]);
109
- ctx.expanded = new Set();
110
- const dependents = walkReverse(serialized, ctx);
111
- const peersSuffixHash = peersSuffixHashFromDepPath(depPath);
112
- const displayName = opts.nameFormatter
113
- ? opts.nameFormatter({ name, version, manifest: readManifest() })
114
- : undefined;
115
- const tree = {
116
- name,
117
- displayName,
118
- version,
119
- path: pkgNode.path,
120
- peersSuffixHash,
121
- dependents,
122
- };
123
- if (typeof matched === 'string') {
124
- tree.searchMessage = matched;
59
+ const allRootIds = [];
60
+ for (const projectPath of projectPaths) {
61
+ const importerId = getLockfileImporterId(opts.lockfileDir, projectPath);
62
+ if (opts.lockfile.importers[importerId]) {
63
+ allRootIds.push({ type: 'importer', importerId });
125
64
  }
126
- trees.push(tree);
127
65
  }
128
- trees.sort((a, b) => {
129
- const nameCmp = lexCompare(a.name, b.name);
130
- if (nameCmp !== 0)
131
- return nameCmp;
132
- const versionCmp = semver.valid(a.version) && semver.valid(b.version)
133
- ? semver.compare(a.version, b.version)
134
- : lexCompare(a.version, b.version);
135
- if (versionCmp !== 0)
136
- return versionCmp;
137
- return lexCompare(a.peersSuffixHash ?? '', b.peersSuffixHash ?? '');
66
+ return buildDependencyGraph(allRootIds, {
67
+ currentPackages: opts.lockfile.packages ?? {},
68
+ importers: opts.lockfile.importers,
69
+ include,
70
+ lockfileDir: opts.lockfileDir,
71
+ peerSatisfactionEdges: getPeerSatisfactionEdgesToSkip(opts.lockfile, {
72
+ include,
73
+ resolvePeersFromWorkspaceRoot: opts.resolvePeersFromWorkspaceRoot,
74
+ }),
138
75
  });
139
- storeIndex?.close();
76
+ }
77
+ // Scan all package nodes for matches.
78
+ // A package matches if any of the aliases used to refer to it (from incoming
79
+ // edges in the graph) or its canonical name match the search query.
80
+ // Each distinct depPath (i.e. different peer dep resolutions) is kept as a
81
+ // separate result so that peer variants are visible in the output.
82
+ function collectMatchedTrees(search, ctx) {
83
+ const trees = [];
84
+ for (const [serialized, node] of ctx.graph.nodes) {
85
+ if (node.nodeId.type !== 'package')
86
+ continue;
87
+ const tree = buildTreeIfMatched(search, { serialized, depPath: node.nodeId.depPath }, ctx);
88
+ if (tree != null)
89
+ trees.push(tree);
90
+ }
140
91
  return trees;
141
92
  }
93
+ function buildTreeIfMatched(search, { serialized, depPath }, ctx) {
94
+ const snapshot = ctx.currentPackages[depPath];
95
+ if (snapshot == null)
96
+ return undefined;
97
+ const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot);
98
+ const pkgNode = ctx.resolvedPackageNodes.get(serialized);
99
+ if (!pkgNode)
100
+ return undefined;
101
+ const readManifest = pkgNode.readManifest;
102
+ const matched = searchPackage(search, { serialized, name, version, readManifest }, ctx);
103
+ if (!matched)
104
+ return undefined;
105
+ ctx.visited = new Set([serialized]);
106
+ ctx.expanded = new Set();
107
+ const dependents = walkReverse(serialized, ctx);
108
+ const peersSuffixHash = peersSuffixHashFromDepPath(depPath);
109
+ const displayName = ctx.nameFormatter
110
+ ? ctx.nameFormatter({ name, version, manifest: readManifest() })
111
+ : undefined;
112
+ const tree = {
113
+ name,
114
+ displayName,
115
+ version,
116
+ path: pkgNode.path,
117
+ peersSuffixHash,
118
+ dependents,
119
+ };
120
+ if (typeof matched === 'string') {
121
+ tree.searchMessage = matched;
122
+ }
123
+ return tree;
124
+ }
125
+ function searchPackage(search, pkg, ctx) {
126
+ const { name, version, readManifest } = pkg;
127
+ const matched = search({ alias: name, name, version, readManifest });
128
+ if (matched)
129
+ return matched;
130
+ // Also check aliases from incoming edges (handles npm: protocol aliases)
131
+ for (const edge of ctx.reverseMap.get(pkg.serialized) ?? []) {
132
+ if (edge.alias === name)
133
+ continue;
134
+ const aliasMatched = search({ alias: edge.alias, name, version, readManifest });
135
+ if (aliasMatched)
136
+ return aliasMatched;
137
+ }
138
+ return false;
139
+ }
140
+ function compareDependentsTrees(left, right) {
141
+ const nameCmp = lexCompare(left.name, right.name);
142
+ if (nameCmp !== 0)
143
+ return nameCmp;
144
+ const versionCmp = semver.valid(left.version) && semver.valid(right.version)
145
+ ? semver.compare(left.version, right.version)
146
+ : lexCompare(left.version, right.version);
147
+ if (versionCmp !== 0)
148
+ return versionCmp;
149
+ return lexCompare(left.peersSuffixHash ?? '', right.peersSuffixHash ?? '');
150
+ }
142
151
  function invertGraph(graph) {
143
152
  const reverse = new Map();
144
153
  for (const [parentSerialized, node] of graph.nodes) {
@@ -207,78 +216,88 @@ function walkReverse(nodeId, ctx) {
207
216
  return [];
208
217
  // Sort edges by parent name (with serialized ID as tiebreaker) so that
209
218
  // deduplication is deterministic: the first parent always gets fully expanded.
210
- const sortedEdges = [...reverseEdges].sort((a, b) => {
211
- const cmp = lexCompare(resolveParentName(a, ctx), resolveParentName(b, ctx));
219
+ const sortedEdges = [...reverseEdges].sort((left, right) => {
220
+ const cmp = lexCompare(resolveParentName(left, ctx), resolveParentName(right, ctx));
212
221
  if (cmp !== 0)
213
222
  return cmp;
214
- return lexCompare(a.parentSerialized, b.parentSerialized);
223
+ return lexCompare(left.parentSerialized, right.parentSerialized);
215
224
  });
216
225
  const dependents = [];
217
226
  for (const edge of sortedEdges) {
218
227
  // Cycle detection: this node is already on our current path
219
- if (ctx.visited.has(edge.parentSerialized)) {
220
- const parentNode = ctx.graph.nodes.get(edge.parentSerialized);
221
- if (parentNode?.nodeId.type === 'importer') {
222
- const info = ctx.importerInfoMap.get(parentNode.nodeId.importerId);
223
- if (info) {
224
- dependents.push({
225
- name: info.name,
226
- version: info.version,
227
- circular: true,
228
- });
229
- }
230
- }
231
- else if (parentNode?.nodeId.type === 'package') {
232
- const snapshot = ctx.currentPackages[parentNode.nodeId.depPath];
233
- if (snapshot) {
234
- const { name, version } = nameVerFromPkgSnapshot(parentNode.nodeId.depPath, snapshot);
235
- const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
236
- dependents.push({ name, displayName, version, circular: true });
237
- }
238
- }
239
- continue;
240
- }
241
- const parentGraphNode = ctx.graph.nodes.get(edge.parentSerialized);
242
- if (parentGraphNode == null)
243
- continue;
244
- if (parentGraphNode.nodeId.type === 'importer') {
245
- const importerId = parentGraphNode.nodeId.importerId;
246
- const info = ctx.importerInfoMap.get(importerId) ?? { name: importerId, version: '' };
247
- const depField = getDepFieldForAlias(edge.alias, ctx.importers[importerId]);
248
- dependents.push({
249
- name: info.name,
250
- version: info.version,
251
- depField,
252
- });
253
- }
254
- else if (parentGraphNode.nodeId.type === 'package') {
255
- const snapshot = ctx.currentPackages[parentGraphNode.nodeId.depPath];
256
- if (snapshot == null)
257
- continue;
258
- const { name, version } = nameVerFromPkgSnapshot(parentGraphNode.nodeId.depPath, snapshot);
259
- const peersSuffixHash = peersSuffixHashFromDepPath(parentGraphNode.nodeId.depPath);
260
- // Deduplication: if this package was already expanded elsewhere in the
261
- // tree, show it as a leaf to keep the output bounded.
262
- const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
263
- if (ctx.expanded.has(edge.parentSerialized)) {
264
- dependents.push({ name, displayName, version, peersSuffixHash, deduped: true });
265
- continue;
266
- }
267
- ctx.visited.add(edge.parentSerialized);
268
- ctx.expanded.add(edge.parentSerialized);
269
- const childDependents = walkReverse(edge.parentSerialized, ctx);
270
- ctx.visited.delete(edge.parentSerialized);
271
- dependents.push({
272
- name,
273
- displayName,
274
- version,
275
- peersSuffixHash,
276
- dependents: childDependents.length > 0 ? childDependents : undefined,
277
- });
278
- }
228
+ const dependent = ctx.visited.has(edge.parentSerialized)
229
+ ? createCircularDependent(edge, ctx)
230
+ : createDependent(edge, ctx);
231
+ if (dependent != null)
232
+ dependents.push(dependent);
279
233
  }
280
234
  return dependents;
281
235
  }
236
+ function createCircularDependent(edge, ctx) {
237
+ const parentNode = ctx.graph.nodes.get(edge.parentSerialized);
238
+ if (parentNode?.nodeId.type === 'importer') {
239
+ const info = ctx.importerInfoMap.get(parentNode.nodeId.importerId);
240
+ if (!info)
241
+ return undefined;
242
+ return {
243
+ name: info.name,
244
+ version: info.version,
245
+ circular: true,
246
+ };
247
+ }
248
+ if (parentNode?.nodeId.type !== 'package')
249
+ return undefined;
250
+ const snapshot = ctx.currentPackages[parentNode.nodeId.depPath];
251
+ if (!snapshot)
252
+ return undefined;
253
+ const { name, version } = nameVerFromPkgSnapshot(parentNode.nodeId.depPath, snapshot);
254
+ const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
255
+ return { name, displayName, version, circular: true };
256
+ }
257
+ function createDependent(edge, ctx) {
258
+ const parentGraphNode = ctx.graph.nodes.get(edge.parentSerialized);
259
+ if (parentGraphNode == null)
260
+ return undefined;
261
+ const parentNodeId = parentGraphNode.nodeId;
262
+ if (parentNodeId.type === 'importer') {
263
+ const importerId = parentNodeId.importerId;
264
+ const info = ctx.importerInfoMap.get(importerId) ?? { name: importerId, version: '' };
265
+ const depField = getDepFieldForAlias(edge.alias, ctx.importers[importerId]);
266
+ return {
267
+ name: info.name,
268
+ version: info.version,
269
+ depField,
270
+ };
271
+ }
272
+ if (parentNodeId.type === 'package') {
273
+ return createPackageDependent(edge, parentNodeId.depPath, ctx);
274
+ }
275
+ return undefined;
276
+ }
277
+ function createPackageDependent(edge, depPath, ctx) {
278
+ const snapshot = ctx.currentPackages[depPath];
279
+ if (snapshot == null)
280
+ return undefined;
281
+ const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot);
282
+ const peersSuffixHash = peersSuffixHashFromDepPath(depPath);
283
+ // Deduplication: if this package was already expanded elsewhere in the
284
+ // tree, show it as a leaf to keep the output bounded.
285
+ const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
286
+ if (ctx.expanded.has(edge.parentSerialized)) {
287
+ return { name, displayName, version, peersSuffixHash, deduped: true };
288
+ }
289
+ ctx.visited.add(edge.parentSerialized);
290
+ ctx.expanded.add(edge.parentSerialized);
291
+ const childDependents = walkReverse(edge.parentSerialized, ctx);
292
+ ctx.visited.delete(edge.parentSerialized);
293
+ return {
294
+ name,
295
+ displayName,
296
+ version,
297
+ peersSuffixHash,
298
+ dependents: childDependents.length > 0 ? childDependents : undefined,
299
+ };
300
+ }
282
301
  function resolveParentName(edge, ctx) {
283
302
  const graphNode = ctx.graph.nodes.get(edge.parentSerialized);
284
303
  if (graphNode == null)
@@ -301,12 +320,15 @@ function resolveDisplayName(serialized, name, version, ctx) {
301
320
  return ctx.nameFormatter({ name, version, manifest: pkgNode.readManifest() });
302
321
  }
303
322
  function getDepFieldForAlias(alias, importerSnapshot) {
304
- if (importerSnapshot.devDependencies?.[alias] != null)
323
+ if (hasDependency(importerSnapshot.devDependencies, alias))
305
324
  return 'devDependencies';
306
- if (importerSnapshot.optionalDependencies?.[alias] != null)
325
+ if (hasDependency(importerSnapshot.optionalDependencies, alias))
307
326
  return 'optionalDependencies';
308
- if (importerSnapshot.dependencies?.[alias] != null)
327
+ if (hasDependency(importerSnapshot.dependencies, alias))
309
328
  return 'dependencies';
310
329
  return undefined;
311
330
  }
331
+ function hasDependency(dependencies, alias) {
332
+ return dependencies != null && Object.hasOwn(dependencies, alias) && dependencies[alias] != null;
333
+ }
312
334
  //# sourceMappingURL=buildDependentsTree.js.map
@@ -11,22 +11,25 @@ export function createPackagesSearcher(queries, finders) {
11
11
  }
12
12
  if (finders == null)
13
13
  return false;
14
- const messages = [];
15
- let found = false;
16
- for (const finder of finders) {
17
- const result = finder(pkg);
18
- if (result) {
19
- found = true;
20
- if (typeof result === 'string') {
21
- messages.push(result);
22
- }
23
- }
24
- }
25
- if (messages.length)
26
- return messages.join('\n');
27
- return found;
14
+ return runFinders(finders, pkg);
28
15
  };
29
16
  }
17
+ function runFinders(finders, pkg) {
18
+ const messages = [];
19
+ let found = false;
20
+ for (const finder of finders) {
21
+ const result = finder(pkg);
22
+ if (!result)
23
+ continue;
24
+ found = true;
25
+ if (typeof result === 'string') {
26
+ messages.push(result);
27
+ }
28
+ }
29
+ if (messages.length)
30
+ return messages.join('\n');
31
+ return found;
32
+ }
30
33
  function search(packageSelector, { alias, name, version }) {
31
34
  const nameMatches = packageSelector.matchName(name) || packageSelector.matchName(alias);
32
35
  if (!nameMatches) {
package/lib/getPkgInfo.js CHANGED
@@ -7,62 +7,11 @@ import normalizePath from 'normalize-path';
7
7
  import { readManifestFromCafs } from './readManifestFromCafs.js';
8
8
  import { resolvePackagePath } from './resolvePackagePath.js';
9
9
  export function getPkgInfo(opts) {
10
- let name;
11
- let version;
12
- let resolved;
13
- let depType;
14
- let optional;
15
- let isSkipped = false;
16
- let isMissing = false;
17
- let integrity;
18
10
  const depPath = refToRelative(opts.ref, opts.alias);
19
- if (depPath) {
20
- let pkgSnapshot;
21
- if (opts.currentPackages[depPath]) {
22
- pkgSnapshot = opts.currentPackages[depPath];
23
- const parsed = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
24
- name = parsed.name;
25
- version = parsed.version;
26
- }
27
- else {
28
- pkgSnapshot = opts.wantedPackages[depPath];
29
- if (pkgSnapshot) {
30
- const parsed = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
31
- name = parsed.name;
32
- version = parsed.version;
33
- }
34
- else {
35
- name = opts.alias;
36
- version = opts.ref;
37
- }
38
- isMissing = true;
39
- isSkipped = opts.skipped.has(depPath);
40
- }
41
- if (pkgSnapshot) {
42
- try {
43
- resolved = pkgSnapshotToResolution(depPath, pkgSnapshot, { registriesByScope: opts.registriesByScope, registriesByPrefix: opts.registriesByPrefix }).tarball;
44
- }
45
- catch (err) {
46
- // Inspection commands may run without the workspace's registriesByPrefix
47
- // setting (registries come from .modules.yaml); a named-registry entry
48
- // whose alias can't be resolved to a URL just has no tarball to show.
49
- if (err.code !== 'ERR_PNPM_MISSING_NAMED_REGISTRY')
50
- throw err;
51
- }
52
- optional = pkgSnapshot.optional;
53
- if ('integrity' in pkgSnapshot.resolution) {
54
- integrity = pkgSnapshot.resolution.integrity;
55
- }
56
- }
57
- depType = opts.depTypes[depPath];
58
- }
59
- else {
60
- name = opts.alias;
61
- version = opts.ref;
62
- }
63
- if (!version) {
64
- version = opts.ref;
65
- }
11
+ const lockedInfo = depPath
12
+ ? readLockedPackageInfo(depPath, opts)
13
+ : { name: opts.alias, version: opts.ref, isMissing: false, isSkipped: false };
14
+ const { name } = lockedInfo;
66
15
  const fullPackagePath = depPath
67
16
  ? resolvePackagePath({
68
17
  depPath,
@@ -74,41 +23,89 @@ export function getPkgInfo(opts) {
74
23
  parentDir: opts.parentDir,
75
24
  })
76
25
  : resolveLinkedPath(opts);
77
- if (version.startsWith('link:') && opts.rewriteLinkVersionDir) {
78
- version = `link:${normalizePath(path.relative(opts.rewriteLinkVersionDir, fullPackagePath))}`;
26
+ const version = rewriteLinkVersion(lockedInfo.version || opts.ref, fullPackagePath, opts.rewriteLinkVersionDir);
27
+ const pkgInfo = createPackageInfo(opts, { ...lockedInfo, version, path: fullPackagePath });
28
+ return {
29
+ pkgInfo,
30
+ readManifest: () => readManifest(opts, { integrity: lockedInfo.integrity, name, version, path: fullPackagePath }),
31
+ };
32
+ }
33
+ function rewriteLinkVersion(version, fullPackagePath, rewriteLinkVersionDir) {
34
+ if (!version.startsWith('link:') || !rewriteLinkVersionDir)
35
+ return version;
36
+ return `link:${normalizePath(path.relative(rewriteLinkVersionDir, fullPackagePath))}`;
37
+ }
38
+ function readManifest(opts, pkg) {
39
+ if (pkg.integrity && opts.storeDir && opts.storeIndex) {
40
+ const manifest = readManifestFromCafs(opts.storeDir, opts.storeIndex, { integrity: pkg.integrity, name: pkg.name, version: pkg.version });
41
+ if (manifest)
42
+ return manifest;
79
43
  }
44
+ return readPackageJsonFromDirSync(pkg.path);
45
+ }
46
+ function readLockedPackageInfo(depPath, opts) {
47
+ const { pkgSnapshot, ...identity } = findPackageSnapshot(depPath, opts);
48
+ return {
49
+ ...identity,
50
+ ...(pkgSnapshot && readSnapshotDetails(depPath, pkgSnapshot, opts)),
51
+ depType: opts.depTypes[depPath],
52
+ };
53
+ }
54
+ function findPackageSnapshot(depPath, opts) {
55
+ if (opts.currentPackages[depPath]) {
56
+ const pkgSnapshot = opts.currentPackages[depPath];
57
+ const { name, version } = nameVerFromPkgSnapshot(depPath, pkgSnapshot);
58
+ return { pkgSnapshot, name, version, isMissing: false, isSkipped: false };
59
+ }
60
+ const pkgSnapshot = opts.wantedPackages[depPath];
61
+ const { name, version } = pkgSnapshot
62
+ ? nameVerFromPkgSnapshot(depPath, pkgSnapshot)
63
+ : { name: opts.alias, version: opts.ref };
64
+ return { pkgSnapshot, name, version, isMissing: true, isSkipped: opts.skipped.has(depPath) };
65
+ }
66
+ function readSnapshotDetails(depPath, pkgSnapshot, opts) {
67
+ return {
68
+ resolved: readTarballUrl(depPath, pkgSnapshot, opts),
69
+ optional: pkgSnapshot.optional,
70
+ integrity: 'integrity' in pkgSnapshot.resolution ? pkgSnapshot.resolution.integrity : undefined,
71
+ };
72
+ }
73
+ function readTarballUrl(depPath, pkgSnapshot, opts) {
74
+ try {
75
+ return pkgSnapshotToResolution(depPath, pkgSnapshot, { registriesByScope: opts.registriesByScope, registriesByPrefix: opts.registriesByPrefix }).tarball;
76
+ }
77
+ catch (err) {
78
+ // Inspection commands may run without the workspace's registriesByPrefix
79
+ // setting (registries come from .modules.yaml); a named-registry entry
80
+ // whose alias can't be resolved to a URL just has no tarball to show.
81
+ if (err.code !== 'ERR_PNPM_MISSING_NAMED_REGISTRY')
82
+ throw err;
83
+ return undefined;
84
+ }
85
+ }
86
+ function createPackageInfo(opts, info) {
80
87
  const packageInfo = {
81
88
  alias: opts.alias,
82
- isMissing,
89
+ isMissing: info.isMissing,
83
90
  isPeer: Boolean(opts.peers?.has(opts.alias)),
84
- isSkipped,
85
- name,
86
- path: fullPackagePath,
87
- version,
91
+ isSkipped: info.isSkipped,
92
+ name: info.name,
93
+ path: info.path,
94
+ version: info.version,
88
95
  };
89
- if (resolved) {
90
- packageInfo.resolved = resolved;
96
+ if (info.resolved) {
97
+ packageInfo.resolved = info.resolved;
91
98
  }
92
- if (optional === true) {
99
+ if (info.optional === true) {
93
100
  packageInfo.optional = true;
94
101
  }
95
- if (depType === DepType.DevOnly) {
102
+ if (info.depType === DepType.DevOnly) {
96
103
  packageInfo.dev = true;
97
104
  }
98
- else if (depType === DepType.ProdOnly) {
105
+ else if (info.depType === DepType.ProdOnly) {
99
106
  packageInfo.dev = false;
100
107
  }
101
- return {
102
- pkgInfo: packageInfo,
103
- readManifest: () => {
104
- if (integrity && opts.storeDir && opts.storeIndex) {
105
- const manifest = readManifestFromCafs(opts.storeDir, opts.storeIndex, { integrity, name, version });
106
- if (manifest)
107
- return manifest;
108
- }
109
- return readPackageJsonFromDirSync(fullPackagePath);
110
- },
111
- };
108
+ return packageInfo;
112
109
  }
113
110
  function resolveLinkedPath(opts) {
114
111
  const target = packageRootLinkTarget(opts.ref);