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.
Files changed (71) hide show
  1. package/out/asar/asarUtil.js +78 -10
  2. package/out/asar/asarUtil.js.map +1 -1
  3. package/out/asar/unpackDetector.js +1 -3
  4. package/out/asar/unpackDetector.js.map +1 -1
  5. package/out/codeSign/macCodeSign.js +2 -1
  6. package/out/codeSign/macCodeSign.js.map +1 -1
  7. package/out/electron/search-module.js +1 -1
  8. package/out/electron/search-module.js.map +1 -1
  9. package/out/fileMatcher.js +1 -1
  10. package/out/fileMatcher.js.map +1 -1
  11. package/out/node-module-collector/bunNodeModulesCollector.d.ts +11 -0
  12. package/out/node-module-collector/bunNodeModulesCollector.js +22 -0
  13. package/out/node-module-collector/bunNodeModulesCollector.js.map +1 -0
  14. package/out/node-module-collector/index.d.ts +21 -6
  15. package/out/node-module-collector/index.js +93 -32
  16. package/out/node-module-collector/index.js.map +1 -1
  17. package/out/node-module-collector/moduleCache.d.ts +21 -0
  18. package/out/node-module-collector/moduleCache.js +16 -0
  19. package/out/node-module-collector/moduleCache.js.map +1 -0
  20. package/out/node-module-collector/nodeModulesCollector.d.ts +50 -14
  21. package/out/node-module-collector/nodeModulesCollector.js +239 -70
  22. package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
  23. package/out/node-module-collector/npmNodeModulesCollector.d.ts +10 -3
  24. package/out/node-module-collector/npmNodeModulesCollector.js +100 -13
  25. package/out/node-module-collector/npmNodeModulesCollector.js.map +1 -1
  26. package/out/node-module-collector/packageManager.d.ts +8 -6
  27. package/out/node-module-collector/packageManager.js +73 -29
  28. package/out/node-module-collector/packageManager.js.map +1 -1
  29. package/out/node-module-collector/pnpmNodeModulesCollector.d.ts +4 -4
  30. package/out/node-module-collector/pnpmNodeModulesCollector.js +49 -23
  31. package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
  32. package/out/node-module-collector/types.d.ts +25 -1
  33. package/out/node-module-collector/types.js.map +1 -1
  34. package/out/node-module-collector/yarnBerryNodeModulesCollector.d.ts +15 -0
  35. package/out/node-module-collector/yarnBerryNodeModulesCollector.js +93 -0
  36. package/out/node-module-collector/yarnBerryNodeModulesCollector.js.map +1 -0
  37. package/out/node-module-collector/yarnNodeModulesCollector.d.ts +12 -2
  38. package/out/node-module-collector/yarnNodeModulesCollector.js +234 -5
  39. package/out/node-module-collector/yarnNodeModulesCollector.js.map +1 -1
  40. package/out/options/winOptions.d.ts +2 -1
  41. package/out/options/winOptions.js.map +1 -1
  42. package/out/packager.d.ts +6 -1
  43. package/out/packager.js +12 -5
  44. package/out/packager.js.map +1 -1
  45. package/out/publish/PublishManager.js +2 -2
  46. package/out/publish/PublishManager.js.map +1 -1
  47. package/out/targets/AppxTarget.js +1 -1
  48. package/out/targets/AppxTarget.js.map +1 -1
  49. package/out/targets/MsiTarget.js +1 -1
  50. package/out/targets/MsiTarget.js.map +1 -1
  51. package/out/targets/nsis/NsisTarget.js +2 -2
  52. package/out/targets/nsis/NsisTarget.js.map +1 -1
  53. package/out/targets/nsis/nsisUtil.js +1 -1
  54. package/out/targets/nsis/nsisUtil.js.map +1 -1
  55. package/out/targets/tools.js +12 -12
  56. package/out/targets/tools.js.map +1 -1
  57. package/out/util/appFileCopier.js +18 -10
  58. package/out/util/appFileCopier.js.map +1 -1
  59. package/out/util/macosIconComposer.js +11 -4
  60. package/out/util/macosIconComposer.js.map +1 -1
  61. package/out/util/yarn.d.ts +4 -2
  62. package/out/util/yarn.js +34 -24
  63. package/out/util/yarn.js.map +1 -1
  64. package/out/version.d.ts +1 -1
  65. package/out/version.js +1 -1
  66. package/out/version.js.map +1 -1
  67. package/out/winPackager.d.ts +1 -1
  68. package/out/winPackager.js +26 -9
  69. package/out/winPackager.js.map +1 -1
  70. package/package.json +9 -9
  71. 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 child_process_1 = require("child_process");
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
- this.collectAllDependencies(tree); // Parse from the root, as npm list can host and deduplicate across projects in the workspace
24
- const realTree = this.getTreeFromWorkspaces(tree);
25
- this.extractProductionDependencyGraph(realTree, "." /*root project name*/);
26
- const hoisterResult = (0, hoist_1.hoist)(this.transToHoisterTree(this.productionGraph), { check: true });
27
- this._getNodeModules(hoisterResult.dependencies, this.nodeModules);
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)(this.installOptions.manager);
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.streamCollectorCommandToJsonFile(command, args, this.rootDir, tempOutputFile);
39
- const dependencies = await fs.readFile(tempOutputFile, { encoding: "utf8" });
40
- try {
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: 2,
84
+ retries: 1,
49
85
  interval: 2000,
50
86
  backoff: 2000,
51
87
  shouldRetry: async (error) => {
52
88
  var _a;
53
- if (!(await (0, builder_util_1.exists)(tempOutputFile))) {
54
- builder_util_1.log.error({ error: error.message || error.stack, tempOutputFile }, "error getting dependencies tree, unable to find output; retrying");
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
- const dependencies = await fs.readFile(tempOutputFile, { encoding: "utf8" });
58
- if (dependencies.trim().length === 0 || ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes("Unexpected end of JSON input"))) {
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
- resolvePath(filePath) {
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 = fs.lstatSync(filePath);
139
+ const stats = await this.lstatMemoized(filePath);
71
140
  if (stats.isSymbolicLink()) {
72
- return fs.realpathSync(filePath);
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
- getTreeFromWorkspaces(tree) {
84
- if (tree.workspaces && tree.dependencies) {
85
- const packageJson = require(path.join(this.rootDir, "package.json"));
86
- const dependencyName = packageJson.name;
87
- for (const [key, value] of Object.entries(tree.dependencies)) {
88
- if (key === dependencyName) {
89
- return value;
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
- transToHoisterTree(obj, key = `.`, nodes = new Map()) {
254
+ transformToHoisterTree(obj, key, nodes = new Map()) {
96
255
  let node = nodes.get(key);
97
- const name = key.match(/@?[^@]+/)[0];
256
+ const { name, version } = this.parseNameVersion(key);
98
257
  if (!node) {
99
258
  node = {
100
259
  name,
101
260
  identName: name,
102
- reference: key.match(/@?[^@]+@?(.+)?/)[1] || ``,
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
- for (const dep of (obj[key] || {}).dependencies || []) {
108
- node.dependencies.add(this.transToHoisterTree(obj, dep, nodes));
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 (!fs.existsSync(p)) {
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
- static async safeExec(command, args, cwd) {
145
- const payload = await execAsync([`"${command}"`, ...args].join(" "), { cwd, maxBuffer: 100 * 1024 * 1024 }); // 100MB buffer LOL, some projects can have extremely large dependency trees
146
- return payload.stdout.trim();
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 streamCollectorCommandToJsonFile(command, args, cwd, tempOutputFile) {
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, fs_1.createWriteStream)(tempOutputFile);
166
- const child = (0, child_process_1.spawn)(command, args, {
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(`Spawn failed: ${err.message}`));
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
- if (code === 1 && execName.toLowerCase() === "npm" && args.includes("list")) {
182
- builder_util_1.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.");
183
- // This is a known issue with npm list command, it can return code 1 even when the command is "technically" successful
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 (code !== 0) {
188
- return reject(new Error(`Process exited with code ${code}:\n${stderr}`));
355
+ if (stderr.length > 0) {
356
+ builder_util_1.log.debug({ stderr }, "note: there was node module collector output on stderr");
189
357
  }
190
- resolve();
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":"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","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":"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","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 collectAllDependencies(tree: NpmDependency): void;
11
- protected extractProductionDependencyGraph(tree: NpmDependency, dependencyId: string): void;
12
- protected parseDependenciesTree(jsonBlob: string): NpmDependency;
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
  }