@pnpm/reviewing.dependencies-hierarchy 1001.2.7 → 1001.3.0
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/lib/{PackageNode.d.ts → DependencyNode.d.ts} +8 -2
- package/lib/{PackageNode.js → DependencyNode.js} +1 -1
- package/lib/DependencyNode.js.map +1 -0
- package/lib/{buildDependenciesHierarchy.d.ts → buildDependenciesTree.d.ts} +8 -8
- package/lib/buildDependenciesTree.js +184 -0
- package/lib/buildDependenciesTree.js.map +1 -0
- package/lib/buildDependencyGraph.d.ts +1 -1
- package/lib/buildDependencyGraph.js +2 -2
- package/lib/buildDependencyGraph.js.map +1 -1
- package/lib/buildDependentsTree.d.ts +46 -0
- package/lib/buildDependentsTree.js +311 -0
- package/lib/buildDependentsTree.js.map +1 -0
- package/lib/getPkgInfo.d.ts +1 -0
- package/lib/getPkgInfo.js +24 -35
- package/lib/getPkgInfo.js.map +1 -1
- package/lib/getTree.d.ts +13 -10
- package/lib/getTree.js +18 -7
- package/lib/getTree.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.js +5 -3
- package/lib/index.js.map +1 -1
- package/lib/peersSuffixHash.d.ts +1 -0
- package/lib/peersSuffixHash.js +15 -0
- package/lib/peersSuffixHash.js.map +1 -0
- package/lib/readManifestFromCafs.d.ts +10 -0
- package/lib/readManifestFromCafs.js +27 -0
- package/lib/readManifestFromCafs.js.map +1 -0
- package/lib/resolvePackagePath.d.ts +16 -0
- package/lib/resolvePackagePath.js +53 -0
- package/lib/resolvePackagePath.js.map +1 -0
- package/package.json +7 -5
- package/lib/PackageNode.js.map +0 -1
- package/lib/buildDependenciesHierarchy.js +0 -232
- package/lib/buildDependenciesHierarchy.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface DependencyNode {
|
|
2
2
|
alias: string;
|
|
3
3
|
circular?: true;
|
|
4
4
|
deduped?: true;
|
|
@@ -7,7 +7,13 @@ export interface PackageNode {
|
|
|
7
7
|
* elided because this subtree was already expanded elsewhere in the tree.
|
|
8
8
|
*/
|
|
9
9
|
dedupedDependenciesCount?: number;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Short hash of the peer dependency suffix in the depPath, used to
|
|
12
|
+
* distinguish deduped instances of the same package with different
|
|
13
|
+
* peer dependency resolutions.
|
|
14
|
+
*/
|
|
15
|
+
peersSuffixHash?: string;
|
|
16
|
+
dependencies?: DependencyNode[];
|
|
11
17
|
dev?: boolean;
|
|
12
18
|
isPeer: boolean;
|
|
13
19
|
isSkipped: boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DependencyNode.js","sourceRoot":"","sources":["../src/DependencyNode.ts"],"names":[],"mappings":""}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type DependenciesField, type Finder, type Registries } from '@pnpm/types';
|
|
2
|
-
import { type
|
|
3
|
-
export interface
|
|
4
|
-
dependencies?:
|
|
5
|
-
devDependencies?:
|
|
6
|
-
optionalDependencies?:
|
|
7
|
-
unsavedDependencies?:
|
|
2
|
+
import { type DependencyNode } from './DependencyNode.js';
|
|
3
|
+
export interface DependenciesTree {
|
|
4
|
+
dependencies?: DependencyNode[];
|
|
5
|
+
devDependencies?: DependencyNode[];
|
|
6
|
+
optionalDependencies?: DependencyNode[];
|
|
7
|
+
unsavedDependencies?: DependencyNode[];
|
|
8
8
|
}
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function buildDependenciesTree(projectPaths: string[] | undefined, maybeOpts: {
|
|
10
10
|
depth: number;
|
|
11
11
|
excludePeerDependencies?: boolean;
|
|
12
12
|
include?: {
|
|
@@ -21,5 +21,5 @@ export declare function buildDependenciesHierarchy(projectPaths: string[] | unde
|
|
|
21
21
|
modulesDir?: string;
|
|
22
22
|
virtualStoreDirMaxLength: number;
|
|
23
23
|
}): Promise<{
|
|
24
|
-
[projectDir: string]:
|
|
24
|
+
[projectDir: string]: DependenciesTree;
|
|
25
25
|
}>;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildDependenciesTree = buildDependenciesTree;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const lockfile_fs_1 = require("@pnpm/lockfile.fs");
|
|
9
|
+
const lockfile_detect_dep_types_1 = require("@pnpm/lockfile.detect-dep-types");
|
|
10
|
+
const modules_yaml_1 = require("@pnpm/modules-yaml");
|
|
11
|
+
const normalize_registries_1 = require("@pnpm/normalize-registries");
|
|
12
|
+
const read_modules_dir_1 = require("@pnpm/read-modules-dir");
|
|
13
|
+
const read_package_json_1 = require("@pnpm/read-package-json");
|
|
14
|
+
const types_1 = require("@pnpm/types");
|
|
15
|
+
const normalize_path_1 = __importDefault(require("normalize-path"));
|
|
16
|
+
const realpath_missing_1 = __importDefault(require("realpath-missing"));
|
|
17
|
+
const resolve_link_target_1 = __importDefault(require("resolve-link-target"));
|
|
18
|
+
const buildDependencyGraph_js_1 = require("./buildDependencyGraph.js");
|
|
19
|
+
const getTree_js_1 = require("./getTree.js");
|
|
20
|
+
async function buildDependenciesTree(projectPaths, maybeOpts) {
|
|
21
|
+
if (!maybeOpts?.lockfileDir) {
|
|
22
|
+
throw new TypeError('opts.lockfileDir is required');
|
|
23
|
+
}
|
|
24
|
+
const modulesDir = await (0, realpath_missing_1.default)(path_1.default.join(maybeOpts.lockfileDir, maybeOpts.modulesDir ?? 'node_modules'));
|
|
25
|
+
const modules = await (0, modules_yaml_1.readModulesManifest)(modulesDir);
|
|
26
|
+
const registries = (0, normalize_registries_1.normalizeRegistries)({
|
|
27
|
+
...maybeOpts?.registries,
|
|
28
|
+
...modules?.registries,
|
|
29
|
+
});
|
|
30
|
+
const internalPnpmDir = path_1.default.join(modulesDir, '.pnpm');
|
|
31
|
+
const currentLockfile = await (0, lockfile_fs_1.readCurrentLockfile)(internalPnpmDir, { ignoreIncompatible: false });
|
|
32
|
+
const wantedLockfile = await (0, lockfile_fs_1.readWantedLockfile)(maybeOpts.lockfileDir, { ignoreIncompatible: false });
|
|
33
|
+
if (projectPaths == null) {
|
|
34
|
+
projectPaths = Object.keys(wantedLockfile?.importers ?? {})
|
|
35
|
+
.map((id) => path_1.default.join(maybeOpts.lockfileDir, id));
|
|
36
|
+
}
|
|
37
|
+
const result = {};
|
|
38
|
+
const lockfileToUse = maybeOpts.checkWantedLockfileOnly ? wantedLockfile : currentLockfile;
|
|
39
|
+
if (!lockfileToUse) {
|
|
40
|
+
for (const projectPath of projectPaths) {
|
|
41
|
+
result[projectPath] = {};
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
const opts = {
|
|
46
|
+
depth: maybeOpts.depth || 0,
|
|
47
|
+
excludePeerDependencies: maybeOpts.excludePeerDependencies,
|
|
48
|
+
include: maybeOpts.include ?? {
|
|
49
|
+
dependencies: true,
|
|
50
|
+
devDependencies: true,
|
|
51
|
+
optionalDependencies: true,
|
|
52
|
+
},
|
|
53
|
+
lockfileDir: maybeOpts.lockfileDir,
|
|
54
|
+
checkWantedLockfileOnly: maybeOpts.checkWantedLockfileOnly,
|
|
55
|
+
onlyProjects: maybeOpts.onlyProjects,
|
|
56
|
+
registries,
|
|
57
|
+
search: maybeOpts.search,
|
|
58
|
+
showDedupedSearchMatches: maybeOpts.showDedupedSearchMatches ?? (maybeOpts.search != null),
|
|
59
|
+
skipped: new Set(modules?.skipped ?? []),
|
|
60
|
+
storeDir: modules?.storeDir,
|
|
61
|
+
modulesDir,
|
|
62
|
+
virtualStoreDir: modules?.virtualStoreDir,
|
|
63
|
+
virtualStoreDirMaxLength: modules?.virtualStoreDirMaxLength ?? maybeOpts.virtualStoreDirMaxLength,
|
|
64
|
+
};
|
|
65
|
+
// Build the dependency graph ONCE for all importers and share a single
|
|
66
|
+
// MaterializationCache so that identical subtrees are only materialized once.
|
|
67
|
+
const allRootIds = [];
|
|
68
|
+
for (const projectPath of projectPaths) {
|
|
69
|
+
const importerId = (0, lockfile_fs_1.getLockfileImporterId)(opts.lockfileDir, projectPath);
|
|
70
|
+
if (lockfileToUse.importers[importerId]) {
|
|
71
|
+
allRootIds.push({ type: 'importer', importerId });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const sharedGraph = (0, buildDependencyGraph_js_1.buildDependencyGraph)(allRootIds, {
|
|
75
|
+
currentPackages: lockfileToUse.packages ?? {},
|
|
76
|
+
importers: lockfileToUse.importers,
|
|
77
|
+
include: opts.include,
|
|
78
|
+
lockfileDir: opts.lockfileDir,
|
|
79
|
+
});
|
|
80
|
+
const sharedMaterializationCache = new Map();
|
|
81
|
+
const sharedDepTypes = (0, lockfile_detect_dep_types_1.detectDepTypes)(lockfileToUse);
|
|
82
|
+
const ctx = {
|
|
83
|
+
currentLockfile: lockfileToUse,
|
|
84
|
+
wantedLockfile,
|
|
85
|
+
...opts,
|
|
86
|
+
graph: sharedGraph,
|
|
87
|
+
materializationCache: sharedMaterializationCache,
|
|
88
|
+
depTypes: sharedDepTypes,
|
|
89
|
+
};
|
|
90
|
+
const getHierarchy = dependenciesHierarchyForPackage.bind(null, ctx);
|
|
91
|
+
const pairs = await Promise.all(projectPaths.map(async (projectPath) => {
|
|
92
|
+
return [
|
|
93
|
+
projectPath,
|
|
94
|
+
await getHierarchy(projectPath),
|
|
95
|
+
];
|
|
96
|
+
}));
|
|
97
|
+
for (const [projectPath, dependenciesHierarchy] of pairs) {
|
|
98
|
+
result[projectPath] = dependenciesHierarchy;
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
async function dependenciesHierarchyForPackage(opts, projectPath) {
|
|
103
|
+
const { currentLockfile, wantedLockfile } = opts;
|
|
104
|
+
const importerId = (0, lockfile_fs_1.getLockfileImporterId)(opts.lockfileDir, projectPath);
|
|
105
|
+
if (!currentLockfile.importers[importerId])
|
|
106
|
+
return {};
|
|
107
|
+
const modulesDir = opts.modulesDir && path_1.default.isAbsolute(opts.modulesDir)
|
|
108
|
+
? opts.modulesDir
|
|
109
|
+
: path_1.default.join(projectPath, opts.modulesDir ?? 'node_modules');
|
|
110
|
+
const currentPackages = currentLockfile.packages ?? {};
|
|
111
|
+
const wantedPackages = wantedLockfile?.packages ?? {};
|
|
112
|
+
// Build a map from alias → dependency field for post-categorization.
|
|
113
|
+
const result = {};
|
|
114
|
+
const fieldMap = new Map();
|
|
115
|
+
for (const field of types_1.DEPENDENCIES_FIELDS.sort().filter(f => opts.include[f])) {
|
|
116
|
+
result[field] = [];
|
|
117
|
+
const fieldDeps = currentLockfile.importers[importerId][field] ?? {};
|
|
118
|
+
for (const alias in fieldDeps) {
|
|
119
|
+
fieldMap.set(alias, field);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const parentId = { type: 'importer', importerId };
|
|
123
|
+
// Materialize the tree rooted at this importer in a single getTree call.
|
|
124
|
+
// materializeChildren handles all dedup, search, and circular detection.
|
|
125
|
+
// The depth is incremented by 1 because the importer itself is one level;
|
|
126
|
+
// opts.depth controls how deep *below* the direct dependencies we go.
|
|
127
|
+
const nodes = (0, getTree_js_1.getTree)({
|
|
128
|
+
...opts,
|
|
129
|
+
currentPackages,
|
|
130
|
+
importers: currentLockfile.importers,
|
|
131
|
+
rewriteLinkVersionDir: projectPath,
|
|
132
|
+
maxDepth: opts.depth + 1,
|
|
133
|
+
wantedPackages,
|
|
134
|
+
modulesDir,
|
|
135
|
+
}, parentId);
|
|
136
|
+
// Categorize the materialized nodes into their dependency fields.
|
|
137
|
+
for (const node of nodes) {
|
|
138
|
+
const field = fieldMap.get(node.alias);
|
|
139
|
+
if (field != null) {
|
|
140
|
+
result[field].push(node);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Handle unsaved dependencies (packages in node_modules but not in lockfile).
|
|
144
|
+
// When searching, unsaved deps are irrelevant — they aren't in the lockfile
|
|
145
|
+
// graph and can't have dependency subtrees showing paths to the search target.
|
|
146
|
+
if (!opts.search) {
|
|
147
|
+
const savedDeps = getAllDirectDependencies(currentLockfile.importers[importerId]);
|
|
148
|
+
const unsavedDeps = ((await (0, read_modules_dir_1.readModulesDir)(modulesDir)) ?? []).filter((directDep) => !savedDeps[directDep]);
|
|
149
|
+
if (unsavedDeps.length > 0)
|
|
150
|
+
await Promise.all(unsavedDeps.map(async (unsavedDep) => {
|
|
151
|
+
let pkgPath = path_1.default.join(modulesDir, unsavedDep);
|
|
152
|
+
let version;
|
|
153
|
+
try {
|
|
154
|
+
pkgPath = await (0, resolve_link_target_1.default)(pkgPath);
|
|
155
|
+
version = `link:${(0, normalize_path_1.default)(path_1.default.relative(projectPath, pkgPath))}`;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// if error happened. The package is not a link
|
|
159
|
+
const pkg = await (0, read_package_json_1.safeReadPackageJsonFromDir)(pkgPath);
|
|
160
|
+
version = pkg?.version ?? 'undefined';
|
|
161
|
+
}
|
|
162
|
+
const pkg = {
|
|
163
|
+
alias: unsavedDep,
|
|
164
|
+
isMissing: false,
|
|
165
|
+
isPeer: false,
|
|
166
|
+
isSkipped: false,
|
|
167
|
+
name: unsavedDep,
|
|
168
|
+
path: pkgPath,
|
|
169
|
+
version,
|
|
170
|
+
};
|
|
171
|
+
result.unsavedDependencies = result.unsavedDependencies ?? [];
|
|
172
|
+
result.unsavedDependencies.push(pkg);
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
function getAllDirectDependencies(projectSnapshot) {
|
|
178
|
+
return {
|
|
179
|
+
...projectSnapshot.dependencies,
|
|
180
|
+
...projectSnapshot.devDependencies,
|
|
181
|
+
...projectSnapshot.optionalDependencies,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=buildDependenciesTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildDependenciesTree.js","sourceRoot":"","sources":["../src/buildDependenciesTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ interface DependencyGraphNode {
|
|
|
16
16
|
export interface DependencyGraph {
|
|
17
17
|
nodes: Map<string, DependencyGraphNode>;
|
|
18
18
|
}
|
|
19
|
-
export declare function buildDependencyGraph(
|
|
19
|
+
export declare function buildDependencyGraph(rootIds: TreeNodeId[], opts: {
|
|
20
20
|
currentPackages: PackageSnapshots;
|
|
21
21
|
importers: Record<string, ProjectSnapshot>;
|
|
22
22
|
include: {
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.buildDependencyGraph = buildDependencyGraph;
|
|
4
4
|
const getTreeNodeChildId_js_1 = require("./getTreeNodeChildId.js");
|
|
5
5
|
const TreeNodeId_js_1 = require("./TreeNodeId.js");
|
|
6
|
-
function buildDependencyGraph(
|
|
6
|
+
function buildDependencyGraph(rootIds, opts) {
|
|
7
7
|
const graph = { nodes: new Map() };
|
|
8
|
-
const queue = [
|
|
8
|
+
const queue = [...rootIds];
|
|
9
9
|
let queueIdx = 0;
|
|
10
10
|
const visited = new Set();
|
|
11
11
|
while (queueIdx < queue.length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildDependencyGraph.js","sourceRoot":"","sources":["../src/buildDependencyGraph.ts"],"names":[],"mappings":";;AAuBA,oDA4EC;AAlGD,mEAA4D;AAC5D,mDAAsE;AAqBtE,SAAgB,oBAAoB,CAClC,
|
|
1
|
+
{"version":3,"file":"buildDependencyGraph.js","sourceRoot":"","sources":["../src/buildDependencyGraph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type LockfileObject } from '@pnpm/lockfile.fs';
|
|
2
|
+
import { type DependenciesField, type DependencyManifest, type Finder, type Registries } from '@pnpm/types';
|
|
3
|
+
export interface DependentNode {
|
|
4
|
+
name: string;
|
|
5
|
+
displayName?: string;
|
|
6
|
+
version: string;
|
|
7
|
+
dependents?: DependentNode[];
|
|
8
|
+
circular?: true;
|
|
9
|
+
deduped?: true;
|
|
10
|
+
/** Short hash distinguishing peer-dep variants of the same name@version */
|
|
11
|
+
peersSuffixHash?: string;
|
|
12
|
+
/** For importer leaf nodes: which dep field */
|
|
13
|
+
depField?: DependenciesField;
|
|
14
|
+
}
|
|
15
|
+
export interface DependentsTree {
|
|
16
|
+
name: string;
|
|
17
|
+
displayName?: string;
|
|
18
|
+
version: string;
|
|
19
|
+
/** Resolved filesystem path to this package */
|
|
20
|
+
path?: string;
|
|
21
|
+
/** Short hash distinguishing peer-dep variants of the same name@version */
|
|
22
|
+
peersSuffixHash?: string;
|
|
23
|
+
/** Message returned by the finder function, if any */
|
|
24
|
+
searchMessage?: string;
|
|
25
|
+
dependents: DependentNode[];
|
|
26
|
+
}
|
|
27
|
+
export interface ImporterInfo {
|
|
28
|
+
name: string;
|
|
29
|
+
version: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function buildDependentsTree(packages: string[], projectPaths: string[], opts: {
|
|
32
|
+
lockfileDir: string;
|
|
33
|
+
include?: {
|
|
34
|
+
[field in DependenciesField]?: boolean;
|
|
35
|
+
};
|
|
36
|
+
modulesDir?: string;
|
|
37
|
+
registries?: Registries;
|
|
38
|
+
finders?: Finder[];
|
|
39
|
+
importerInfoMap: Map<string, ImporterInfo>;
|
|
40
|
+
lockfile: LockfileObject;
|
|
41
|
+
nameFormatter?: (info: {
|
|
42
|
+
name: string;
|
|
43
|
+
version: string;
|
|
44
|
+
manifest: DependencyManifest;
|
|
45
|
+
}) => string | undefined;
|
|
46
|
+
}): Promise<DependentsTree[]>;
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildDependentsTree = buildDependentsTree;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const lockfile_fs_1 = require("@pnpm/lockfile.fs");
|
|
9
|
+
const lockfile_utils_1 = require("@pnpm/lockfile.utils");
|
|
10
|
+
const modules_yaml_1 = require("@pnpm/modules-yaml");
|
|
11
|
+
const normalize_registries_1 = require("@pnpm/normalize-registries");
|
|
12
|
+
const util_lex_comparator_1 = require("@pnpm/util.lex-comparator");
|
|
13
|
+
const semver_1 = __importDefault(require("semver"));
|
|
14
|
+
const realpath_missing_1 = __importDefault(require("realpath-missing"));
|
|
15
|
+
const buildDependencyGraph_js_1 = require("./buildDependencyGraph.js");
|
|
16
|
+
const createPackagesSearcher_js_1 = require("./createPackagesSearcher.js");
|
|
17
|
+
const peersSuffixHash_js_1 = require("./peersSuffixHash.js");
|
|
18
|
+
const getPkgInfo_js_1 = require("./getPkgInfo.js");
|
|
19
|
+
async function buildDependentsTree(packages, projectPaths, opts) {
|
|
20
|
+
const modulesDir = await (0, realpath_missing_1.default)(path_1.default.join(opts.lockfileDir, opts.modulesDir ?? 'node_modules'));
|
|
21
|
+
const modules = await (0, modules_yaml_1.readModulesManifest)(modulesDir);
|
|
22
|
+
const registries = (0, normalize_registries_1.normalizeRegistries)({
|
|
23
|
+
...opts.registries,
|
|
24
|
+
...modules?.registries,
|
|
25
|
+
});
|
|
26
|
+
const storeDir = modules?.storeDir;
|
|
27
|
+
const virtualStoreDir = modules?.virtualStoreDir ?? path_1.default.join(modulesDir, '.pnpm');
|
|
28
|
+
const virtualStoreDirMaxLength = modules?.virtualStoreDirMaxLength ?? 120;
|
|
29
|
+
const include = opts.include ?? {
|
|
30
|
+
dependencies: true,
|
|
31
|
+
devDependencies: true,
|
|
32
|
+
optionalDependencies: true,
|
|
33
|
+
};
|
|
34
|
+
// Build root IDs from the selected project paths (respects --filter / --recursive)
|
|
35
|
+
const allRootIds = [];
|
|
36
|
+
for (const projectPath of projectPaths) {
|
|
37
|
+
const importerId = (0, lockfile_fs_1.getLockfileImporterId)(opts.lockfileDir, projectPath);
|
|
38
|
+
if (opts.lockfile.importers[importerId]) {
|
|
39
|
+
allRootIds.push({ type: 'importer', importerId });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const graph = (0, buildDependencyGraph_js_1.buildDependencyGraph)(allRootIds, {
|
|
43
|
+
currentPackages: opts.lockfile.packages ?? {},
|
|
44
|
+
importers: opts.lockfile.importers,
|
|
45
|
+
include,
|
|
46
|
+
lockfileDir: opts.lockfileDir,
|
|
47
|
+
});
|
|
48
|
+
const reverseMap = invertGraph(graph);
|
|
49
|
+
const search = (0, createPackagesSearcher_js_1.createPackagesSearcher)(packages, opts.finders);
|
|
50
|
+
const currentPackages = opts.lockfile.packages ?? {};
|
|
51
|
+
// Pre-compute resolved filesystem paths for all package nodes by walking the
|
|
52
|
+
// graph top-down from importers. This is needed for global virtual store
|
|
53
|
+
// where symlinks must be resolved through each parent's node_modules.
|
|
54
|
+
const resolvedPackageNodes = resolvePackageNodes(graph, currentPackages, {
|
|
55
|
+
virtualStoreDir,
|
|
56
|
+
virtualStoreDirMaxLength,
|
|
57
|
+
modulesDir,
|
|
58
|
+
registries,
|
|
59
|
+
wantedPackages: currentPackages,
|
|
60
|
+
storeDir,
|
|
61
|
+
});
|
|
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 = {
|
|
69
|
+
reverseMap,
|
|
70
|
+
graph,
|
|
71
|
+
importers: opts.lockfile.importers,
|
|
72
|
+
currentPackages,
|
|
73
|
+
importerInfoMap: opts.importerInfoMap,
|
|
74
|
+
resolvedPackageNodes,
|
|
75
|
+
nameFormatter: opts.nameFormatter,
|
|
76
|
+
visited: new Set(),
|
|
77
|
+
expanded: new Set(),
|
|
78
|
+
};
|
|
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 } = (0, lockfile_utils_1.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 = (0, peersSuffixHash_js_1.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;
|
|
125
|
+
}
|
|
126
|
+
trees.push(tree);
|
|
127
|
+
}
|
|
128
|
+
trees.sort((a, b) => {
|
|
129
|
+
const nameCmp = (0, util_lex_comparator_1.lexCompare)(a.name, b.name);
|
|
130
|
+
if (nameCmp !== 0)
|
|
131
|
+
return nameCmp;
|
|
132
|
+
const versionCmp = semver_1.default.valid(a.version) && semver_1.default.valid(b.version)
|
|
133
|
+
? semver_1.default.compare(a.version, b.version)
|
|
134
|
+
: (0, util_lex_comparator_1.lexCompare)(a.version, b.version);
|
|
135
|
+
if (versionCmp !== 0)
|
|
136
|
+
return versionCmp;
|
|
137
|
+
return (0, util_lex_comparator_1.lexCompare)(a.peersSuffixHash ?? '', b.peersSuffixHash ?? '');
|
|
138
|
+
});
|
|
139
|
+
return trees;
|
|
140
|
+
}
|
|
141
|
+
function invertGraph(graph) {
|
|
142
|
+
const reverse = new Map();
|
|
143
|
+
for (const [parentSerialized, node] of graph.nodes) {
|
|
144
|
+
for (const edge of node.edges) {
|
|
145
|
+
if (edge.target == null)
|
|
146
|
+
continue;
|
|
147
|
+
const childSerialized = edge.target.id;
|
|
148
|
+
let entries = reverse.get(childSerialized);
|
|
149
|
+
if (entries == null) {
|
|
150
|
+
entries = [];
|
|
151
|
+
reverse.set(childSerialized, entries);
|
|
152
|
+
}
|
|
153
|
+
entries.push({
|
|
154
|
+
parentSerialized,
|
|
155
|
+
parentNodeId: node.nodeId,
|
|
156
|
+
alias: edge.alias,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return reverse;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Walks the dependency graph top-down from importer nodes and resolves the
|
|
164
|
+
* filesystem path for every package node. This is necessary for global virtual
|
|
165
|
+
* store where the correct path can only be obtained by following symlinks
|
|
166
|
+
* through each parent's node_modules directory.
|
|
167
|
+
*/
|
|
168
|
+
function resolvePackageNodes(graph, currentPackages, opts) {
|
|
169
|
+
const resolved = new Map();
|
|
170
|
+
function walk(serialized, parentDir) {
|
|
171
|
+
const node = graph.nodes.get(serialized);
|
|
172
|
+
if (!node)
|
|
173
|
+
return;
|
|
174
|
+
for (const edge of node.edges) {
|
|
175
|
+
if (edge.target == null)
|
|
176
|
+
continue;
|
|
177
|
+
const childSerialized = edge.target.id;
|
|
178
|
+
if (resolved.has(childSerialized))
|
|
179
|
+
continue;
|
|
180
|
+
if (edge.target.nodeId.type !== 'package')
|
|
181
|
+
continue;
|
|
182
|
+
const { pkgInfo, readManifest } = (0, getPkgInfo_js_1.getPkgInfo)({
|
|
183
|
+
...opts,
|
|
184
|
+
alias: edge.alias,
|
|
185
|
+
currentPackages,
|
|
186
|
+
depTypes: {},
|
|
187
|
+
linkedPathBaseDir: opts.modulesDir, // This might need adjustment for linked deps?
|
|
188
|
+
parentDir,
|
|
189
|
+
ref: edge.target.nodeId.depPath,
|
|
190
|
+
skipped: new Set(),
|
|
191
|
+
});
|
|
192
|
+
resolved.set(childSerialized, { path: pkgInfo.path, readManifest });
|
|
193
|
+
walk(childSerialized, pkgInfo.path);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
for (const [serialized, node] of graph.nodes) {
|
|
197
|
+
if (node.nodeId.type === 'importer') {
|
|
198
|
+
walk(serialized, undefined);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return resolved;
|
|
202
|
+
}
|
|
203
|
+
function walkReverse(nodeId, ctx) {
|
|
204
|
+
const reverseEdges = ctx.reverseMap.get(nodeId);
|
|
205
|
+
if (reverseEdges == null || reverseEdges.length === 0)
|
|
206
|
+
return [];
|
|
207
|
+
// Sort edges by parent name (with serialized ID as tiebreaker) so that
|
|
208
|
+
// deduplication is deterministic: the first parent always gets fully expanded.
|
|
209
|
+
const sortedEdges = [...reverseEdges].sort((a, b) => {
|
|
210
|
+
const cmp = (0, util_lex_comparator_1.lexCompare)(resolveParentName(a, ctx), resolveParentName(b, ctx));
|
|
211
|
+
if (cmp !== 0)
|
|
212
|
+
return cmp;
|
|
213
|
+
return (0, util_lex_comparator_1.lexCompare)(a.parentSerialized, b.parentSerialized);
|
|
214
|
+
});
|
|
215
|
+
const dependents = [];
|
|
216
|
+
for (const edge of sortedEdges) {
|
|
217
|
+
// Cycle detection: this node is already on our current path
|
|
218
|
+
if (ctx.visited.has(edge.parentSerialized)) {
|
|
219
|
+
const parentNode = ctx.graph.nodes.get(edge.parentSerialized);
|
|
220
|
+
if (parentNode?.nodeId.type === 'importer') {
|
|
221
|
+
const info = ctx.importerInfoMap.get(parentNode.nodeId.importerId);
|
|
222
|
+
if (info) {
|
|
223
|
+
dependents.push({
|
|
224
|
+
name: info.name,
|
|
225
|
+
version: info.version,
|
|
226
|
+
circular: true,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (parentNode?.nodeId.type === 'package') {
|
|
231
|
+
const snapshot = ctx.currentPackages[parentNode.nodeId.depPath];
|
|
232
|
+
if (snapshot) {
|
|
233
|
+
const { name, version } = (0, lockfile_utils_1.nameVerFromPkgSnapshot)(parentNode.nodeId.depPath, snapshot);
|
|
234
|
+
const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
|
|
235
|
+
dependents.push({ name, displayName, version, circular: true });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const parentGraphNode = ctx.graph.nodes.get(edge.parentSerialized);
|
|
241
|
+
if (parentGraphNode == null)
|
|
242
|
+
continue;
|
|
243
|
+
if (parentGraphNode.nodeId.type === 'importer') {
|
|
244
|
+
const importerId = parentGraphNode.nodeId.importerId;
|
|
245
|
+
const info = ctx.importerInfoMap.get(importerId) ?? { name: importerId, version: '' };
|
|
246
|
+
const depField = getDepFieldForAlias(edge.alias, ctx.importers[importerId]);
|
|
247
|
+
dependents.push({
|
|
248
|
+
name: info.name,
|
|
249
|
+
version: info.version,
|
|
250
|
+
depField,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
else if (parentGraphNode.nodeId.type === 'package') {
|
|
254
|
+
const snapshot = ctx.currentPackages[parentGraphNode.nodeId.depPath];
|
|
255
|
+
if (snapshot == null)
|
|
256
|
+
continue;
|
|
257
|
+
const { name, version } = (0, lockfile_utils_1.nameVerFromPkgSnapshot)(parentGraphNode.nodeId.depPath, snapshot);
|
|
258
|
+
const peersSuffixHash = (0, peersSuffixHash_js_1.peersSuffixHashFromDepPath)(parentGraphNode.nodeId.depPath);
|
|
259
|
+
// Deduplication: if this package was already expanded elsewhere in the
|
|
260
|
+
// tree, show it as a leaf to keep the output bounded.
|
|
261
|
+
const displayName = resolveDisplayName(edge.parentSerialized, name, version, ctx);
|
|
262
|
+
if (ctx.expanded.has(edge.parentSerialized)) {
|
|
263
|
+
dependents.push({ name, displayName, version, peersSuffixHash, deduped: true });
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
ctx.visited.add(edge.parentSerialized);
|
|
267
|
+
ctx.expanded.add(edge.parentSerialized);
|
|
268
|
+
const childDependents = walkReverse(edge.parentSerialized, ctx);
|
|
269
|
+
ctx.visited.delete(edge.parentSerialized);
|
|
270
|
+
dependents.push({
|
|
271
|
+
name,
|
|
272
|
+
displayName,
|
|
273
|
+
version,
|
|
274
|
+
peersSuffixHash,
|
|
275
|
+
dependents: childDependents.length > 0 ? childDependents : undefined,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return dependents;
|
|
280
|
+
}
|
|
281
|
+
function resolveParentName(edge, ctx) {
|
|
282
|
+
const graphNode = ctx.graph.nodes.get(edge.parentSerialized);
|
|
283
|
+
if (graphNode == null)
|
|
284
|
+
return '';
|
|
285
|
+
if (graphNode.nodeId.type === 'importer') {
|
|
286
|
+
const info = ctx.importerInfoMap.get(graphNode.nodeId.importerId);
|
|
287
|
+
return info?.name ?? graphNode.nodeId.importerId;
|
|
288
|
+
}
|
|
289
|
+
const snapshot = ctx.currentPackages[graphNode.nodeId.depPath];
|
|
290
|
+
if (snapshot == null)
|
|
291
|
+
return '';
|
|
292
|
+
return (0, lockfile_utils_1.nameVerFromPkgSnapshot)(graphNode.nodeId.depPath, snapshot).name;
|
|
293
|
+
}
|
|
294
|
+
function resolveDisplayName(serialized, name, version, ctx) {
|
|
295
|
+
if (!ctx.nameFormatter)
|
|
296
|
+
return undefined;
|
|
297
|
+
const pkgNode = ctx.resolvedPackageNodes.get(serialized);
|
|
298
|
+
if (!pkgNode)
|
|
299
|
+
return undefined;
|
|
300
|
+
return ctx.nameFormatter({ name, version, manifest: pkgNode.readManifest() });
|
|
301
|
+
}
|
|
302
|
+
function getDepFieldForAlias(alias, importerSnapshot) {
|
|
303
|
+
if (importerSnapshot.devDependencies?.[alias] != null)
|
|
304
|
+
return 'devDependencies';
|
|
305
|
+
if (importerSnapshot.optionalDependencies?.[alias] != null)
|
|
306
|
+
return 'optionalDependencies';
|
|
307
|
+
if (importerSnapshot.dependencies?.[alias] != null)
|
|
308
|
+
return 'dependencies';
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=buildDependentsTree.js.map
|