app-builder-lib 26.2.0 → 26.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/asar/asarUtil.js +78 -10
- package/out/asar/asarUtil.js.map +1 -1
- package/out/asar/unpackDetector.js +1 -3
- package/out/asar/unpackDetector.js.map +1 -1
- package/out/codeSign/macCodeSign.js +2 -1
- package/out/codeSign/macCodeSign.js.map +1 -1
- package/out/electron/search-module.js +1 -1
- package/out/electron/search-module.js.map +1 -1
- package/out/fileMatcher.js +1 -1
- package/out/fileMatcher.js.map +1 -1
- package/out/node-module-collector/bunNodeModulesCollector.d.ts +11 -0
- package/out/node-module-collector/bunNodeModulesCollector.js +22 -0
- package/out/node-module-collector/bunNodeModulesCollector.js.map +1 -0
- package/out/node-module-collector/index.d.ts +21 -6
- package/out/node-module-collector/index.js +93 -32
- package/out/node-module-collector/index.js.map +1 -1
- package/out/node-module-collector/moduleCache.d.ts +21 -0
- package/out/node-module-collector/moduleCache.js +16 -0
- package/out/node-module-collector/moduleCache.js.map +1 -0
- package/out/node-module-collector/nodeModulesCollector.d.ts +50 -14
- package/out/node-module-collector/nodeModulesCollector.js +239 -70
- package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/npmNodeModulesCollector.d.ts +10 -3
- package/out/node-module-collector/npmNodeModulesCollector.js +100 -13
- package/out/node-module-collector/npmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/packageManager.d.ts +8 -6
- package/out/node-module-collector/packageManager.js +73 -29
- package/out/node-module-collector/packageManager.js.map +1 -1
- package/out/node-module-collector/pnpmNodeModulesCollector.d.ts +4 -4
- package/out/node-module-collector/pnpmNodeModulesCollector.js +49 -23
- package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/types.d.ts +25 -1
- package/out/node-module-collector/types.js.map +1 -1
- package/out/node-module-collector/yarnBerryNodeModulesCollector.d.ts +15 -0
- package/out/node-module-collector/yarnBerryNodeModulesCollector.js +93 -0
- package/out/node-module-collector/yarnBerryNodeModulesCollector.js.map +1 -0
- package/out/node-module-collector/yarnNodeModulesCollector.d.ts +12 -2
- package/out/node-module-collector/yarnNodeModulesCollector.js +234 -5
- package/out/node-module-collector/yarnNodeModulesCollector.js.map +1 -1
- package/out/options/winOptions.d.ts +2 -1
- package/out/options/winOptions.js.map +1 -1
- package/out/packager.d.ts +6 -1
- package/out/packager.js +12 -5
- package/out/packager.js.map +1 -1
- package/out/publish/PublishManager.js +2 -2
- package/out/publish/PublishManager.js.map +1 -1
- package/out/targets/AppxTarget.js +1 -1
- package/out/targets/AppxTarget.js.map +1 -1
- package/out/targets/MsiTarget.js +1 -1
- package/out/targets/MsiTarget.js.map +1 -1
- package/out/targets/nsis/NsisTarget.js +2 -2
- package/out/targets/nsis/NsisTarget.js.map +1 -1
- package/out/targets/nsis/nsisUtil.js +1 -1
- package/out/targets/nsis/nsisUtil.js.map +1 -1
- package/out/targets/tools.js +12 -12
- package/out/targets/tools.js.map +1 -1
- package/out/util/appFileCopier.js +18 -10
- package/out/util/appFileCopier.js.map +1 -1
- package/out/util/macosIconComposer.js +11 -4
- package/out/util/macosIconComposer.js.map +1 -1
- package/out/util/yarn.d.ts +4 -2
- package/out/util/yarn.js +34 -24
- package/out/util/yarn.js.map +1 -1
- package/out/version.d.ts +1 -1
- package/out/version.js +1 -1
- package/out/version.js.map +1 -1
- package/out/winPackager.d.ts +1 -1
- package/out/winPackager.js +26 -9
- package/out/winPackager.js.map +1 -1
- package/package.json +9 -9
- package/scheme.json +1 -1
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NodeModulesCollector = void 0;
|
|
4
|
-
const hoist_1 = require("./hoist");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const fs = require("fs-extra");
|
|
7
4
|
const builder_util_1 = require("builder-util");
|
|
5
|
+
const childProcess = require("child_process");
|
|
6
|
+
const fs = require("fs-extra");
|
|
7
|
+
const fs_extra_1 = require("fs-extra");
|
|
8
|
+
const lazy_val_1 = require("lazy-val");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const hoist_1 = require("./hoist");
|
|
11
|
+
const moduleCache_1 = require("./moduleCache");
|
|
8
12
|
const packageManager_1 = require("./packageManager");
|
|
9
|
-
const
|
|
10
|
-
const util_1 = require("util");
|
|
11
|
-
const fs_1 = require("fs");
|
|
12
|
-
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
13
|
+
const node_url_1 = require("node:url");
|
|
13
14
|
class NodeModulesCollector {
|
|
14
15
|
constructor(rootDir, tempDirManager) {
|
|
15
16
|
this.rootDir = rootDir;
|
|
@@ -17,100 +18,260 @@ class NodeModulesCollector {
|
|
|
17
18
|
this.nodeModules = [];
|
|
18
19
|
this.allDependencies = new Map();
|
|
19
20
|
this.productionGraph = {};
|
|
21
|
+
this.pkgJsonCache = new Map();
|
|
22
|
+
this.memoResolvedModules = new Map();
|
|
23
|
+
this.importMetaResolve = new lazy_val_1.Lazy(async () => {
|
|
24
|
+
try {
|
|
25
|
+
// Node >= 16 builtin ESM-aware resolver
|
|
26
|
+
const packageName = "import-meta-resolve";
|
|
27
|
+
const imported = await Promise.resolve(`${packageName}`).then(s => require(s));
|
|
28
|
+
return imported.resolve;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
// Unified cache for all file system and module operations
|
|
35
|
+
this.cache = (0, moduleCache_1.createModuleCache)();
|
|
36
|
+
this.isHoisted = new lazy_val_1.Lazy(async () => {
|
|
37
|
+
const { manager } = this.installOptions;
|
|
38
|
+
const command = (0, packageManager_1.getPackageManagerCommand)(manager);
|
|
39
|
+
const config = (await this.asyncExec(command, ["config", "list"])).stdout;
|
|
40
|
+
if (config == null) {
|
|
41
|
+
builder_util_1.log.debug({ manager }, "unable to determine if node_modules are hoisted: no config output. falling back to hoisted mode");
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const lines = Object.fromEntries(config.split("\n").map(line => line.split("=").map(s => s.trim())));
|
|
45
|
+
if (lines["node-linker"] === "hoisted") {
|
|
46
|
+
builder_util_1.log.debug({ manager }, "node_modules are hoisted");
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
});
|
|
51
|
+
this.appPkgJson = new lazy_val_1.Lazy(async () => {
|
|
52
|
+
const appPkgPath = path.join(this.rootDir, "package.json");
|
|
53
|
+
return this.readJsonMemoized(appPkgPath);
|
|
54
|
+
});
|
|
20
55
|
}
|
|
21
|
-
async getNodeModules() {
|
|
22
|
-
const tree = await this.getDependenciesTree();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.
|
|
56
|
+
async getNodeModules({ cancellationToken, packageName }) {
|
|
57
|
+
const tree = await this.getDependenciesTree(this.installOptions.manager);
|
|
58
|
+
if (cancellationToken.cancelled) {
|
|
59
|
+
throw new Error("getNodeModules cancelled after fetching dependency tree");
|
|
60
|
+
}
|
|
61
|
+
await this.collectAllDependencies(tree, packageName);
|
|
62
|
+
const realTree = await this.getTreeFromWorkspaces(tree, packageName);
|
|
63
|
+
await this.extractProductionDependencyGraph(realTree, packageName);
|
|
64
|
+
if (cancellationToken.cancelled) {
|
|
65
|
+
throw new Error("getNodeModules cancelled after building production graph");
|
|
66
|
+
}
|
|
67
|
+
const hoisterResult = (0, hoist_1.hoist)(this.transformToHoisterTree(this.productionGraph, packageName), { check: true });
|
|
68
|
+
await this._getNodeModules(hoisterResult.dependencies, this.nodeModules);
|
|
69
|
+
builder_util_1.log.debug({ packageName, depCount: this.nodeModules.length }, "node modules collection complete");
|
|
28
70
|
return this.nodeModules;
|
|
29
71
|
}
|
|
30
|
-
async getDependenciesTree() {
|
|
31
|
-
const command = (0, packageManager_1.getPackageManagerCommand)(
|
|
72
|
+
async getDependenciesTree(pm) {
|
|
73
|
+
const command = (0, packageManager_1.getPackageManagerCommand)(pm);
|
|
32
74
|
const args = this.getArgs();
|
|
33
75
|
const tempOutputFile = await this.tempDirManager.getTempFile({
|
|
34
76
|
prefix: path.basename(command, path.extname(command)),
|
|
35
77
|
suffix: "output.json",
|
|
36
78
|
});
|
|
37
79
|
return (0, builder_util_1.retry)(async () => {
|
|
38
|
-
await this.
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return this.parseDependenciesTree(dependencies);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
builder_util_1.log.debug({ message: error.message || error.stack, shellOutput: dependencies }, "error parsing dependencies tree");
|
|
45
|
-
throw new Error(`Failed to parse dependencies tree: ${error.message || error.stack}. Use DEBUG=electron-builder env var to see the dependency query output.`);
|
|
46
|
-
}
|
|
80
|
+
await this.streamCollectorCommandToFile(command, args, this.rootDir, tempOutputFile);
|
|
81
|
+
const shellOutput = await fs.readFile(tempOutputFile, { encoding: "utf8" });
|
|
82
|
+
return await this.parseDependenciesTree(shellOutput);
|
|
47
83
|
}, {
|
|
48
|
-
retries:
|
|
84
|
+
retries: 1,
|
|
49
85
|
interval: 2000,
|
|
50
86
|
backoff: 2000,
|
|
51
87
|
shouldRetry: async (error) => {
|
|
52
88
|
var _a;
|
|
53
|
-
|
|
54
|
-
|
|
89
|
+
const logFields = { error: error.message, tempOutputFile, cwd: this.rootDir };
|
|
90
|
+
if (!(await this.existsMemoized(tempOutputFile))) {
|
|
91
|
+
builder_util_1.log.debug(logFields, "dependency tree output file missing, retrying");
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
const fileContent = await fs.readFile(tempOutputFile, { encoding: "utf8" });
|
|
95
|
+
const fields = { ...logFields, fileContent };
|
|
96
|
+
if (fileContent.trim().length === 0) {
|
|
97
|
+
builder_util_1.log.debug(fields, "dependency tree output file empty, retrying");
|
|
55
98
|
return true;
|
|
56
99
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// If the output file is empty or contains invalid JSON, we retry
|
|
60
|
-
// This can happen if the command fails or if the output is not as expected
|
|
61
|
-
builder_util_1.log.error({ error: error.message || error.stack, tempOutputFile }, "dependency tree output file is empty, retrying");
|
|
100
|
+
if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes("Unexpected end of JSON input")) {
|
|
101
|
+
builder_util_1.log.debug(fields, "JSON parse error in dependency tree, retrying");
|
|
62
102
|
return true;
|
|
63
103
|
}
|
|
104
|
+
builder_util_1.log.error(fields, "error parsing dependencies tree");
|
|
64
105
|
return false;
|
|
65
106
|
},
|
|
66
107
|
});
|
|
67
108
|
}
|
|
68
|
-
|
|
109
|
+
async existsMemoized(filePath) {
|
|
110
|
+
if (!this.cache.exists.has(filePath)) {
|
|
111
|
+
this.cache.exists.set(filePath, await (0, builder_util_1.exists)(filePath));
|
|
112
|
+
}
|
|
113
|
+
return this.cache.exists.get(filePath);
|
|
114
|
+
}
|
|
115
|
+
async readJsonMemoized(filePath) {
|
|
116
|
+
if (!this.cache.packageJson.has(filePath)) {
|
|
117
|
+
this.cache.packageJson.set(filePath, await (0, fs_extra_1.readJson)(filePath));
|
|
118
|
+
}
|
|
119
|
+
return this.cache.packageJson.get(filePath);
|
|
120
|
+
}
|
|
121
|
+
async lstatMemoized(filePath) {
|
|
122
|
+
if (!this.cache.lstat.has(filePath)) {
|
|
123
|
+
this.cache.lstat.set(filePath, await fs.lstat(filePath));
|
|
124
|
+
}
|
|
125
|
+
return this.cache.lstat.get(filePath);
|
|
126
|
+
}
|
|
127
|
+
async realpathMemoized(filePath) {
|
|
128
|
+
if (!this.cache.realPath.has(filePath)) {
|
|
129
|
+
this.cache.realPath.set(filePath, await fs.realpath(filePath));
|
|
130
|
+
}
|
|
131
|
+
return this.cache.realPath.get(filePath);
|
|
132
|
+
}
|
|
133
|
+
async resolvePath(filePath) {
|
|
134
|
+
// Check if we've already resolved this path
|
|
135
|
+
if (this.cache.realPath.has(filePath)) {
|
|
136
|
+
return this.cache.realPath.get(filePath);
|
|
137
|
+
}
|
|
69
138
|
try {
|
|
70
|
-
const stats =
|
|
139
|
+
const stats = await this.lstatMemoized(filePath);
|
|
71
140
|
if (stats.isSymbolicLink()) {
|
|
72
|
-
|
|
141
|
+
const resolved = await this.realpathMemoized(filePath);
|
|
142
|
+
this.cache.realPath.set(filePath, resolved);
|
|
143
|
+
return resolved;
|
|
73
144
|
}
|
|
74
145
|
else {
|
|
146
|
+
this.cache.realPath.set(filePath, filePath);
|
|
75
147
|
return filePath;
|
|
76
148
|
}
|
|
77
149
|
}
|
|
78
150
|
catch (error) {
|
|
79
|
-
builder_util_1.log.debug({ message: error.message || error.stack }, "error resolving path");
|
|
151
|
+
builder_util_1.log.debug({ filePath, message: error.message || error.stack }, "error resolving path");
|
|
152
|
+
this.cache.realPath.set(filePath, filePath);
|
|
80
153
|
return filePath;
|
|
81
154
|
}
|
|
82
155
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Resolves a package to its filesystem location using Node.js module resolution.
|
|
158
|
+
* Returns the directory containing the package, not the package.json path.
|
|
159
|
+
*/
|
|
160
|
+
async resolvePackageDir(packageName, fromDir) {
|
|
161
|
+
const cacheKey = `${packageName}::${fromDir}`;
|
|
162
|
+
if (this.cache.requireResolve.has(cacheKey)) {
|
|
163
|
+
return this.cache.requireResolve.get(cacheKey);
|
|
164
|
+
}
|
|
165
|
+
const resolveEntry = async () => {
|
|
166
|
+
// 1) Try Node ESM resolver (handles exports reliably)
|
|
167
|
+
if (await this.importMetaResolve.value) {
|
|
168
|
+
try {
|
|
169
|
+
const url = (await this.importMetaResolve.value)(packageName, (0, node_url_1.pathToFileURL)(fromDir).href);
|
|
170
|
+
return url.startsWith("file://") ? (0, node_url_1.fileURLToPath)(url) : null;
|
|
90
171
|
}
|
|
172
|
+
catch {
|
|
173
|
+
// ignore
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// 2) Fallback: require.resolve (CJS, old packages)
|
|
177
|
+
try {
|
|
178
|
+
return require.resolve(packageName, { paths: [fromDir, this.rootDir] });
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// ignore
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
};
|
|
185
|
+
const entry = await resolveEntry();
|
|
186
|
+
if (!entry) {
|
|
187
|
+
this.cache.requireResolve.set(cacheKey, null);
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
// 3) Walk upward until you find a package.json
|
|
191
|
+
let dir = path.dirname(entry);
|
|
192
|
+
while (true) {
|
|
193
|
+
const pkgFile = path.join(dir, "package.json");
|
|
194
|
+
if (await (0, builder_util_1.exists)(pkgFile)) {
|
|
195
|
+
this.cache.requireResolve.set(cacheKey, dir);
|
|
196
|
+
return dir;
|
|
197
|
+
}
|
|
198
|
+
const parent = path.dirname(dir);
|
|
199
|
+
if (parent === dir) {
|
|
200
|
+
break; // root reached
|
|
201
|
+
}
|
|
202
|
+
dir = parent;
|
|
203
|
+
}
|
|
204
|
+
this.cache.requireResolve.set(cacheKey, null);
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
requireMemoized(pkgPath) {
|
|
208
|
+
if (!this.cache.packageJson.has(pkgPath)) {
|
|
209
|
+
this.cache.packageJson.set(pkgPath, require(pkgPath));
|
|
210
|
+
}
|
|
211
|
+
return this.cache.packageJson.get(pkgPath);
|
|
212
|
+
}
|
|
213
|
+
existsSyncMemoized(filePath) {
|
|
214
|
+
if (!this.cache.exists.has(filePath)) {
|
|
215
|
+
this.cache.exists.set(filePath, fs.existsSync(filePath));
|
|
216
|
+
}
|
|
217
|
+
return this.cache.exists.get(filePath);
|
|
218
|
+
}
|
|
219
|
+
cacheKey(pkg) {
|
|
220
|
+
const rel = path.relative(this.rootDir, pkg.path);
|
|
221
|
+
return `${pkg.name}::${pkg.version}::${rel !== null && rel !== void 0 ? rel : "."}`;
|
|
222
|
+
}
|
|
223
|
+
packageVersionString(pkg) {
|
|
224
|
+
return `${pkg.name}@${pkg.version}`;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Parse a dependency identifier like "@scope/pkg@1.2.3" or "pkg@1.2.3"
|
|
228
|
+
*/
|
|
229
|
+
parseNameVersion(identifier) {
|
|
230
|
+
const lastAt = identifier.lastIndexOf("@");
|
|
231
|
+
if (lastAt <= 0) {
|
|
232
|
+
// fallback for scoped packages or malformed strings
|
|
233
|
+
return { name: identifier, version: "unknown" };
|
|
234
|
+
}
|
|
235
|
+
const name = identifier.slice(0, lastAt);
|
|
236
|
+
const version = identifier.slice(lastAt + 1);
|
|
237
|
+
return { name, version };
|
|
238
|
+
}
|
|
239
|
+
async getTreeFromWorkspaces(tree, packageName) {
|
|
240
|
+
var _a;
|
|
241
|
+
if (!(tree.workspaces && tree.dependencies)) {
|
|
242
|
+
return tree;
|
|
243
|
+
}
|
|
244
|
+
if ((_a = tree.dependencies) === null || _a === void 0 ? void 0 : _a[packageName]) {
|
|
245
|
+
const { name, path, dependencies } = tree.dependencies[packageName];
|
|
246
|
+
builder_util_1.log.debug({ name, path, dependencies: JSON.stringify(dependencies) }, "pruning root app/self package from workspace tree");
|
|
247
|
+
for (const [name, pkg] of Object.entries(dependencies !== null && dependencies !== void 0 ? dependencies : {})) {
|
|
248
|
+
tree.dependencies[name] = pkg;
|
|
91
249
|
}
|
|
250
|
+
delete tree.dependencies[packageName];
|
|
92
251
|
}
|
|
93
|
-
return tree;
|
|
252
|
+
return Promise.resolve(tree);
|
|
94
253
|
}
|
|
95
|
-
|
|
254
|
+
transformToHoisterTree(obj, key, nodes = new Map()) {
|
|
96
255
|
let node = nodes.get(key);
|
|
97
|
-
const name =
|
|
256
|
+
const { name, version } = this.parseNameVersion(key);
|
|
98
257
|
if (!node) {
|
|
99
258
|
node = {
|
|
100
259
|
name,
|
|
101
260
|
identName: name,
|
|
102
|
-
reference:
|
|
261
|
+
reference: version,
|
|
103
262
|
dependencies: new Set(),
|
|
104
|
-
peerNames: new Set(
|
|
263
|
+
peerNames: new Set(),
|
|
105
264
|
};
|
|
106
265
|
nodes.set(key, node);
|
|
107
|
-
|
|
108
|
-
|
|
266
|
+
const deps = (obj[key] || {}).dependencies || [];
|
|
267
|
+
for (const dep of deps) {
|
|
268
|
+
const child = this.transformToHoisterTree(obj, dep, nodes);
|
|
269
|
+
node.dependencies.add(child);
|
|
109
270
|
}
|
|
110
271
|
}
|
|
111
272
|
return node;
|
|
112
273
|
}
|
|
113
|
-
_getNodeModules(dependencies, result) {
|
|
274
|
+
async _getNodeModules(dependencies, result) {
|
|
114
275
|
var _a;
|
|
115
276
|
if (dependencies.size === 0) {
|
|
116
277
|
return;
|
|
@@ -124,34 +285,43 @@ class NodeModulesCollector {
|
|
|
124
285
|
}
|
|
125
286
|
// fix npm list issue
|
|
126
287
|
// https://github.com/npm/cli/issues/8535
|
|
127
|
-
if (!
|
|
288
|
+
if (!(await (0, builder_util_1.exists)(p))) {
|
|
128
289
|
builder_util_1.log.debug({ name: d.name, reference, p }, "dependency path does not exist");
|
|
129
290
|
continue;
|
|
130
291
|
}
|
|
131
292
|
const node = {
|
|
132
293
|
name: d.name,
|
|
133
294
|
version: reference,
|
|
134
|
-
dir: this.resolvePath(p),
|
|
295
|
+
dir: await this.resolvePath(p),
|
|
135
296
|
};
|
|
136
297
|
result.push(node);
|
|
137
298
|
if (d.dependencies.size > 0) {
|
|
138
299
|
node.dependencies = [];
|
|
139
|
-
this._getNodeModules(d.dependencies, node.dependencies);
|
|
300
|
+
await this._getNodeModules(d.dependencies, node.dependencies);
|
|
140
301
|
}
|
|
141
302
|
}
|
|
142
303
|
result.sort((a, b) => a.name.localeCompare(b.name));
|
|
143
304
|
}
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
305
|
+
async asyncExec(command, args, cwd = this.rootDir) {
|
|
306
|
+
const file = await this.tempDirManager.getTempFile({ prefix: "exec-", suffix: ".txt" });
|
|
307
|
+
try {
|
|
308
|
+
await this.streamCollectorCommandToFile(command, args, cwd, file);
|
|
309
|
+
const result = await fs.readFile(file, { encoding: "utf8" });
|
|
310
|
+
return { stdout: result === null || result === void 0 ? void 0 : result.trim(), stderr: undefined };
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
builder_util_1.log.debug({ error: error.message }, "failed to execute command");
|
|
314
|
+
return { stdout: undefined, stderr: error.message };
|
|
315
|
+
}
|
|
147
316
|
}
|
|
148
|
-
async
|
|
317
|
+
async streamCollectorCommandToFile(command, args, cwd, tempOutputFile) {
|
|
149
318
|
const execName = path.basename(command, path.extname(command));
|
|
150
319
|
const isWindowsScriptFile = process.platform === "win32" && path.extname(command).toLowerCase() === ".cmd";
|
|
151
320
|
if (isWindowsScriptFile) {
|
|
152
321
|
// If the command is a Windows script file (.cmd), we need to wrap it in a .bat file to ensure it runs correctly with cmd.exe
|
|
153
322
|
// This is necessary because .cmd files are not directly executable in the same way as .bat files.
|
|
154
323
|
// We create a temporary .bat file that calls the .cmd file with the provided arguments. The .bat file will be executed by cmd.exe.
|
|
324
|
+
// Note: This is a workaround for Windows command execution quirks for specifically when `shell: false`
|
|
155
325
|
const tempBatFile = await this.tempDirManager.getTempFile({
|
|
156
326
|
prefix: execName,
|
|
157
327
|
suffix: ".bat",
|
|
@@ -162,8 +332,8 @@ class NodeModulesCollector {
|
|
|
162
332
|
args = ["/c", tempBatFile, ...args];
|
|
163
333
|
}
|
|
164
334
|
await new Promise((resolve, reject) => {
|
|
165
|
-
const outStream = (0,
|
|
166
|
-
const child =
|
|
335
|
+
const outStream = (0, fs_extra_1.createWriteStream)(tempOutputFile);
|
|
336
|
+
const child = childProcess.spawn(command, args, {
|
|
167
337
|
cwd,
|
|
168
338
|
shell: false, // required to prevent console logs polution from shell profile loading when `true`
|
|
169
339
|
});
|
|
@@ -173,21 +343,20 @@ class NodeModulesCollector {
|
|
|
173
343
|
stderr += chunk.toString();
|
|
174
344
|
});
|
|
175
345
|
child.on("error", err => {
|
|
176
|
-
reject(new Error(`
|
|
346
|
+
reject(new Error(`Node module collector spawn failed: ${err.message}`));
|
|
177
347
|
});
|
|
178
348
|
child.on("close", code => {
|
|
179
349
|
outStream.close();
|
|
180
350
|
// https://github.com/npm/npm/issues/17624
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
resolve();
|
|
185
|
-
return;
|
|
351
|
+
const shouldIgnore = code === 1 && "npm" === execName.toLowerCase() && args.includes("list");
|
|
352
|
+
if (shouldIgnore) {
|
|
353
|
+
builder_util_1.log.debug(null, "`npm list` returned non-zero exit code, but it MIGHT be expected (https://github.com/npm/npm/issues/17624). Check stderr for details.");
|
|
186
354
|
}
|
|
187
|
-
if (
|
|
188
|
-
|
|
355
|
+
if (stderr.length > 0) {
|
|
356
|
+
builder_util_1.log.debug({ stderr }, "note: there was node module collector output on stderr");
|
|
189
357
|
}
|
|
190
|
-
|
|
358
|
+
const shouldResolve = code === 0 || shouldIgnore;
|
|
359
|
+
return shouldResolve ? resolve() : reject(new Error(`Node module collector process exited with code ${code}:\n${stderr}`));
|
|
191
360
|
});
|
|
192
361
|
});
|
|
193
362
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeModulesCollector.js","sourceRoot":"","sources":["../../src/node-module-collector/nodeModulesCollector.ts"],"names":[],"mappings":";;;AAAA,mCAAqE;AACrE,6BAA4B;AAC5B,+BAA8B;AAE9B,+CAAyD;AACzD,qDAA+D;AAC/D,iDAA2C;AAC3C,+BAAgC;AAChC,2BAAsC;AAEtC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAA;AAEjC,MAAsB,oBAAoB;IAKxC,YACmB,OAAe,EACf,cAAsB;QADtB,YAAO,GAAP,OAAO,CAAQ;QACf,mBAAc,GAAd,cAAc,CAAQ;QANjC,gBAAW,GAAqB,EAAE,CAAA;QAChC,oBAAe,GAAmB,IAAI,GAAG,EAAE,CAAA;QAC3C,oBAAe,GAAoB,EAAE,CAAA;IAK5C,CAAC;IAEG,KAAK,CAAC,cAAc;QACzB,MAAM,IAAI,GAAM,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAA;QAChD,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAA,CAAC,6FAA6F;QAC/H,MAAM,QAAQ,GAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;QACpD,IAAI,CAAC,gCAAgC,CAAC,QAAQ,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAA;QAE1E,MAAM,aAAa,GAAkB,IAAA,aAAK,EAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1G,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QAElE,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAYS,KAAK,CAAC,mBAAmB;QACjC,MAAM,OAAO,GAAG,IAAA,yCAAwB,EAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;QACrE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;QAE3B,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;YAC3D,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrD,MAAM,EAAE,aAAa;SACtB,CAAC,CAAA;QAEF,OAAO,IAAA,oBAAK,EACV,KAAK,IAAI,EAAE;YACT,MAAM,IAAI,CAAC,gCAAgC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;YACxF,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAC5E,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAA;YACjD,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,iCAAiC,CAAC,CAAA;gBAClH,MAAM,IAAI,KAAK,CAAC,sCAAsC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,0EAA0E,CAAC,CAAA;YAC/J,CAAC;QACH,CAAC,EACD;YACE,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;;gBAChC,IAAI,CAAC,CAAC,MAAM,IAAA,qBAAM,EAAC,cAAc,CAAC,CAAC,EAAE,CAAC;oBACpC,kBAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,kEAAkE,CAAC,CAAA;oBACtI,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;gBAC5E,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,KAAI,MAAA,KAAK,CAAC,OAAO,0CAAE,QAAQ,CAAC,8BAA8B,CAAC,CAAA,EAAE,CAAC;oBAChG,iEAAiE;oBACjE,2EAA2E;oBAC3E,kBAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,gDAAgD,CAAC,CAAA;oBACpH,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,OAAO,KAAK,CAAA;YACd,CAAC;SACF,CACF,CAAA;IACH,CAAC;IAES,WAAW,CAAC,QAAgB;QACpC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;YACpC,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC3B,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;YAClC,CAAC;iBAAM,CAAC;gBACN,OAAO,QAAQ,CAAA;YACjB,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,sBAAsB,CAAC,CAAA;YAC5E,OAAO,QAAQ,CAAA;QACjB,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,IAAO;QACnC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACzC,MAAM,WAAW,GAA+B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAA;YAChG,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,CAAA;YACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC7D,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;oBAC3B,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,kBAAkB,CAAC,GAAoB,EAAE,MAAc,GAAG,EAAE,QAAkC,IAAI,GAAG,EAAE;QAC7G,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAE,CAAC,CAAC,CAAC,CAAA;QACrC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG;gBACL,IAAI;gBACJ,SAAS,EAAE,IAAI;gBACf,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAE,CAAC,CAAC,CAAC,IAAI,EAAE;gBAChD,YAAY,EAAE,IAAI,GAAG,EAAe;gBACpC,SAAS,EAAE,IAAI,GAAG,CAAS,EAAE,CAAC;aAC/B,CAAA;YACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAEpB,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;gBACtD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;YACjE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,eAAe,CAAC,YAAgC,EAAE,MAAwB;;QAChF,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAM;QACR,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;YACtC,MAAM,CAAC,GAAG,MAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,0CAAE,IAAI,CAAA;YAClE,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,iCAAiC,CAAC,CAAA;gBACzE,SAAQ;YACV,CAAC;YAED,qBAAqB;YACrB,yCAAyC;YACzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,kBAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAA;gBAC3E,SAAQ;YACV,CAAC;YAED,MAAM,IAAI,GAAmB;gBAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,SAAS;gBAClB,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;aACzB,CAAA;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjB,IAAI,CAAC,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;gBACtB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;YACzD,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW;QAChE,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,CAAC,IAAI,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAA,CAAC,4EAA4E;QACxL,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,gCAAgC,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW,EAAE,cAAsB;QACzG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;QAC9D,MAAM,mBAAmB,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAA;QAC1G,IAAI,mBAAmB,EAAE,CAAC;YACxB,6HAA6H;YAC7H,kGAAkG;YAClG,mIAAmI;YACnI,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;gBACxD,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,MAAM;aACf,CAAC,CAAA;YACF,MAAM,SAAS,GAAG,iBAAiB,OAAO,UAAU,CAAA,CAAC,6BAA6B;YAClF,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAChE,OAAO,GAAG,SAAS,CAAA;YACnB,IAAI,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,CAAA;QACrC,CAAC;QAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAA,sBAAiB,EAAC,cAAc,CAAC,CAAA;YAEnD,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,OAAO,EAAE,IAAI,EAAE;gBACjC,GAAG;gBACH,KAAK,EAAE,KAAK,EAAE,mFAAmF;aAClG,CAAC,CAAA;YAEF,IAAI,MAAM,GAAG,EAAE,CAAA;YACf,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC5B,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;gBAC9B,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAA;YAC5B,CAAC,CAAC,CAAA;YACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;gBACtB,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACnD,CAAC,CAAC,CAAA;YAEF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;gBACvB,SAAS,CAAC,KAAK,EAAE,CAAA;gBACjB,0CAA0C;gBAC1C,IAAI,IAAI,KAAK,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5E,kBAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,uIAAuI,CAAC,CAAA;oBACpK,sHAAsH;oBACtH,OAAO,EAAE,CAAA;oBACT,OAAM;gBACR,CAAC;gBACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC,CAAA;gBAC1E,CAAC;gBACD,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAnND,oDAmNC","sourcesContent":["import { hoist, type HoisterTree, type HoisterResult } from \"./hoist\"\nimport * as path from \"path\"\nimport * as fs from \"fs-extra\"\nimport type { NodeModuleInfo, DependencyGraph, Dependency } from \"./types\"\nimport { exists, log, retry, TmpDir } from \"builder-util\"\nimport { getPackageManagerCommand, PM } from \"./packageManager\"\nimport { exec, spawn } from \"child_process\"\nimport { promisify } from \"util\"\nimport { createWriteStream } from \"fs\"\n\nconst execAsync = promisify(exec)\n\nexport abstract class NodeModulesCollector<T extends Dependency<T, OptionalsType>, OptionalsType> {\n private nodeModules: NodeModuleInfo[] = []\n protected allDependencies: Map<string, T> = new Map()\n protected productionGraph: DependencyGraph = {}\n\n constructor(\n private readonly rootDir: string,\n private readonly tempDirManager: TmpDir\n ) {}\n\n public async getNodeModules(): Promise<NodeModuleInfo[]> {\n const tree: T = await this.getDependenciesTree()\n this.collectAllDependencies(tree) // Parse from the root, as npm list can host and deduplicate across projects in the workspace\n const realTree: T = this.getTreeFromWorkspaces(tree)\n this.extractProductionDependencyGraph(realTree, \".\" /*root project name*/)\n\n const hoisterResult: HoisterResult = hoist(this.transToHoisterTree(this.productionGraph), { check: true })\n this._getNodeModules(hoisterResult.dependencies, this.nodeModules)\n\n return this.nodeModules\n }\n\n public abstract readonly installOptions: {\n manager: PM\n lockfile: string\n }\n\n protected abstract getArgs(): string[]\n protected abstract parseDependenciesTree(jsonBlob: string): T\n protected abstract extractProductionDependencyGraph(tree: Dependency<T, OptionalsType>, dependencyId: string): void\n protected abstract collectAllDependencies(tree: Dependency<T, OptionalsType>): void\n\n protected async getDependenciesTree(): Promise<T> {\n const command = getPackageManagerCommand(this.installOptions.manager)\n const args = this.getArgs()\n\n const tempOutputFile = await this.tempDirManager.getTempFile({\n prefix: path.basename(command, path.extname(command)),\n suffix: \"output.json\",\n })\n\n return retry(\n async () => {\n await this.streamCollectorCommandToJsonFile(command, args, this.rootDir, tempOutputFile)\n const dependencies = await fs.readFile(tempOutputFile, { encoding: \"utf8\" })\n try {\n return this.parseDependenciesTree(dependencies)\n } catch (error: any) {\n log.debug({ message: error.message || error.stack, shellOutput: dependencies }, \"error parsing dependencies tree\")\n throw new Error(`Failed to parse dependencies tree: ${error.message || error.stack}. Use DEBUG=electron-builder env var to see the dependency query output.`)\n }\n },\n {\n retries: 2,\n interval: 2000,\n backoff: 2000,\n shouldRetry: async (error: any) => {\n if (!(await exists(tempOutputFile))) {\n log.error({ error: error.message || error.stack, tempOutputFile }, \"error getting dependencies tree, unable to find output; retrying\")\n return true\n }\n const dependencies = await fs.readFile(tempOutputFile, { encoding: \"utf8\" })\n if (dependencies.trim().length === 0 || error.message?.includes(\"Unexpected end of JSON input\")) {\n // If the output file is empty or contains invalid JSON, we retry\n // This can happen if the command fails or if the output is not as expected\n log.error({ error: error.message || error.stack, tempOutputFile }, \"dependency tree output file is empty, retrying\")\n return true\n }\n return false\n },\n }\n )\n }\n\n protected resolvePath(filePath: string): string {\n try {\n const stats = fs.lstatSync(filePath)\n if (stats.isSymbolicLink()) {\n return fs.realpathSync(filePath)\n } else {\n return filePath\n }\n } catch (error: any) {\n log.debug({ message: error.message || error.stack }, \"error resolving path\")\n return filePath\n }\n }\n\n private getTreeFromWorkspaces(tree: T): T {\n if (tree.workspaces && tree.dependencies) {\n const packageJson: Dependency<string, string> = require(path.join(this.rootDir, \"package.json\"))\n const dependencyName = packageJson.name\n for (const [key, value] of Object.entries(tree.dependencies)) {\n if (key === dependencyName) {\n return value\n }\n }\n }\n\n return tree\n }\n\n private transToHoisterTree(obj: DependencyGraph, key: string = `.`, nodes: Map<string, HoisterTree> = new Map()): HoisterTree {\n let node = nodes.get(key)\n const name = key.match(/@?[^@]+/)![0]\n if (!node) {\n node = {\n name,\n identName: name,\n reference: key.match(/@?[^@]+@?(.+)?/)![1] || ``,\n dependencies: new Set<HoisterTree>(),\n peerNames: new Set<string>([]),\n }\n nodes.set(key, node)\n\n for (const dep of (obj[key] || {}).dependencies || []) {\n node.dependencies.add(this.transToHoisterTree(obj, dep, nodes))\n }\n }\n return node\n }\n\n private _getNodeModules(dependencies: Set<HoisterResult>, result: NodeModuleInfo[]) {\n if (dependencies.size === 0) {\n return\n }\n\n for (const d of dependencies.values()) {\n const reference = [...d.references][0]\n const p = this.allDependencies.get(`${d.name}@${reference}`)?.path\n if (p === undefined) {\n log.debug({ name: d.name, reference }, \"cannot find path for dependency\")\n continue\n }\n\n // fix npm list issue\n // https://github.com/npm/cli/issues/8535\n if (!fs.existsSync(p)) {\n log.debug({ name: d.name, reference, p }, \"dependency path does not exist\")\n continue\n }\n\n const node: NodeModuleInfo = {\n name: d.name,\n version: reference,\n dir: this.resolvePath(p),\n }\n result.push(node)\n if (d.dependencies.size > 0) {\n node.dependencies = []\n this._getNodeModules(d.dependencies, node.dependencies)\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n static async safeExec(command: string, args: string[], cwd: string): Promise<string> {\n const payload = await execAsync([`\"${command}\"`, ...args].join(\" \"), { cwd, maxBuffer: 100 * 1024 * 1024 }) // 100MB buffer LOL, some projects can have extremely large dependency trees\n return payload.stdout.trim()\n }\n\n async streamCollectorCommandToJsonFile(command: string, args: string[], cwd: string, tempOutputFile: string) {\n const execName = path.basename(command, path.extname(command))\n const isWindowsScriptFile = process.platform === \"win32\" && path.extname(command).toLowerCase() === \".cmd\"\n if (isWindowsScriptFile) {\n // If the command is a Windows script file (.cmd), we need to wrap it in a .bat file to ensure it runs correctly with cmd.exe\n // This is necessary because .cmd files are not directly executable in the same way as .bat files.\n // We create a temporary .bat file that calls the .cmd file with the provided arguments. The .bat file will be executed by cmd.exe.\n const tempBatFile = await this.tempDirManager.getTempFile({\n prefix: execName,\n suffix: \".bat\",\n })\n const batScript = `@echo off\\r\\n\"${command}\" %*\\r\\n` // <-- CRLF required for .bat\n await fs.writeFile(tempBatFile, batScript, { encoding: \"utf8\" })\n command = \"cmd.exe\"\n args = [\"/c\", tempBatFile, ...args]\n }\n\n await new Promise<void>((resolve, reject) => {\n const outStream = createWriteStream(tempOutputFile)\n\n const child = spawn(command, args, {\n cwd,\n shell: false, // required to prevent console logs polution from shell profile loading when `true`\n })\n\n let stderr = \"\"\n child.stdout.pipe(outStream)\n child.stderr.on(\"data\", chunk => {\n stderr += chunk.toString()\n })\n child.on(\"error\", err => {\n reject(new Error(`Spawn failed: ${err.message}`))\n })\n\n child.on(\"close\", code => {\n outStream.close()\n // https://github.com/npm/npm/issues/17624\n if (code === 1 && execName.toLowerCase() === \"npm\" && args.includes(\"list\")) {\n log.debug({ code, stderr }, \"`npm list` returned non-zero exit code, but it MIGHT be expected (https://github.com/npm/npm/issues/17624). Check stderr for details.\")\n // This is a known issue with npm list command, it can return code 1 even when the command is \"technically\" successful\n resolve()\n return\n }\n if (code !== 0) {\n return reject(new Error(`Process exited with code ${code}:\\n${stderr}`))\n }\n resolve()\n })\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"nodeModulesCollector.js","sourceRoot":"","sources":["../../src/node-module-collector/nodeModulesCollector.ts"],"names":[],"mappings":";;;AAAA,+CAAyD;AACzD,8CAA6C;AAE7C,+BAA8B;AAC9B,uCAAsD;AACtD,uCAA+B;AAC/B,6BAA4B;AAC5B,mCAAqE;AACrE,+CAAmE;AACnE,qDAA+D;AAE/D,uCAAuD;AAEvD,MAAsB,oBAAoB;IA6CxC,YACqB,OAAe,EACjB,cAAsB;QADpB,YAAO,GAAP,OAAO,CAAQ;QACjB,mBAAc,GAAd,cAAc,CAAQ;QA9CjC,gBAAW,GAAqB,EAAE,CAAA;QAChC,oBAAe,GAA6B,IAAI,GAAG,EAAE,CAAA;QACrD,oBAAe,GAAoB,EAAE,CAAA;QACrC,iBAAY,GAAwB,IAAI,GAAG,EAAE,CAAA;QAC7C,wBAAmB,GAAG,IAAI,GAAG,EAAkC,CAAA;QAEjE,sBAAiB,GAAG,IAAI,eAAI,CAAC,KAAK,IAAI,EAAE;YAC9C,IAAI,CAAC;gBACH,wCAAwC;gBACxC,MAAM,WAAW,GAAG,qBAAqB,CAAA;gBACzC,MAAM,QAAQ,GAAG,yBAAa,WAAW,yBAAC,CAAA;gBAC1C,OAAO,QAAQ,CAAC,OAAO,CAAA;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,0DAA0D;QAChD,UAAK,GAAgB,IAAA,+BAAiB,GAAE,CAAA;QAExC,cAAS,GAAG,IAAI,eAAI,CAAU,KAAK,IAAI,EAAE;YACjD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;YACvC,MAAM,OAAO,GAAG,IAAA,yCAAwB,EAAC,OAAO,CAAC,CAAA;YAEjD,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;YACzE,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,kBAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,iGAAiG,CAAC,CAAA;gBACzH,OAAO,KAAK,CAAA;YACd,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YAEpG,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;gBACvC,kBAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,0BAA0B,CAAC,CAAA;gBAClD,OAAO,IAAI,CAAA;YACb,CAAC;YAED,OAAO,KAAK,CAAA;QACd,CAAC,CAAC,CAAA;QAEQ,eAAU,GAAsB,IAAI,eAAI,CAAc,KAAK,IAAI,EAAE;YACzE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;YAC1D,OAAO,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IAKC,CAAC;IAEG,KAAK,CAAC,cAAc,CAAC,EAAE,iBAAiB,EAAE,WAAW,EAAiE;QAC3H,MAAM,IAAI,GAAgB,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;QAErF,IAAI,iBAAiB,CAAC,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAA;QAC5E,CAAC;QAED,MAAM,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QAEpD,MAAM,QAAQ,GAAgB,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACjF,MAAM,IAAI,CAAC,gCAAgC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;QAElE,IAAI,iBAAiB,CAAC,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;QAC7E,CAAC;QAED,MAAM,aAAa,GAAkB,IAAA,aAAK,EAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAE3H,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QACxE,kBAAG,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,kCAAkC,CAAC,CAAA;QAEjG,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAYS,KAAK,CAAC,mBAAmB,CAAC,EAAM;QACxC,MAAM,OAAO,GAAG,IAAA,yCAAwB,EAAC,EAAE,CAAC,CAAA;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;QAE3B,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;YAC3D,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrD,MAAM,EAAE,aAAa;SACtB,CAAC,CAAA;QAEF,OAAO,IAAA,oBAAK,EACV,KAAK,IAAI,EAAE;YACT,MAAM,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;YACpF,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAC3E,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAA;QACtD,CAAC,EACD;YACE,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;;gBAChC,MAAM,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,CAAA;gBAE7E,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;oBACjD,kBAAG,CAAC,KAAK,CAAC,SAAS,EAAE,+CAA+C,CAAC,CAAA;oBACrE,OAAO,IAAI,CAAA;gBACb,CAAC;gBAED,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;gBAC3E,MAAM,MAAM,GAAG,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,CAAA;gBAE5C,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACpC,kBAAG,CAAC,KAAK,CAAC,MAAM,EAAE,6CAA6C,CAAC,CAAA;oBAChE,OAAO,IAAI,CAAA;gBACb,CAAC;gBAED,IAAI,MAAA,KAAK,CAAC,OAAO,0CAAE,QAAQ,CAAC,8BAA8B,CAAC,EAAE,CAAC;oBAC5D,kBAAG,CAAC,KAAK,CAAC,MAAM,EAAE,+CAA+C,CAAC,CAAA;oBAClE,OAAO,IAAI,CAAA;gBACb,CAAC;gBAED,kBAAG,CAAC,KAAK,CAAC,MAAM,EAAE,iCAAiC,CAAC,CAAA;gBACpD,OAAO,KAAK,CAAA;YACd,CAAC;SACF,CACF,CAAA;IACH,CAAC;IAES,KAAK,CAAC,cAAc,CAAC,QAAgB;QAC7C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAA,qBAAM,EAAC,QAAQ,CAAC,CAAC,CAAA;QACzD,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IACzC,CAAC;IAES,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC/C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAA,mBAAQ,EAAC,QAAQ,CAAC,CAAC,CAAA;QAChE,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IAC9C,CAAC;IAES,KAAK,CAAC,aAAa,CAAC,QAAgB;QAC5C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC1D,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IACxC,CAAC;IAES,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC/C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;QAChE,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IAC3C,CAAC;IAES,KAAK,CAAC,WAAW,CAAC,QAAgB;QAC1C,4CAA4C;QAC5C,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;QAC3C,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;YAChD,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAA;gBACtD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;gBAC3C,OAAO,QAAQ,CAAA;YACjB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;gBAC3C,OAAO,QAAQ,CAAA;YACjB,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,sBAAsB,CAAC,CAAA;YACtF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAC3C,OAAO,QAAQ,CAAA;QACjB,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,iBAAiB,CAAC,WAAmB,EAAE,OAAe;QACpE,MAAM,QAAQ,GAAG,GAAG,WAAW,KAAK,OAAO,EAAE,CAAA;QAC7C,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;QACjD,CAAC;QAED,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;YAC9B,sDAAsD;YACtD,IAAI,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;gBACvC,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,IAAA,wBAAa,EAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAA;oBAC1F,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAA,wBAAa,EAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;gBAC9D,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;YAED,mDAAmD;YACnD,IAAI,CAAC;gBACH,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YACzE,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,OAAO,IAAI,CAAA;QACb,CAAC,CAAA;QAED,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAA;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAC7C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,+CAA+C;QAC/C,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;YAC9C,IAAI,MAAM,IAAA,qBAAM,EAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;gBAC5C,OAAO,GAAG,CAAA;YACZ,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAChC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAK,CAAC,eAAe;YACvB,CAAC;YACD,GAAG,GAAG,MAAM,CAAA;QACd,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAC7C,OAAO,IAAI,CAAA;IACb,CAAC;IAES,eAAe,CAAC,OAAe;QACvC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;QACvD,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAE,CAAA;IAC7C,CAAC;IAES,kBAAkB,CAAC,QAAgB;QAC3C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC1D,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IACzC,CAAC;IAES,QAAQ,CAAC,GAAgB;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;QACjD,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,KAAK,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,GAAG,EAAE,CAAA;IACrD,CAAC;IAES,oBAAoB,CAAC,GAAgB;QAC7C,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,CAAA;IACrC,CAAC;IAED;;OAEG;IACO,gBAAgB,CAAC,UAAkB;QAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;QAC1C,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YAChB,oDAAoD;YACpD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,CAAA;QACjD,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QACxC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IAC1B,CAAC;IAES,KAAK,CAAC,qBAAqB,CAAC,IAAiB,EAAE,WAAmB;;QAC1E,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,MAAA,IAAI,CAAC,YAAY,0CAAG,WAAW,CAAC,EAAE,CAAC;YACrC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;YACnE,kBAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,EAAE,mDAAmD,CAAC,CAAA;YAC1H,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,EAAE,CAAC,EAAE,CAAC;gBAC7D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,GAAG,CAAA;YAC/B,CAAC;YACD,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QACvC,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;IAEO,sBAAsB,CAAC,GAAoB,EAAE,GAAW,EAAE,QAAkC,IAAI,GAAG,EAAE;QAC3G,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACzB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAEpD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG;gBACL,IAAI;gBACJ,SAAS,EAAE,IAAI;gBACf,SAAS,EAAE,OAAO;gBAClB,YAAY,EAAE,IAAI,GAAG,EAAe;gBACpC,SAAS,EAAE,IAAI,GAAG,EAAU;aAC7B,CAAA;YAED,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;YAEpB,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE,CAAA;YAChD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;gBAC1D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,YAAgC,EAAE,MAAwB;;QACtF,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAM;QACR,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YACtC,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;YACtC,MAAM,CAAC,GAAG,MAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,0CAAE,IAAI,CAAA;YAClE,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,iCAAiC,CAAC,CAAA;gBACzE,SAAQ;YACV,CAAC;YAED,qBAAqB;YACrB,yCAAyC;YACzC,IAAI,CAAC,CAAC,MAAM,IAAA,qBAAM,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvB,kBAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAA;gBAC3E,SAAQ;YACV,CAAC;YAED,MAAM,IAAI,GAAmB;gBAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,SAAS;gBAClB,GAAG,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;aAC/B,CAAA;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjB,IAAI,CAAC,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;gBACtB,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;YAC/D,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAe,EAAE,IAAc,EAAE,MAAc,IAAI,CAAC,OAAO;QACzE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QACvF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;YACjE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;QACtD,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,2BAA2B,CAAC,CAAA;YAChE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,4BAA4B,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW,EAAE,cAAsB;QACrG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;QAC9D,MAAM,mBAAmB,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAA;QAC1G,IAAI,mBAAmB,EAAE,CAAC;YACxB,6HAA6H;YAC7H,kGAAkG;YAClG,mIAAmI;YACnI,uGAAuG;YACvG,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;gBACxD,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,MAAM;aACf,CAAC,CAAA;YACF,MAAM,SAAS,GAAG,iBAAiB,OAAO,UAAU,CAAA,CAAC,6BAA6B;YAClF,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAChE,OAAO,GAAG,SAAS,CAAA;YACnB,IAAI,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,CAAA;QACrC,CAAC;QAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAA,4BAAiB,EAAC,cAAc,CAAC,CAAA;YAEnD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;gBAC9C,GAAG;gBACH,KAAK,EAAE,KAAK,EAAE,mFAAmF;aAClG,CAAC,CAAA;YAEF,IAAI,MAAM,GAAG,EAAE,CAAA;YACf,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC5B,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;gBAC9B,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAA;YAC5B,CAAC,CAAC,CAAA;YACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;gBACtB,MAAM,CAAC,IAAI,KAAK,CAAC,uCAAuC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACzE,CAAC,CAAC,CAAA;YAEF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;gBACvB,SAAS,CAAC,KAAK,EAAE,CAAA;gBACjB,0CAA0C;gBAC1C,MAAM,YAAY,GAAG,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,QAAQ,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;gBAC5F,IAAI,YAAY,EAAE,CAAC;oBACjB,kBAAG,CAAC,KAAK,CAAC,IAAI,EAAE,uIAAuI,CAAC,CAAA;gBAC1J,CAAC;gBACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,kBAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,wDAAwD,CAAC,CAAA;gBACjF,CAAC;gBACD,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,IAAI,YAAY,CAAA;gBAChD,OAAO,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,kDAAkD,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC,CAAA;YAC5H,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AA7ZD,oDA6ZC","sourcesContent":["import { exists, log, retry, TmpDir } from \"builder-util\"\nimport * as childProcess from \"child_process\"\nimport { CancellationToken } from \"builder-util-runtime\"\nimport * as fs from \"fs-extra\"\nimport { createWriteStream, readJson } from \"fs-extra\"\nimport { Lazy } from \"lazy-val\"\nimport * as path from \"path\"\nimport { hoist, type HoisterResult, type HoisterTree } from \"./hoist\"\nimport { createModuleCache, type ModuleCache } from \"./moduleCache\"\nimport { getPackageManagerCommand, PM } from \"./packageManager\"\nimport type { Dependency, DependencyGraph, NodeModuleInfo, PackageJson } from \"./types\"\nimport { fileURLToPath, pathToFileURL } from \"node:url\"\n\nexport abstract class NodeModulesCollector<ProdDepType extends Dependency<ProdDepType, OptionalDepType>, OptionalDepType> {\n private nodeModules: NodeModuleInfo[] = []\n protected allDependencies: Map<string, ProdDepType> = new Map()\n protected productionGraph: DependencyGraph = {}\n protected pkgJsonCache: Map<string, string> = new Map()\n protected memoResolvedModules = new Map<string, Promise<string | null>>()\n\n private importMetaResolve = new Lazy(async () => {\n try {\n // Node >= 16 builtin ESM-aware resolver\n const packageName = \"import-meta-resolve\"\n const imported = await import(packageName)\n return imported.resolve\n } catch {\n return null\n }\n })\n\n // Unified cache for all file system and module operations\n protected cache: ModuleCache = createModuleCache()\n\n protected isHoisted = new Lazy<boolean>(async () => {\n const { manager } = this.installOptions\n const command = getPackageManagerCommand(manager)\n\n const config = (await this.asyncExec(command, [\"config\", \"list\"])).stdout\n if (config == null) {\n log.debug({ manager }, \"unable to determine if node_modules are hoisted: no config output. falling back to hoisted mode\")\n return false\n }\n const lines = Object.fromEntries(config.split(\"\\n\").map(line => line.split(\"=\").map(s => s.trim())))\n\n if (lines[\"node-linker\"] === \"hoisted\") {\n log.debug({ manager }, \"node_modules are hoisted\")\n return true\n }\n\n return false\n })\n\n protected appPkgJson: Lazy<PackageJson> = new Lazy<PackageJson>(async () => {\n const appPkgPath = path.join(this.rootDir, \"package.json\")\n return this.readJsonMemoized(appPkgPath)\n })\n\n constructor(\n protected readonly rootDir: string,\n private readonly tempDirManager: TmpDir\n ) {}\n\n public async getNodeModules({ cancellationToken, packageName }: { cancellationToken: CancellationToken; packageName: string }): Promise<NodeModuleInfo[]> {\n const tree: ProdDepType = await this.getDependenciesTree(this.installOptions.manager)\n\n if (cancellationToken.cancelled) {\n throw new Error(\"getNodeModules cancelled after fetching dependency tree\")\n }\n\n await this.collectAllDependencies(tree, packageName)\n\n const realTree: ProdDepType = await this.getTreeFromWorkspaces(tree, packageName)\n await this.extractProductionDependencyGraph(realTree, packageName)\n\n if (cancellationToken.cancelled) {\n throw new Error(\"getNodeModules cancelled after building production graph\")\n }\n\n const hoisterResult: HoisterResult = hoist(this.transformToHoisterTree(this.productionGraph, packageName), { check: true })\n\n await this._getNodeModules(hoisterResult.dependencies, this.nodeModules)\n log.debug({ packageName, depCount: this.nodeModules.length }, \"node modules collection complete\")\n\n return this.nodeModules\n }\n\n public abstract readonly installOptions: {\n manager: PM\n lockfile: string\n }\n\n protected abstract getArgs(): string[]\n protected abstract parseDependenciesTree(jsonBlob: string): Promise<ProdDepType>\n protected abstract extractProductionDependencyGraph(tree: Dependency<ProdDepType, OptionalDepType>, dependencyId: string): Promise<void>\n protected abstract collectAllDependencies(tree: Dependency<ProdDepType, OptionalDepType>, appPackageName: string): Promise<void>\n\n protected async getDependenciesTree(pm: PM): Promise<ProdDepType> {\n const command = getPackageManagerCommand(pm)\n const args = this.getArgs()\n\n const tempOutputFile = await this.tempDirManager.getTempFile({\n prefix: path.basename(command, path.extname(command)),\n suffix: \"output.json\",\n })\n\n return retry(\n async () => {\n await this.streamCollectorCommandToFile(command, args, this.rootDir, tempOutputFile)\n const shellOutput = await fs.readFile(tempOutputFile, { encoding: \"utf8\" })\n return await this.parseDependenciesTree(shellOutput)\n },\n {\n retries: 1,\n interval: 2000,\n backoff: 2000,\n shouldRetry: async (error: any) => {\n const logFields = { error: error.message, tempOutputFile, cwd: this.rootDir }\n\n if (!(await this.existsMemoized(tempOutputFile))) {\n log.debug(logFields, \"dependency tree output file missing, retrying\")\n return true\n }\n\n const fileContent = await fs.readFile(tempOutputFile, { encoding: \"utf8\" })\n const fields = { ...logFields, fileContent }\n\n if (fileContent.trim().length === 0) {\n log.debug(fields, \"dependency tree output file empty, retrying\")\n return true\n }\n\n if (error.message?.includes(\"Unexpected end of JSON input\")) {\n log.debug(fields, \"JSON parse error in dependency tree, retrying\")\n return true\n }\n\n log.error(fields, \"error parsing dependencies tree\")\n return false\n },\n }\n )\n }\n\n protected async existsMemoized(filePath: string): Promise<boolean> {\n if (!this.cache.exists.has(filePath)) {\n this.cache.exists.set(filePath, await exists(filePath))\n }\n return this.cache.exists.get(filePath)!\n }\n\n protected async readJsonMemoized(filePath: string): Promise<PackageJson> {\n if (!this.cache.packageJson.has(filePath)) {\n this.cache.packageJson.set(filePath, await readJson(filePath))\n }\n return this.cache.packageJson.get(filePath)!\n }\n\n protected async lstatMemoized(filePath: string): Promise<fs.Stats> {\n if (!this.cache.lstat.has(filePath)) {\n this.cache.lstat.set(filePath, await fs.lstat(filePath))\n }\n return this.cache.lstat.get(filePath)!\n }\n\n protected async realpathMemoized(filePath: string): Promise<string> {\n if (!this.cache.realPath.has(filePath)) {\n this.cache.realPath.set(filePath, await fs.realpath(filePath))\n }\n return this.cache.realPath.get(filePath)!\n }\n\n protected async resolvePath(filePath: string): Promise<string> {\n // Check if we've already resolved this path\n if (this.cache.realPath.has(filePath)) {\n return this.cache.realPath.get(filePath)!\n }\n\n try {\n const stats = await this.lstatMemoized(filePath)\n if (stats.isSymbolicLink()) {\n const resolved = await this.realpathMemoized(filePath)\n this.cache.realPath.set(filePath, resolved)\n return resolved\n } else {\n this.cache.realPath.set(filePath, filePath)\n return filePath\n }\n } catch (error: any) {\n log.debug({ filePath, message: error.message || error.stack }, \"error resolving path\")\n this.cache.realPath.set(filePath, filePath)\n return filePath\n }\n }\n\n /**\n * Resolves a package to its filesystem location using Node.js module resolution.\n * Returns the directory containing the package, not the package.json path.\n */\n protected async resolvePackageDir(packageName: string, fromDir: string): Promise<string | null> {\n const cacheKey = `${packageName}::${fromDir}`\n if (this.cache.requireResolve.has(cacheKey)) {\n return this.cache.requireResolve.get(cacheKey)!\n }\n\n const resolveEntry = async () => {\n // 1) Try Node ESM resolver (handles exports reliably)\n if (await this.importMetaResolve.value) {\n try {\n const url = (await this.importMetaResolve.value)(packageName, pathToFileURL(fromDir).href)\n return url.startsWith(\"file://\") ? fileURLToPath(url) : null\n } catch {\n // ignore\n }\n }\n\n // 2) Fallback: require.resolve (CJS, old packages)\n try {\n return require.resolve(packageName, { paths: [fromDir, this.rootDir] })\n } catch {\n // ignore\n }\n\n return null\n }\n\n const entry = await resolveEntry()\n if (!entry) {\n this.cache.requireResolve.set(cacheKey, null)\n return null\n }\n\n // 3) Walk upward until you find a package.json\n let dir = path.dirname(entry)\n while (true) {\n const pkgFile = path.join(dir, \"package.json\")\n if (await exists(pkgFile)) {\n this.cache.requireResolve.set(cacheKey, dir)\n return dir\n }\n\n const parent = path.dirname(dir)\n if (parent === dir) {\n break // root reached\n }\n dir = parent\n }\n\n this.cache.requireResolve.set(cacheKey, null)\n return null\n }\n\n protected requireMemoized(pkgPath: string): PackageJson {\n if (!this.cache.packageJson.has(pkgPath)) {\n this.cache.packageJson.set(pkgPath, require(pkgPath))\n }\n return this.cache.packageJson.get(pkgPath)!\n }\n\n protected existsSyncMemoized(filePath: string): boolean {\n if (!this.cache.exists.has(filePath)) {\n this.cache.exists.set(filePath, fs.existsSync(filePath))\n }\n return this.cache.exists.get(filePath)!\n }\n\n protected cacheKey(pkg: ProdDepType): string {\n const rel = path.relative(this.rootDir, pkg.path)\n return `${pkg.name}::${pkg.version}::${rel ?? \".\"}`\n }\n\n protected packageVersionString(pkg: ProdDepType): string {\n return `${pkg.name}@${pkg.version}`\n }\n\n /**\n * Parse a dependency identifier like \"@scope/pkg@1.2.3\" or \"pkg@1.2.3\"\n */\n protected parseNameVersion(identifier: string): { name: string; version: string } {\n const lastAt = identifier.lastIndexOf(\"@\")\n if (lastAt <= 0) {\n // fallback for scoped packages or malformed strings\n return { name: identifier, version: \"unknown\" }\n }\n const name = identifier.slice(0, lastAt)\n const version = identifier.slice(lastAt + 1)\n return { name, version }\n }\n\n protected async getTreeFromWorkspaces(tree: ProdDepType, packageName: string): Promise<ProdDepType> {\n if (!(tree.workspaces && tree.dependencies)) {\n return tree\n }\n\n if (tree.dependencies?.[packageName]) {\n const { name, path, dependencies } = tree.dependencies[packageName]\n log.debug({ name, path, dependencies: JSON.stringify(dependencies) }, \"pruning root app/self package from workspace tree\")\n for (const [name, pkg] of Object.entries(dependencies ?? {})) {\n tree.dependencies[name] = pkg\n }\n delete tree.dependencies[packageName]\n }\n return Promise.resolve(tree)\n }\n\n private transformToHoisterTree(obj: DependencyGraph, key: string, nodes: Map<string, HoisterTree> = new Map()): HoisterTree {\n let node = nodes.get(key)\n const { name, version } = this.parseNameVersion(key)\n\n if (!node) {\n node = {\n name,\n identName: name,\n reference: version,\n dependencies: new Set<HoisterTree>(),\n peerNames: new Set<string>(),\n }\n\n nodes.set(key, node)\n\n const deps = (obj[key] || {}).dependencies || []\n for (const dep of deps) {\n const child = this.transformToHoisterTree(obj, dep, nodes)\n node.dependencies.add(child)\n }\n }\n\n return node\n }\n\n private async _getNodeModules(dependencies: Set<HoisterResult>, result: NodeModuleInfo[]) {\n if (dependencies.size === 0) {\n return\n }\n\n for (const d of dependencies.values()) {\n const reference = [...d.references][0]\n const p = this.allDependencies.get(`${d.name}@${reference}`)?.path\n if (p === undefined) {\n log.debug({ name: d.name, reference }, \"cannot find path for dependency\")\n continue\n }\n\n // fix npm list issue\n // https://github.com/npm/cli/issues/8535\n if (!(await exists(p))) {\n log.debug({ name: d.name, reference, p }, \"dependency path does not exist\")\n continue\n }\n\n const node: NodeModuleInfo = {\n name: d.name,\n version: reference,\n dir: await this.resolvePath(p),\n }\n result.push(node)\n if (d.dependencies.size > 0) {\n node.dependencies = []\n await this._getNodeModules(d.dependencies, node.dependencies)\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n async asyncExec(command: string, args: string[], cwd: string = this.rootDir): Promise<{ stdout: string | undefined; stderr: string | undefined }> {\n const file = await this.tempDirManager.getTempFile({ prefix: \"exec-\", suffix: \".txt\" })\n try {\n await this.streamCollectorCommandToFile(command, args, cwd, file)\n const result = await fs.readFile(file, { encoding: \"utf8\" })\n return { stdout: result?.trim(), stderr: undefined }\n } catch (error: any) {\n log.debug({ error: error.message }, \"failed to execute command\")\n return { stdout: undefined, stderr: error.message }\n }\n }\n\n async streamCollectorCommandToFile(command: string, args: string[], cwd: string, tempOutputFile: string) {\n const execName = path.basename(command, path.extname(command))\n const isWindowsScriptFile = process.platform === \"win32\" && path.extname(command).toLowerCase() === \".cmd\"\n if (isWindowsScriptFile) {\n // If the command is a Windows script file (.cmd), we need to wrap it in a .bat file to ensure it runs correctly with cmd.exe\n // This is necessary because .cmd files are not directly executable in the same way as .bat files.\n // We create a temporary .bat file that calls the .cmd file with the provided arguments. The .bat file will be executed by cmd.exe.\n // Note: This is a workaround for Windows command execution quirks for specifically when `shell: false`\n const tempBatFile = await this.tempDirManager.getTempFile({\n prefix: execName,\n suffix: \".bat\",\n })\n const batScript = `@echo off\\r\\n\"${command}\" %*\\r\\n` // <-- CRLF required for .bat\n await fs.writeFile(tempBatFile, batScript, { encoding: \"utf8\" })\n command = \"cmd.exe\"\n args = [\"/c\", tempBatFile, ...args]\n }\n\n await new Promise<void>((resolve, reject) => {\n const outStream = createWriteStream(tempOutputFile)\n\n const child = childProcess.spawn(command, args, {\n cwd,\n shell: false, // required to prevent console logs polution from shell profile loading when `true`\n })\n\n let stderr = \"\"\n child.stdout.pipe(outStream)\n child.stderr.on(\"data\", chunk => {\n stderr += chunk.toString()\n })\n child.on(\"error\", err => {\n reject(new Error(`Node module collector spawn failed: ${err.message}`))\n })\n\n child.on(\"close\", code => {\n outStream.close()\n // https://github.com/npm/npm/issues/17624\n const shouldIgnore = code === 1 && \"npm\" === execName.toLowerCase() && args.includes(\"list\")\n if (shouldIgnore) {\n log.debug(null, \"`npm list` returned non-zero exit code, but it MIGHT be expected (https://github.com/npm/npm/issues/17624). Check stderr for details.\")\n }\n if (stderr.length > 0) {\n log.debug({ stderr }, \"note: there was node module collector output on stderr\")\n }\n const shouldResolve = code === 0 || shouldIgnore\n return shouldResolve ? resolve() : reject(new Error(`Node module collector process exited with code ${code}:\\n${stderr}`))\n })\n })\n }\n}\n"]}
|
|
@@ -7,7 +7,14 @@ export declare class NpmNodeModulesCollector extends NodeModulesCollector<NpmDep
|
|
|
7
7
|
lockfile: string;
|
|
8
8
|
};
|
|
9
9
|
protected getArgs(): string[];
|
|
10
|
-
protected
|
|
11
|
-
protected
|
|
12
|
-
protected
|
|
10
|
+
protected getDependenciesTree(pm: PM): Promise<NpmDependency>;
|
|
11
|
+
protected collectAllDependencies(tree: NpmDependency): Promise<void>;
|
|
12
|
+
protected extractProductionDependencyGraph(tree: NpmDependency, dependencyId: string): Promise<void>;
|
|
13
|
+
protected isProdDependency(packageName: string, tree: NpmDependency): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Builds a dependency tree using only package.json dependencies and optionalDependencies.
|
|
16
|
+
* This skips devDependencies and uses Node.js module resolution (require.resolve).
|
|
17
|
+
*/
|
|
18
|
+
protected buildNodeModulesTreeManually(baseDir: string): Promise<NpmDependency>;
|
|
19
|
+
protected parseDependenciesTree(jsonBlob: string): Promise<NpmDependency>;
|
|
13
20
|
}
|