@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.
- package/CHANGELOG.md +19 -0
- package/lib/buildDependenciesTree.js +142 -119
- package/lib/buildDependencyGraph.d.ts +3 -2
- package/lib/buildDependencyGraph.js +70 -52
- package/lib/buildDependentsTree.d.ts +10 -7
- package/lib/buildDependentsTree.js +180 -158
- package/lib/createPackagesSearcher.js +17 -14
- package/lib/getPkgInfo.js +75 -78
- package/lib/getTree.js +151 -136
- package/lib/resolvePackagePath.js +34 -32
- package/package.json +6 -6
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
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((
|
|
211
|
-
const cmp = lexCompare(resolveParentName(
|
|
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(
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
|
323
|
+
if (hasDependency(importerSnapshot.devDependencies, alias))
|
|
305
324
|
return 'devDependencies';
|
|
306
|
-
if (importerSnapshot.optionalDependencies
|
|
325
|
+
if (hasDependency(importerSnapshot.optionalDependencies, alias))
|
|
307
326
|
return 'optionalDependencies';
|
|
308
|
-
if (importerSnapshot.dependencies
|
|
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
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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:
|
|
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);
|