@pnpm/deps.inspection.tree-builder 1101.0.6 → 1101.0.8
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 +32 -0
- package/lib/buildDependenciesTree.js +143 -116
- package/lib/buildDependencyGraph.d.ts +3 -2
- package/lib/buildDependencyGraph.js +70 -52
- package/lib/buildDependentsTree.d.ts +10 -7
- package/lib/buildDependentsTree.js +182 -158
- package/lib/createPackagesSearcher.js +17 -14
- package/lib/getPkgInfo.d.ts +3 -1
- package/lib/getPkgInfo.js +83 -80
- package/lib/getTree.js +152 -130
- package/lib/resolvePackagePath.js +34 -32
- package/package.json +12 -12
|
@@ -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,111 @@ 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
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
// Build root IDs from the selected project paths (respects --filter / --recursive)
|
|
60
|
+
const allRootIds = [];
|
|
61
|
+
for (const projectPath of projectPaths) {
|
|
62
|
+
const importerId = getLockfileImporterId(opts.lockfileDir, projectPath);
|
|
63
|
+
if (opts.lockfile.importers[importerId]) {
|
|
64
|
+
allRootIds.push({ type: 'importer', importerId });
|
|
125
65
|
}
|
|
126
|
-
trees.push(tree);
|
|
127
66
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return lexCompare(a.peersSuffixHash ?? '', b.peersSuffixHash ?? '');
|
|
67
|
+
return buildDependencyGraph(allRootIds, {
|
|
68
|
+
currentPackages: opts.lockfile.packages ?? {},
|
|
69
|
+
importers: opts.lockfile.importers,
|
|
70
|
+
include,
|
|
71
|
+
lockfileDir: opts.lockfileDir,
|
|
72
|
+
peerSatisfactionEdges: getPeerSatisfactionEdgesToSkip(opts.lockfile, {
|
|
73
|
+
include,
|
|
74
|
+
resolvePeersFromWorkspaceRoot: opts.resolvePeersFromWorkspaceRoot,
|
|
75
|
+
}),
|
|
138
76
|
});
|
|
139
|
-
|
|
77
|
+
}
|
|
78
|
+
// Scan all package nodes for matches.
|
|
79
|
+
// A package matches if any of the aliases used to refer to it (from incoming
|
|
80
|
+
// edges in the graph) or its canonical name match the search query.
|
|
81
|
+
// Each distinct depPath (i.e. different peer dep resolutions) is kept as a
|
|
82
|
+
// separate result so that peer variants are visible in the output.
|
|
83
|
+
function collectMatchedTrees(search, ctx) {
|
|
84
|
+
const trees = [];
|
|
85
|
+
for (const [serialized, node] of ctx.graph.nodes) {
|
|
86
|
+
if (node.nodeId.type !== 'package')
|
|
87
|
+
continue;
|
|
88
|
+
const tree = buildTreeIfMatched(search, { serialized, depPath: node.nodeId.depPath }, ctx);
|
|
89
|
+
if (tree != null)
|
|
90
|
+
trees.push(tree);
|
|
91
|
+
}
|
|
140
92
|
return trees;
|
|
141
93
|
}
|
|
94
|
+
function buildTreeIfMatched(search, { serialized, depPath }, ctx) {
|
|
95
|
+
const snapshot = ctx.currentPackages[depPath];
|
|
96
|
+
if (snapshot == null)
|
|
97
|
+
return undefined;
|
|
98
|
+
const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot);
|
|
99
|
+
const pkgNode = ctx.resolvedPackageNodes.get(serialized);
|
|
100
|
+
if (!pkgNode)
|
|
101
|
+
return undefined;
|
|
102
|
+
const readManifest = pkgNode.readManifest;
|
|
103
|
+
const matched = searchPackage(search, { serialized, name, version, readManifest }, ctx);
|
|
104
|
+
if (!matched)
|
|
105
|
+
return undefined;
|
|
106
|
+
ctx.visited = new Set([serialized]);
|
|
107
|
+
ctx.expanded = new Set();
|
|
108
|
+
const dependents = walkReverse(serialized, ctx);
|
|
109
|
+
const peersSuffixHash = peersSuffixHashFromDepPath(depPath);
|
|
110
|
+
const displayName = ctx.nameFormatter
|
|
111
|
+
? ctx.nameFormatter({ name, version, manifest: readManifest() })
|
|
112
|
+
: undefined;
|
|
113
|
+
const tree = {
|
|
114
|
+
name,
|
|
115
|
+
displayName,
|
|
116
|
+
version,
|
|
117
|
+
path: pkgNode.path,
|
|
118
|
+
peersSuffixHash,
|
|
119
|
+
dependents,
|
|
120
|
+
};
|
|
121
|
+
if (typeof matched === 'string') {
|
|
122
|
+
tree.searchMessage = matched;
|
|
123
|
+
}
|
|
124
|
+
return tree;
|
|
125
|
+
}
|
|
126
|
+
function searchPackage(search, pkg, ctx) {
|
|
127
|
+
const { name, version, readManifest } = pkg;
|
|
128
|
+
// Check canonical name first
|
|
129
|
+
const matched = search({ alias: name, name, version, readManifest });
|
|
130
|
+
if (matched)
|
|
131
|
+
return matched;
|
|
132
|
+
// Also check aliases from incoming edges (handles npm: protocol aliases)
|
|
133
|
+
for (const edge of ctx.reverseMap.get(pkg.serialized) ?? []) {
|
|
134
|
+
if (edge.alias === name)
|
|
135
|
+
continue;
|
|
136
|
+
const aliasMatched = search({ alias: edge.alias, name, version, readManifest });
|
|
137
|
+
if (aliasMatched)
|
|
138
|
+
return aliasMatched;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
function compareDependentsTrees(left, right) {
|
|
143
|
+
const nameCmp = lexCompare(left.name, right.name);
|
|
144
|
+
if (nameCmp !== 0)
|
|
145
|
+
return nameCmp;
|
|
146
|
+
const versionCmp = semver.valid(left.version) && semver.valid(right.version)
|
|
147
|
+
? semver.compare(left.version, right.version)
|
|
148
|
+
: lexCompare(left.version, right.version);
|
|
149
|
+
if (versionCmp !== 0)
|
|
150
|
+
return versionCmp;
|
|
151
|
+
return lexCompare(left.peersSuffixHash ?? '', right.peersSuffixHash ?? '');
|
|
152
|
+
}
|
|
142
153
|
function invertGraph(graph) {
|
|
143
154
|
const reverse = new Map();
|
|
144
155
|
for (const [parentSerialized, node] of graph.nodes) {
|
|
@@ -207,78 +218,88 @@ function walkReverse(nodeId, ctx) {
|
|
|
207
218
|
return [];
|
|
208
219
|
// Sort edges by parent name (with serialized ID as tiebreaker) so that
|
|
209
220
|
// deduplication is deterministic: the first parent always gets fully expanded.
|
|
210
|
-
const sortedEdges = [...reverseEdges].sort((
|
|
211
|
-
const cmp = lexCompare(resolveParentName(
|
|
221
|
+
const sortedEdges = [...reverseEdges].sort((left, right) => {
|
|
222
|
+
const cmp = lexCompare(resolveParentName(left, ctx), resolveParentName(right, ctx));
|
|
212
223
|
if (cmp !== 0)
|
|
213
224
|
return cmp;
|
|
214
|
-
return lexCompare(
|
|
225
|
+
return lexCompare(left.parentSerialized, right.parentSerialized);
|
|
215
226
|
});
|
|
216
227
|
const dependents = [];
|
|
217
228
|
for (const edge of sortedEdges) {
|
|
218
229
|
// 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
|
-
}
|
|
230
|
+
const dependent = ctx.visited.has(edge.parentSerialized)
|
|
231
|
+
? createCircularDependent(edge, ctx)
|
|
232
|
+
: createDependent(edge, ctx);
|
|
233
|
+
if (dependent != null)
|
|
234
|
+
dependents.push(dependent);
|
|
279
235
|
}
|
|
280
236
|
return dependents;
|
|
281
237
|
}
|
|
238
|
+
function createCircularDependent(edge, ctx) {
|
|
239
|
+
const parentNode = ctx.graph.nodes.get(edge.parentSerialized);
|
|
240
|
+
if (parentNode?.nodeId.type === 'importer') {
|
|
241
|
+
const info = ctx.importerInfoMap.get(parentNode.nodeId.importerId);
|
|
242
|
+
if (!info)
|
|
243
|
+
return undefined;
|
|
244
|
+
return {
|
|
245
|
+
name: info.name,
|
|
246
|
+
version: info.version,
|
|
247
|
+
circular: true,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
if (parentNode?.nodeId.type !== 'package')
|
|
251
|
+
return undefined;
|
|
252
|
+
const snapshot = ctx.currentPackages[parentNode.nodeId.depPath];
|
|
253
|
+
if (!snapshot)
|
|
254
|
+
return undefined;
|
|
255
|
+
const { name, version } = nameVerFromPkgSnapshot(parentNode.nodeId.depPath, snapshot);
|
|
256
|
+
const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
|
|
257
|
+
return { name, displayName, version, circular: true };
|
|
258
|
+
}
|
|
259
|
+
function createDependent(edge, ctx) {
|
|
260
|
+
const parentGraphNode = ctx.graph.nodes.get(edge.parentSerialized);
|
|
261
|
+
if (parentGraphNode == null)
|
|
262
|
+
return undefined;
|
|
263
|
+
const parentNodeId = parentGraphNode.nodeId;
|
|
264
|
+
if (parentNodeId.type === 'importer') {
|
|
265
|
+
const importerId = parentNodeId.importerId;
|
|
266
|
+
const info = ctx.importerInfoMap.get(importerId) ?? { name: importerId, version: '' };
|
|
267
|
+
const depField = getDepFieldForAlias(edge.alias, ctx.importers[importerId]);
|
|
268
|
+
return {
|
|
269
|
+
name: info.name,
|
|
270
|
+
version: info.version,
|
|
271
|
+
depField,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
if (parentNodeId.type === 'package') {
|
|
275
|
+
return createPackageDependent(edge, parentNodeId.depPath, ctx);
|
|
276
|
+
}
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
function createPackageDependent(edge, depPath, ctx) {
|
|
280
|
+
const snapshot = ctx.currentPackages[depPath];
|
|
281
|
+
if (snapshot == null)
|
|
282
|
+
return undefined;
|
|
283
|
+
const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot);
|
|
284
|
+
const peersSuffixHash = peersSuffixHashFromDepPath(depPath);
|
|
285
|
+
// Deduplication: if this package was already expanded elsewhere in the
|
|
286
|
+
// tree, show it as a leaf to keep the output bounded.
|
|
287
|
+
const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
|
|
288
|
+
if (ctx.expanded.has(edge.parentSerialized)) {
|
|
289
|
+
return { name, displayName, version, peersSuffixHash, deduped: true };
|
|
290
|
+
}
|
|
291
|
+
ctx.visited.add(edge.parentSerialized);
|
|
292
|
+
ctx.expanded.add(edge.parentSerialized);
|
|
293
|
+
const childDependents = walkReverse(edge.parentSerialized, ctx);
|
|
294
|
+
ctx.visited.delete(edge.parentSerialized);
|
|
295
|
+
return {
|
|
296
|
+
name,
|
|
297
|
+
displayName,
|
|
298
|
+
version,
|
|
299
|
+
peersSuffixHash,
|
|
300
|
+
dependents: childDependents.length > 0 ? childDependents : undefined,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
282
303
|
function resolveParentName(edge, ctx) {
|
|
283
304
|
const graphNode = ctx.graph.nodes.get(edge.parentSerialized);
|
|
284
305
|
if (graphNode == null)
|
|
@@ -301,12 +322,15 @@ function resolveDisplayName(serialized, name, version, ctx) {
|
|
|
301
322
|
return ctx.nameFormatter({ name, version, manifest: pkgNode.readManifest() });
|
|
302
323
|
}
|
|
303
324
|
function getDepFieldForAlias(alias, importerSnapshot) {
|
|
304
|
-
if (importerSnapshot.devDependencies
|
|
325
|
+
if (hasDependency(importerSnapshot.devDependencies, alias))
|
|
305
326
|
return 'devDependencies';
|
|
306
|
-
if (importerSnapshot.optionalDependencies
|
|
327
|
+
if (hasDependency(importerSnapshot.optionalDependencies, alias))
|
|
307
328
|
return 'optionalDependencies';
|
|
308
|
-
if (importerSnapshot.dependencies
|
|
329
|
+
if (hasDependency(importerSnapshot.dependencies, alias))
|
|
309
330
|
return 'dependencies';
|
|
310
331
|
return undefined;
|
|
311
332
|
}
|
|
333
|
+
function hasDependency(dependencies, alias) {
|
|
334
|
+
return dependencies != null && Object.hasOwn(dependencies, alias) && dependencies[alias] != null;
|
|
335
|
+
}
|
|
312
336
|
//# 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.d.ts
CHANGED
|
@@ -17,7 +17,9 @@ export interface GetPkgInfoOpts {
|
|
|
17
17
|
readonly virtualStoreDirMaxLength: number;
|
|
18
18
|
readonly depTypes: DepTypes;
|
|
19
19
|
/**
|
|
20
|
-
* The base dir if the `ref` argument is a `"link:"` relative path.
|
|
20
|
+
* The base dir if the `ref` argument is a `"link:"` relative path. An
|
|
21
|
+
* absolute `"link:"` path, such as one on another drive on Windows, is used
|
|
22
|
+
* as is.
|
|
21
23
|
*/
|
|
22
24
|
readonly linkedPathBaseDir: string;
|
|
23
25
|
/**
|
package/lib/getPkgInfo.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { refToRelative } from '@pnpm/deps.path';
|
|
2
|
+
import { packageRootLinkTarget, refToRelative } from '@pnpm/deps.path';
|
|
3
3
|
import { DepType } from '@pnpm/lockfile.detect-dep-types';
|
|
4
4
|
import { nameVerFromPkgSnapshot, pkgSnapshotToResolution, } from '@pnpm/lockfile.utils';
|
|
5
5
|
import { readPackageJsonFromDirSync } from '@pnpm/pkg-manifest.reader';
|
|
@@ -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,
|
|
@@ -73,41 +22,95 @@ export function getPkgInfo(opts) {
|
|
|
73
22
|
modulesDir: opts.modulesDir,
|
|
74
23
|
parentDir: opts.parentDir,
|
|
75
24
|
})
|
|
76
|
-
:
|
|
77
|
-
|
|
78
|
-
|
|
25
|
+
: resolveLinkedPath(opts);
|
|
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;
|
|
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;
|
|
79
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
return readPackageJsonFromDirSync(fullPackagePath);
|
|
110
|
-
},
|
|
111
|
-
};
|
|
108
|
+
return packageInfo;
|
|
109
|
+
}
|
|
110
|
+
function resolveLinkedPath(opts) {
|
|
111
|
+
const target = packageRootLinkTarget(opts.ref);
|
|
112
|
+
return target != null && opts.parentDir != null
|
|
113
|
+
? path.join(opts.parentDir, target)
|
|
114
|
+
: path.resolve(opts.linkedPathBaseDir, opts.ref.slice(5));
|
|
112
115
|
}
|
|
113
116
|
//# sourceMappingURL=getPkgInfo.js.map
|