app-builder-lib 26.13.1 → 26.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/helpers/dynamic-import.js +24 -7
- package/out/asar/asarFileChecker.js.map +1 -1
- package/out/configuration.d.ts +11 -0
- package/out/configuration.js.map +1 -1
- package/out/electron/ElectronFramework.js +1 -5
- package/out/electron/ElectronFramework.js.map +1 -1
- package/out/frameworks/LibUiFramework.d.ts +25 -0
- package/out/frameworks/LibUiFramework.js +107 -19
- package/out/frameworks/LibUiFramework.js.map +1 -1
- package/out/mac/MacTargetHelper.d.ts +7 -2
- package/out/mac/MacTargetHelper.js +13 -10
- package/out/mac/MacTargetHelper.js.map +1 -1
- package/out/macPackager.js +2 -3
- package/out/macPackager.js.map +1 -1
- package/out/node-module-collector/moduleManager.d.ts +6 -0
- package/out/node-module-collector/moduleManager.js +65 -55
- package/out/node-module-collector/moduleManager.js.map +1 -1
- package/out/node-module-collector/nodeModulesCollector.d.ts +17 -8
- package/out/node-module-collector/nodeModulesCollector.js +87 -61
- package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/pnpmNodeModulesCollector.js +7 -5
- package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
- package/out/options/linuxOptions.d.ts +10 -0
- package/out/options/linuxOptions.js.map +1 -1
- package/out/options/macOptions.d.ts +41 -2
- package/out/options/macOptions.js.map +1 -1
- package/out/packager.d.ts +0 -4
- package/out/packager.js +0 -19
- package/out/packager.js.map +1 -1
- package/out/platformPackager.d.ts +1 -5
- package/out/platformPackager.js +9 -31
- package/out/platformPackager.js.map +1 -1
- package/out/targets/FpmTarget.js +6 -5
- package/out/targets/FpmTarget.js.map +1 -1
- package/out/targets/LinuxTargetHelper.d.ts +2 -1
- package/out/targets/LinuxTargetHelper.js +23 -0
- package/out/targets/LinuxTargetHelper.js.map +1 -1
- package/out/targets/MsiTarget.js +2 -1
- package/out/targets/MsiTarget.js.map +1 -1
- package/out/targets/appimage/AppImageTarget.js +6 -1
- package/out/targets/appimage/AppImageTarget.js.map +1 -1
- package/out/targets/appimage/appImageUtil.d.ts +4 -2
- package/out/targets/appimage/appImageUtil.js +2 -2
- package/out/targets/appimage/appImageUtil.js.map +1 -1
- package/out/targets/archive.d.ts +0 -1
- package/out/targets/archive.js +60 -88
- package/out/targets/archive.js.map +1 -1
- package/out/targets/blockmap/blockmap.d.ts +16 -0
- package/out/targets/blockmap/blockmap.js +153 -0
- package/out/targets/blockmap/blockmap.js.map +1 -0
- package/out/targets/differentialUpdateInfoBuilder.js +3 -3
- package/out/targets/differentialUpdateInfoBuilder.js.map +1 -1
- package/out/targets/nsis/NsisTarget.js +6 -12
- package/out/targets/nsis/NsisTarget.js.map +1 -1
- package/out/targets/nsis/nsisValidation.js +5 -4
- package/out/targets/nsis/nsisValidation.js.map +1 -1
- package/out/targets/pkg.d.ts +13 -0
- package/out/targets/pkg.js +34 -9
- package/out/targets/pkg.js.map +1 -1
- package/out/targets/snap/core24.js +4 -3
- package/out/targets/snap/core24.js.map +1 -1
- package/out/targets/snap/coreLegacy.d.ts +23 -0
- package/out/targets/snap/coreLegacy.js +161 -23
- package/out/targets/snap/coreLegacy.js.map +1 -1
- package/out/toolsets/7zip.d.ts +2 -0
- package/out/toolsets/7zip.js +72 -0
- package/out/toolsets/7zip.js.map +1 -0
- package/out/toolsets/icons.d.ts +8 -0
- package/out/toolsets/icons.js +37 -0
- package/out/toolsets/icons.js.map +1 -0
- package/out/toolsets/wine.d.ts +5 -0
- package/out/toolsets/wine.js +100 -0
- package/out/toolsets/wine.js.map +1 -0
- package/out/util/electronGet.js +36 -5
- package/out/util/electronGet.js.map +1 -1
- package/out/util/iconConverter.d.ts +25 -0
- package/out/util/iconConverter.js +260 -0
- package/out/util/iconConverter.js.map +1 -0
- package/out/util/packageDependencies.d.ts +0 -6
- package/out/util/packageDependencies.js +0 -17
- package/out/util/packageDependencies.js.map +1 -1
- package/out/util/yarn.d.ts +0 -3
- package/out/util/yarn.js +3 -15
- 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/vm/WineVm.d.ts +5 -2
- package/out/vm/WineVm.js +19 -5
- package/out/vm/WineVm.js.map +1 -1
- package/out/vm/vm.js.map +1 -1
- package/package.json +10 -9
- package/scheme.json +39 -4
- package/templates/snap/desktop-common.sh +444 -0
- package/templates/snap/desktop-gnome-specific.sh +31 -0
- package/templates/snap/desktop-init.sh +52 -0
- package/out/util/appBuilder.d.ts +0 -4
- package/out/util/appBuilder.js +0 -36
- package/out/util/appBuilder.js.map +0 -1
- package/out/wine.d.ts +0 -5
- package/out/wine.js +0 -31
- package/out/wine.js.map +0 -1
|
@@ -214,7 +214,7 @@ class ModuleManager {
|
|
|
214
214
|
* Looks for node_modules/\*\/node_modules/pkgName (and deeper)
|
|
215
215
|
*/
|
|
216
216
|
async downwardSearch(parentDir, pkgName, requiredRange, maxExplored = 2000, maxDepth = 6) {
|
|
217
|
-
var _a
|
|
217
|
+
var _a;
|
|
218
218
|
const start = path.join(path.resolve(parentDir), "node_modules");
|
|
219
219
|
if (!(await this.exists[start]) || !((_a = (await this.lstat[start])) === null || _a === void 0 ? void 0 : _a.isDirectory())) {
|
|
220
220
|
return null;
|
|
@@ -242,70 +242,80 @@ class ModuleManager {
|
|
|
242
242
|
continue;
|
|
243
243
|
}
|
|
244
244
|
const entryPath = path.join(dir, entry);
|
|
245
|
-
// handle scoped packages @scope/name
|
|
246
245
|
if (entry.startsWith("@")) {
|
|
247
|
-
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
for (const sc of scopeEntries) {
|
|
251
|
-
const scPath = path.join(entryPath, sc);
|
|
252
|
-
// check scPath/node_modules/pkgName
|
|
253
|
-
const candidatePkgJson = path.join(scPath, "node_modules", pkgName, "package.json");
|
|
254
|
-
if (await this.exists[candidatePkgJson]) {
|
|
255
|
-
const json = await this.json[candidatePkgJson];
|
|
256
|
-
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
257
|
-
return { packageDir: path.dirname(candidatePkgJson), packageJson: json };
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
// enqueue scPath/node_modules to explore further
|
|
261
|
-
const scNodeModules = path.join(scPath, "node_modules");
|
|
262
|
-
if ((await this.exists[scNodeModules]) && ((_c = (await this.lstat[scNodeModules])) === null || _c === void 0 ? void 0 : _c.isDirectory())) {
|
|
263
|
-
if (!visited.has(scNodeModules)) {
|
|
264
|
-
visited.add(scNodeModules);
|
|
265
|
-
queue.push({ dir: scNodeModules, depth: depth + 1 });
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
246
|
+
const found = await this.processScope(entryPath, pkgName, requiredRange, depth, visited, queue);
|
|
247
|
+
if (found) {
|
|
248
|
+
return found;
|
|
269
249
|
}
|
|
270
250
|
continue;
|
|
271
251
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (!(stat === null || stat === void 0 ? void 0 : stat.isDirectory())) {
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
catch {
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
const candidatePkgJson = path.join(entryPath, "node_modules", pkgName, "package.json");
|
|
283
|
-
if (await this.exists[candidatePkgJson]) {
|
|
284
|
-
const json = await this.json[candidatePkgJson];
|
|
285
|
-
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
286
|
-
return { packageDir: path.dirname(candidatePkgJson), packageJson: json };
|
|
287
|
-
}
|
|
252
|
+
const found = await this.processEntry(entryPath, pkgName, requiredRange, depth, visited, queue);
|
|
253
|
+
if (found) {
|
|
254
|
+
return found;
|
|
288
255
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
/** Handle a non-scoped entry directory inside a node_modules folder. */
|
|
261
|
+
async processEntry(entryPath, pkgName, requiredRange, depth, visited, queue) {
|
|
262
|
+
const stat = await this.lstat[entryPath];
|
|
263
|
+
if (!(stat === null || stat === void 0 ? void 0 : stat.isDirectory())) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
// Check entry/node_modules/pkgName (nested dep under a package)
|
|
267
|
+
const nested = path.join(entryPath, "node_modules", pkgName, "package.json");
|
|
268
|
+
if (await this.exists[nested]) {
|
|
269
|
+
const json = await this.json[nested];
|
|
270
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
271
|
+
return { packageDir: path.dirname(nested), packageJson: json };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Check entry/pkgName directly (some flat layouts place pkgName as a sibling)
|
|
275
|
+
const direct = path.join(entryPath, pkgName, "package.json");
|
|
276
|
+
if (await this.exists[direct]) {
|
|
277
|
+
const json = await this.json[direct];
|
|
278
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
279
|
+
return { packageDir: path.dirname(direct), packageJson: json };
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
await this.enqueueIfExists(path.join(entryPath, "node_modules"), depth, visited, queue);
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
/** Handle a scoped-package directory (@scope) inside a node_modules folder. */
|
|
286
|
+
async processScope(scopePath, pkgName, requiredRange, depth, visited, queue) {
|
|
287
|
+
var _a;
|
|
288
|
+
if (!(await this.exists[scopePath]) || !((_a = (await this.lstat[scopePath])) === null || _a === void 0 ? void 0 : _a.isDirectory())) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
let scopeEntries;
|
|
292
|
+
try {
|
|
293
|
+
scopeEntries = await fs.readdir(scopePath);
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
for (const sc of scopeEntries) {
|
|
299
|
+
const scPath = path.join(scopePath, sc);
|
|
300
|
+
const candidatePkgJson = path.join(scPath, "node_modules", pkgName, "package.json");
|
|
301
|
+
if (await this.exists[candidatePkgJson]) {
|
|
302
|
+
const json = await this.json[candidatePkgJson];
|
|
303
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
304
|
+
return { packageDir: path.dirname(candidatePkgJson), packageJson: json };
|
|
304
305
|
}
|
|
305
306
|
}
|
|
307
|
+
await this.enqueueIfExists(path.join(scPath, "node_modules"), depth, visited, queue);
|
|
306
308
|
}
|
|
307
309
|
return null;
|
|
308
310
|
}
|
|
311
|
+
/** Enqueue a node_modules directory for BFS only if it exists on disk and hasn't been visited. */
|
|
312
|
+
async enqueueIfExists(nmPath, depth, visited, queue) {
|
|
313
|
+
var _a;
|
|
314
|
+
if (!visited.has(nmPath) && (await this.exists[nmPath]) && ((_a = (await this.lstat[nmPath])) === null || _a === void 0 ? void 0 : _a.isDirectory())) {
|
|
315
|
+
visited.add(nmPath);
|
|
316
|
+
queue.push({ dir: nmPath, depth: depth + 1 });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
309
319
|
}
|
|
310
320
|
exports.ModuleManager = ModuleManager;
|
|
311
321
|
//# sourceMappingURL=moduleManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moduleManager.js","sourceRoot":"","sources":["../../src/node-module-collector/moduleManager.ts"],"names":[],"mappings":";;;AAAA,+CAAqE;AAErE,+BAA8B;AAC9B,6BAA4B;AAC5B,iCAAgC;AAEhC,IAAY,eAUX;AAVD,WAAY,eAAe;IACzB,wEAAqD,CAAA;IACrD,8FAA2E,CAAA;IAC3E,oEAAiD,CAAA;IACjD,mEAAgD,CAAA;IAChD,iEAA8C,CAAA;IAC9C,+EAA4D,CAAA;IAC5D,6PAAqO,CAAA;IACrO,mEAAgD,CAAA;IAChD,6LAAqK,CAAA;AACvK,CAAC,EAVW,eAAe,+BAAf,eAAe,QAU1B;AACY,QAAA,oBAAoB,GAAsC;IACrE,CAAC,eAAe,CAAC,iBAAiB,CAAC,EAAE,MAAM;IAC3C,CAAC,eAAe,CAAC,4BAA4B,CAAC,EAAE,MAAM;IACtD,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM;IACvC,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,MAAM;IACzC,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,OAAO;IACvC,CAAC,eAAe,CAAC,0BAA0B,CAAC,EAAE,MAAM;IACpD,CAAC,eAAe,CAAC,mCAAmC,CAAC,EAAE,MAAM;IAC7D,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE,MAAM;IAC9C,CAAC,eAAe,CAAC,sBAAsB,CAAC,EAAE,OAAO;CAClD,CAAA;AAYD,MAAa,aAAa;IAqBxB;QAPiB,YAAO,GAAoC,IAAI,GAAG,EAAE,CAAA;QACpD,gBAAW,GAAwB,IAAI,GAAG,EAAE,CAAA;QAC5C,cAAS,GAAyB,IAAI,GAAG,EAAE,CAAA;QAC3C,aAAQ,GAAiC,IAAI,GAAG,EAAE,CAAA;QAClD,mBAAc,GAAgC,IAAI,GAAG,EAAE,CAAA;QACvD,kBAAa,GAAmC,IAAI,GAAG,EAAE,CAAA;QAGxE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,yBAAyB,EAAE,CAAA;QAElD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,IAAA,qBAAM,EAAC,CAAC,CAAC,CAAC,CAAA;QAC7E,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;QAChG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;QAC/F,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;QACxI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAS,EAAE,EAAE;YAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YAChC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YACvC,OAAO,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,cAAc,EAAE,EAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;QAClE,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,yBAAyB;QAC/B,OAAO,IAAI,KAAK,CAAC,EAAqB,EAAE;YACtC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAoB,EAAE,EAAE;gBAC/B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;gBACjC,CAAC;gBACD,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAE,CAAA;YACrC,CAAC;YACD,GAAG,EAAE,CAAC,CAAC,EAAE,GAAoB,EAAE,KAAe,EAAE,EAAE;gBAChD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBAClC,OAAO,IAAI,CAAA;YACb,CAAC;YACD,GAAG,EAAE,CAAC,CAAC,EAAE,GAAoB,EAAE,EAAE;gBAC/B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACpC,CAAC;YACD,0CAA0C;YAC1C,OAAO,EAAE,CAAC,CAAC,EAAE;gBACX,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAA;YAC9C,CAAC;YACD,wBAAwB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;gBACnC,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAsB,CAAC,EAAE,CAAC;oBACnD,OAAO;wBACL,UAAU,EAAE,IAAI;wBAChB,YAAY,EAAE,IAAI;qBACnB,CAAA;gBACH,CAAC;gBACD,OAAO,SAAS,CAAA;YAClB,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,yEAAyE;IACzE,iEAAiE;IACzD,gBAAgB,CAAI,GAAmB,EAAE,OAAwC;QACvF,OAAO,IAAI,KAAK,CAAC,EAAgC,EAAE;YACjD,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,GAAW;gBACtB,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,CAAA;gBACvC,CAAC;gBACD,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;oBACtD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;oBACnB,OAAO,KAAK,CAAA;gBACd,CAAC,CAAC,CAAA;YACJ,CAAC;YACD,GAAG,CAAC,CAAC,EAAE,GAAW,EAAE,KAAQ;gBAC1B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBACnB,OAAO,IAAI,CAAA;YACb,CAAC;YACD,GAAG,CAAC,CAAC,EAAE,GAAW;gBAChB,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACrB,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,iBAAiB,CAAC,GAAoD;QACpE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1D,CAAC;IAES,KAAK,CAAC,gCAAgC,CAAC,GAAW;QAC1D,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACpD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAA;QACjH,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAA;IAC1E,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAAC,EAChC,SAAS,EACT,OAAO,EACP,aAAa,EACb,kBAAkB,GAAG,KAAK,GAqB3B;QACC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,kBAAkB,CAAC,CAAA;QAChG,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAA;QACd,CAAC;QAED,wFAAwF;QACxF,wFAAwF;QACxF,yFAAyF;QACzF,+EAA+E;QAC/E,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAA;YACrG,IAAI,cAAc,EAAE,CAAC;gBACnB,kBAAG,CAAC,KAAK,CACP,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,OAAO,EAAE,EACxF,6EAA6E,CAC9E,CAAA;gBACD,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,cAAc,CAAC,WAAW,CAAC,OAAO,cAAc,aAAa,GAAG,CAAC,CAAA;gBAC5I,OAAO,cAAc,CAAA;YACvB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,SAAiB,EAAE,OAAe,EAAE,aAAiC,EAAE,kBAA2B;QAC/H,oDAAoD;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAC1F,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACpC,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;gBAC9D,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;YAChE,CAAC;QACH,CAAC;QAED,gEAAgE;QAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,CAAA;QACzE,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAA;QACf,CAAC;QACD,IAAI,kBAAkB,EAAE,CAAC;YACvB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,IAAI,IAAI,CAAA;IAC/E,CAAC;IAEO,eAAe,CAAC,KAAa,EAAE,KAAc;QACnD,IAAI,IAAA,8BAAe,EAAC,KAAK,CAAC,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACpB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;YACrC,4CAA4C;YAC5C,8CAA8C;YAC9C,mHAAmH;YACnH,kBAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,yDAAyD,CAAC,CAAA;YACtF,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;YAC5D,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnD,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBACxB,OAAO,CAAC,KAAK,KAAK,CAAA;YACpB,CAAC;YACD,8CAA8C;YAC9C,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YACxC,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YAClC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACZ,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;YACvB,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,OAAe,EAAE,aAAsB;QACnF,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAA;QACrC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;YAC7E,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;gBACvC,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;oBAC9D,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;gBACnE,CAAC;gBACD,4EAA4E;YAC9E,CAAC;YACD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAK;YACP,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YACpC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,MAAK;YACP,CAAC;YACD,OAAO,GAAG,MAAM,CAAA;QAClB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,OAAe,EAAE,aAAsB,EAAE,WAAW,GAAG,IAAI,EAAE,QAAQ,GAAG,CAAC;;QACvH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC,CAAA;QAChE,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAA,MAAA,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,0CAAE,WAAW,EAAE,CAAA,EAAE,CAAC;YAC7E,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;QACjC,MAAM,KAAK,GAA0C,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAC/E,IAAI,QAAQ,GAAG,CAAC,CAAA;QAEhB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAA;YACrC,IAAI,QAAQ,EAAE,GAAG,WAAW,EAAE,CAAC;gBAC7B,MAAK;YACP,CAAC;YACD,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;gBACrB,SAAQ;YACV,CAAC;YACD,IAAI,OAAiB,CAAA;YACrB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YACjC,CAAC;YAAC,MAAM,CAAC;gBACP,SAAQ;YACV,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC1B,SAAQ;gBACV,CAAC;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBACvC,qCAAqC;gBACrC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC1B,2DAA2D;oBAC3D,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAI,MAAA,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,0CAAE,WAAW,EAAE,CAAA,EAAE,CAAC;wBACnF,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;wBAChD,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;4BAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;4BACvC,oCAAoC;4BACpC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;4BACnF,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;gCACxC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;gCAC9C,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;oCAC9D,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;gCAC1E,CAAC;4BACH,CAAC;4BACD,iDAAiD;4BACjD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;4BACvD,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAI,MAAA,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,0CAAE,WAAW,EAAE,CAAA,EAAE,CAAC;gCAC3F,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;oCAChC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;oCAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;gCACtD,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,SAAQ;gBACV,CAAC;gBAED,yDAAyD;gBACzD,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;oBACxC,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,WAAW,EAAE,CAAA,EAAE,CAAC;wBACzB,SAAQ;oBACV,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAQ;gBACV,CAAC;gBAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;gBACtF,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACxC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;oBAC9C,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;wBAC9D,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;oBAC1E,CAAC;gBACH,CAAC;gBAED,oEAAoE;gBACpE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;gBACrE,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;oBACvC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;oBAC7C,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC;wBAC9D,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;oBACzE,CAAC;gBACH,CAAC;gBAED,kDAAkD;gBAClD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;gBAC5D,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,KAAI,MAAA,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,0CAAE,WAAW,EAAE,CAAA,EAAE,CAAC;oBAC/F,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;wBAClC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;wBAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;oBACxD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AApVD,sCAoVC","sourcesContent":["import { exists, isEmptyOrSpaces, log, LogLevel } from \"builder-util\"\nimport { PackageJson } from \"./types\"\nimport * as fs from \"fs-extra\"\nimport * as path from \"path\"\nimport * as semver from \"semver\"\n\nexport enum LogMessageByKey {\n PKG_DUPLICATE_REF = \"duplicate dependency references\",\n PKG_DUPLICATE_REF_UNRESOLVED = \"unresolved duplicate dependency references\",\n PKG_NOT_FOUND = \"cannot find path for dependency\",\n PKG_NOT_ON_DISK = \"dependency not found on disk\",\n PKG_SELF_REF = \"self-referential dependencies\",\n PKG_OPTIONAL_NOT_INSTALLED = \"missing optional dependencies\",\n PKG_OPTIONAL_PLATFORM_NOT_INSTALLED = \"platform-specific optional dependencies not bundled — add them to your project's optionalDependencies if your app requires them (pnpm 10+ does not auto-install transitive platform binaries)\",\n PKG_COLLECTOR_OUTPUT = \"collector stderr output\",\n PKG_VERSION_OVERRIDDEN = \"dependencies resolved to a version outside the declared range (installed version accepted — likely resolved via package manager overrides)\",\n}\nexport const logMessageLevelByKey: Record<LogMessageByKey, LogLevel> = {\n [LogMessageByKey.PKG_DUPLICATE_REF]: \"info\",\n [LogMessageByKey.PKG_DUPLICATE_REF_UNRESOLVED]: \"warn\",\n [LogMessageByKey.PKG_NOT_FOUND]: \"warn\",\n [LogMessageByKey.PKG_NOT_ON_DISK]: \"warn\",\n [LogMessageByKey.PKG_SELF_REF]: \"debug\",\n [LogMessageByKey.PKG_OPTIONAL_NOT_INSTALLED]: \"info\",\n [LogMessageByKey.PKG_OPTIONAL_PLATFORM_NOT_INSTALLED]: \"warn\",\n [LogMessageByKey.PKG_COLLECTOR_OUTPUT]: \"warn\",\n [LogMessageByKey.PKG_VERSION_OVERRIDDEN]: \"debug\",\n}\n\nexport type Package = { packageDir: string; packageJson: PackageJson }\n\n// Type aliases for clarity\ntype JsonCache = Record<string, Promise<PackageJson | null>>\ntype RealPathCache = Record<string, Promise<string>>\ntype ExistsCache = Record<string, Promise<boolean>>\ntype LstatCache = Record<string, Promise<fs.Stats | null>>\ntype PackageCache = Record<string, Promise<Package | null>>\ntype LogSummaryCache = Record<LogMessageByKey, string[]>\n\nexport class ModuleManager {\n /** Cache for package.json contents (readJson) */\n readonly json: JsonCache\n /** Cache for resolved real paths (if symlink, realpath; otherwise resolve) */\n readonly realPath: RealPathCache\n /** Cache for file/directory existence checks */\n readonly exists: ExistsCache\n /** Cache for lstat results */\n readonly lstat: LstatCache\n /** Cache for package lookups (key: \"packageName||fromDir||semverRange\"). Use helper function `versionedCacheKey` */\n readonly packageData: PackageCache\n /** For logging purposes, just track all dependencies for each key */\n readonly logSummary: LogSummaryCache\n\n private readonly jsonMap: Map<string, PackageJson | null> = new Map()\n private readonly realPathMap: Map<string, string> = new Map()\n private readonly existsMap: Map<string, boolean> = new Map()\n private readonly lstatMap: Map<string, fs.Stats | null> = new Map()\n private readonly packageDataMap: Map<string, Package | null> = new Map()\n private readonly logSummaryMap: Map<LogMessageByKey, string[]> = new Map()\n\n constructor() {\n this.logSummary = this.createLogSummarySyncProxy()\n\n this.exists = this.createAsyncProxy(this.existsMap, (p: string) => exists(p))\n this.json = this.createAsyncProxy(this.jsonMap, (p: string) => fs.readJson(p).catch(() => null))\n this.lstat = this.createAsyncProxy(this.lstatMap, (p: string) => fs.lstat(p).catch(() => null))\n this.packageData = this.createAsyncProxy(this.packageDataMap, (p: string) => this.locatePackageVersionFromCacheKey(p).catch(() => null))\n this.realPath = this.createAsyncProxy(this.realPathMap, async (p: string) => {\n const filePath = path.resolve(p)\n const stat = await this.lstat[filePath]\n return stat?.isSymbolicLink() ? fs.realpath(filePath) : filePath\n })\n }\n\n private createLogSummarySyncProxy(): LogSummaryCache {\n return new Proxy({} as LogSummaryCache, {\n get: (_, key: LogMessageByKey) => {\n if (!this.logSummaryMap.has(key)) {\n this.logSummaryMap.set(key, [])\n }\n return this.logSummaryMap.get(key)!\n },\n set: (_, key: LogMessageByKey, value: string[]) => {\n this.logSummaryMap.set(key, value)\n return true\n },\n has: (_, key: LogMessageByKey) => {\n return this.logSummaryMap.has(key)\n },\n // Add these to make Object.entries() work\n ownKeys: _ => {\n return Array.from(this.logSummaryMap.keys())\n },\n getOwnPropertyDescriptor: (_, key) => {\n if (this.logSummaryMap.has(key as LogMessageByKey)) {\n return {\n enumerable: true,\n configurable: true,\n }\n }\n return undefined\n },\n })\n }\n\n // this allows dot-notation access while still supporting async retrieval\n // e.g., cache.packageJson[somePath] returns Promise<PackageJson>\n private createAsyncProxy<T>(map: Map<string, T>, compute: (key: string) => T | Promise<T>): Record<string, Promise<T>> {\n return new Proxy({} as Record<string, Promise<T>>, {\n async get(_, key: string) {\n if (map.has(key)) {\n return Promise.resolve(map.get(key)!)\n }\n return await Promise.resolve(compute(key)).then(value => {\n map.set(key, value)\n return value\n })\n },\n set(_, key: string, value: T) {\n map.set(key, value)\n return true\n },\n has(_, key: string) {\n return map.has(key)\n },\n })\n }\n\n versionedCacheKey(pkg: { name: string; path: string; semver?: string }): string {\n return [pkg.name, pkg.path, pkg.semver || \"\"].join(\"||\")\n }\n\n protected async locatePackageVersionFromCacheKey(key: string): Promise<Package | null> {\n const [name, fromDir, semverRange] = key.split(\"||\")\n const result = await this.locatePackageVersion({ parentDir: fromDir, pkgName: name, requiredRange: semverRange })\n if (result == null) {\n return null\n }\n return { ...result, packageDir: await this.realPath[result.packageDir] }\n }\n\n public async locatePackageVersion({\n parentDir,\n pkgName,\n requiredRange,\n skipDownwardSearch = false,\n }: {\n /**\n * The directory to start searching from. Typed optional because pnpm JSON output can omit\n * the `path` field at runtime even when the TypeScript type says `string`. An undefined\n * parentDir is treated as \"package not found\" rather than a crash.\n */\n parentDir?: string\n /**\n * The package name to locate. Typed optional for the same reason as parentDir: the pnpm\n * list JSON can omit `name`/`from` fields (e.g. when the root package.json has no name),\n * producing an undefined pkgName at runtime despite the TypeScript type.\n */\n pkgName?: string\n requiredRange?: string\n /**\n * When true, skip the BFS-based `downwardSearch`. Use for layouts that are guaranteed flat\n * (e.g. pnpm's `.pnpm` virtual store), where the downward walk burns thousands of `readdir`\n * / `lstat` calls and finds nothing.\n */\n skipDownwardSearch?: boolean\n }): Promise<Package | null> {\n if (!parentDir || !pkgName) {\n return null\n }\n\n const found = await this.searchForPackage(parentDir, pkgName, requiredRange, skipDownwardSearch)\n if (found) {\n return found\n }\n\n // Second pass: find any installed version of the package when the declared-range search\n // returns nothing. This handles package manager `overrides` (Bun, npm, pnpm, Yarn) that\n // resolve a transitive dependency to a version intentionally outside its declared range.\n // File-system results are already cached, so this pass costs only JS overhead.\n if (requiredRange) {\n const overrideResult = await this.searchForPackage(parentDir, pkgName, undefined, skipDownwardSearch)\n if (overrideResult) {\n log.debug(\n { pkg: pkgName, declared: requiredRange, installed: overrideResult.packageJson.version },\n \"accepting installed package version that doesn't satisfy the declared range\"\n )\n this.logSummary[LogMessageByKey.PKG_VERSION_OVERRIDDEN].push(`${pkgName}@${overrideResult.packageJson.version} (declared ${requiredRange})`)\n return overrideResult\n }\n }\n\n return null\n }\n\n private async searchForPackage(parentDir: string, pkgName: string, requiredRange: string | undefined, skipDownwardSearch: boolean): Promise<Package | null> {\n // 1) check direct parent node_modules/pkgName first\n const direct = path.join(path.resolve(parentDir), \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[direct]) {\n const json = await this.json[direct]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(direct), packageJson: json }\n }\n }\n\n // 2) upward hoisted search, then 3) downward non-hoisted search\n const upward = await this.upwardSearch(parentDir, pkgName, requiredRange)\n if (upward) {\n return upward\n }\n if (skipDownwardSearch) {\n return null\n }\n return (await this.downwardSearch(parentDir, pkgName, requiredRange)) || null\n }\n\n private semverSatisfies(found: string, range?: string): boolean {\n if (isEmptyOrSpaces(range) || range === \"*\") {\n return true\n }\n\n if (range === found) {\n return true\n }\n\n if (semver.validRange(range) == null) {\n // ignore, we can't verify non-semver ranges\n // e.g. git urls, file:, patch:, etc. Example:\n // \"@ai-sdk/google\": \"patch:@ai-sdk/google@npm%3A2.0.43#~/.yarn/patches/@ai-sdk-google-npm-2.0.43-689ed559b3.patch\"\n log.debug({ found, range }, \"unable to validate semver version range, assuming match\")\n return true\n }\n\n try {\n return semver.satisfies(found, range)\n } catch {\n // fallback: simple equality or basic prefix handling (^, ~)\n if (range.startsWith(\"^\") || range.startsWith(\"~\")) {\n const r = range.slice(1)\n return r === found\n }\n // if range is like \"8.x\" or \"8.*\" match major\n const m = range.match(/^(\\d+)[.(*|x)]*/)\n const fm = found.match(/^(\\d+)\\./)\n if (m && fm) {\n return m[1] === fm[1]\n }\n return false\n }\n }\n\n /**\n * Upward search (hoisted)\n */\n private async upwardSearch(parentDir: string, pkgName: string, requiredRange?: string): Promise<Package | null> {\n let current = path.resolve(parentDir)\n const root = path.parse(current).root\n while (true) {\n const candidate = path.join(current, \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[candidate]) {\n const json = await this.json[candidate]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(candidate), packageJson: json }\n }\n // otherwise keep searching upward (we may find a different hoisted version)\n }\n if (current === root) {\n break\n }\n const parent = path.dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n return null\n }\n\n /**\n * Breadth-first downward search from parentDir/node_modules\n * Looks for node_modules/\\*\\/node_modules/pkgName (and deeper)\n */\n private async downwardSearch(parentDir: string, pkgName: string, requiredRange?: string, maxExplored = 2000, maxDepth = 6): Promise<Package | null> {\n const start = path.join(path.resolve(parentDir), \"node_modules\")\n if (!(await this.exists[start]) || !(await this.lstat[start])?.isDirectory()) {\n return null\n }\n\n const visited = new Set<string>()\n const queue: Array<{ dir: string; depth: number }> = [{ dir: start, depth: 0 }]\n let explored = 0\n\n while (queue.length > 0) {\n const { dir, depth } = queue.shift()!\n if (explored++ > maxExplored) {\n break\n }\n if (depth > maxDepth) {\n continue\n }\n let entries: string[]\n try {\n entries = await fs.readdir(dir)\n } catch {\n continue\n }\n for (const entry of entries) {\n if (entry.startsWith(\".\")) {\n continue\n }\n const entryPath = path.join(dir, entry)\n // handle scoped packages @scope/name\n if (entry.startsWith(\"@\")) {\n // queue the scope directory itself to explore its children\n if ((await this.exists[entryPath]) && (await this.lstat[entryPath])?.isDirectory()) {\n const scopeEntries = await fs.readdir(entryPath)\n for (const sc of scopeEntries) {\n const scPath = path.join(entryPath, sc)\n // check scPath/node_modules/pkgName\n const candidatePkgJson = path.join(scPath, \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[candidatePkgJson]) {\n const json = await this.json[candidatePkgJson]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(candidatePkgJson), packageJson: json }\n }\n }\n // enqueue scPath/node_modules to explore further\n const scNodeModules = path.join(scPath, \"node_modules\")\n if ((await this.exists[scNodeModules]) && (await this.lstat[scNodeModules])?.isDirectory()) {\n if (!visited.has(scNodeModules)) {\n visited.add(scNodeModules)\n queue.push({ dir: scNodeModules, depth: depth + 1 })\n }\n }\n }\n }\n continue\n }\n\n // check for direct candidate: entry/node_modules/pkgName\n try {\n const stat = await this.lstat[entryPath]\n if (!stat?.isDirectory()) {\n continue\n }\n } catch {\n continue\n }\n\n const candidatePkgJson = path.join(entryPath, \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[candidatePkgJson]) {\n const json = await this.json[candidatePkgJson]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(candidatePkgJson), packageJson: json }\n }\n }\n\n // also check entry/node_modules directly for pkgName (some layouts)\n const candidateDirect = path.join(entryPath, pkgName, \"package.json\")\n if (await this.exists[candidateDirect]) {\n const json = await this.json[candidateDirect]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(candidateDirect), packageJson: json }\n }\n }\n\n // enqueue entry/node_modules for deeper traversal\n const nextNodeModules = path.join(entryPath, \"node_modules\")\n if ((await this.exists[nextNodeModules]) && (await this.lstat[nextNodeModules])?.isDirectory()) {\n if (!visited.has(nextNodeModules)) {\n visited.add(nextNodeModules)\n queue.push({ dir: nextNodeModules, depth: depth + 1 })\n }\n }\n }\n }\n\n return null\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"moduleManager.js","sourceRoot":"","sources":["../../src/node-module-collector/moduleManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { exists, isEmptyOrSpaces, log, LogLevel } from \"builder-util\"\nimport { PackageJson } from \"./types\"\nimport * as fs from \"fs-extra\"\nimport * as path from \"path\"\nimport * as semver from \"semver\"\n\nexport enum LogMessageByKey {\n PKG_DUPLICATE_REF = \"duplicate dependency references\",\n PKG_DUPLICATE_REF_UNRESOLVED = \"unresolved duplicate dependency references\",\n PKG_NOT_FOUND = \"cannot find path for dependency\",\n PKG_NOT_ON_DISK = \"dependency not found on disk\",\n PKG_SELF_REF = \"self-referential dependencies\",\n PKG_OPTIONAL_NOT_INSTALLED = \"missing optional dependencies\",\n PKG_OPTIONAL_PLATFORM_NOT_INSTALLED = \"platform-specific optional dependencies not bundled — add them to your project's optionalDependencies if your app requires them (pnpm 10+ does not auto-install transitive platform binaries)\",\n PKG_COLLECTOR_OUTPUT = \"collector stderr output\",\n PKG_VERSION_OVERRIDDEN = \"dependencies resolved to a version outside the declared range (installed version accepted — likely resolved via package manager overrides)\",\n}\nexport const logMessageLevelByKey: Record<LogMessageByKey, LogLevel> = {\n [LogMessageByKey.PKG_DUPLICATE_REF]: \"info\",\n [LogMessageByKey.PKG_DUPLICATE_REF_UNRESOLVED]: \"warn\",\n [LogMessageByKey.PKG_NOT_FOUND]: \"warn\",\n [LogMessageByKey.PKG_NOT_ON_DISK]: \"warn\",\n [LogMessageByKey.PKG_SELF_REF]: \"debug\",\n [LogMessageByKey.PKG_OPTIONAL_NOT_INSTALLED]: \"info\",\n [LogMessageByKey.PKG_OPTIONAL_PLATFORM_NOT_INSTALLED]: \"warn\",\n [LogMessageByKey.PKG_COLLECTOR_OUTPUT]: \"warn\",\n [LogMessageByKey.PKG_VERSION_OVERRIDDEN]: \"debug\",\n}\n\nexport type Package = { packageDir: string; packageJson: PackageJson }\n\n// Type aliases for clarity\ntype JsonCache = Record<string, Promise<PackageJson | null>>\ntype RealPathCache = Record<string, Promise<string>>\ntype ExistsCache = Record<string, Promise<boolean>>\ntype LstatCache = Record<string, Promise<fs.Stats | null>>\ntype PackageCache = Record<string, Promise<Package | null>>\ntype LogSummaryCache = Record<LogMessageByKey, string[]>\n\nexport class ModuleManager {\n /** Cache for package.json contents (readJson) */\n readonly json: JsonCache\n /** Cache for resolved real paths (if symlink, realpath; otherwise resolve) */\n readonly realPath: RealPathCache\n /** Cache for file/directory existence checks */\n readonly exists: ExistsCache\n /** Cache for lstat results */\n readonly lstat: LstatCache\n /** Cache for package lookups (key: \"packageName||fromDir||semverRange\"). Use helper function `versionedCacheKey` */\n readonly packageData: PackageCache\n /** For logging purposes, just track all dependencies for each key */\n readonly logSummary: LogSummaryCache\n\n private readonly jsonMap: Map<string, PackageJson | null> = new Map()\n private readonly realPathMap: Map<string, string> = new Map()\n private readonly existsMap: Map<string, boolean> = new Map()\n private readonly lstatMap: Map<string, fs.Stats | null> = new Map()\n private readonly packageDataMap: Map<string, Package | null> = new Map()\n private readonly logSummaryMap: Map<LogMessageByKey, string[]> = new Map()\n\n constructor() {\n this.logSummary = this.createLogSummarySyncProxy()\n\n this.exists = this.createAsyncProxy(this.existsMap, (p: string) => exists(p))\n this.json = this.createAsyncProxy(this.jsonMap, (p: string) => fs.readJson(p).catch(() => null))\n this.lstat = this.createAsyncProxy(this.lstatMap, (p: string) => fs.lstat(p).catch(() => null))\n this.packageData = this.createAsyncProxy(this.packageDataMap, (p: string) => this.locatePackageVersionFromCacheKey(p).catch(() => null))\n this.realPath = this.createAsyncProxy(this.realPathMap, async (p: string) => {\n const filePath = path.resolve(p)\n const stat = await this.lstat[filePath]\n return stat?.isSymbolicLink() ? fs.realpath(filePath) : filePath\n })\n }\n\n private createLogSummarySyncProxy(): LogSummaryCache {\n return new Proxy({} as LogSummaryCache, {\n get: (_, key: LogMessageByKey) => {\n if (!this.logSummaryMap.has(key)) {\n this.logSummaryMap.set(key, [])\n }\n return this.logSummaryMap.get(key)!\n },\n set: (_, key: LogMessageByKey, value: string[]) => {\n this.logSummaryMap.set(key, value)\n return true\n },\n has: (_, key: LogMessageByKey) => {\n return this.logSummaryMap.has(key)\n },\n // Add these to make Object.entries() work\n ownKeys: _ => {\n return Array.from(this.logSummaryMap.keys())\n },\n getOwnPropertyDescriptor: (_, key) => {\n if (this.logSummaryMap.has(key as LogMessageByKey)) {\n return {\n enumerable: true,\n configurable: true,\n }\n }\n return undefined\n },\n })\n }\n\n // this allows dot-notation access while still supporting async retrieval\n // e.g., cache.packageJson[somePath] returns Promise<PackageJson>\n private createAsyncProxy<T>(map: Map<string, T>, compute: (key: string) => T | Promise<T>): Record<string, Promise<T>> {\n return new Proxy({} as Record<string, Promise<T>>, {\n async get(_, key: string) {\n if (map.has(key)) {\n return Promise.resolve(map.get(key)!)\n }\n return await Promise.resolve(compute(key)).then(value => {\n map.set(key, value)\n return value\n })\n },\n set(_, key: string, value: T) {\n map.set(key, value)\n return true\n },\n has(_, key: string) {\n return map.has(key)\n },\n })\n }\n\n versionedCacheKey(pkg: { name: string; path: string; semver?: string }): string {\n return [pkg.name, pkg.path, pkg.semver || \"\"].join(\"||\")\n }\n\n protected async locatePackageVersionFromCacheKey(key: string): Promise<Package | null> {\n const [name, fromDir, semverRange] = key.split(\"||\")\n const result = await this.locatePackageVersion({ parentDir: fromDir, pkgName: name, requiredRange: semverRange })\n if (result == null) {\n return null\n }\n return { ...result, packageDir: await this.realPath[result.packageDir] }\n }\n\n public async locatePackageVersion({\n parentDir,\n pkgName,\n requiredRange,\n skipDownwardSearch = false,\n }: {\n /**\n * The directory to start searching from. Typed optional because pnpm JSON output can omit\n * the `path` field at runtime even when the TypeScript type says `string`. An undefined\n * parentDir is treated as \"package not found\" rather than a crash.\n */\n parentDir?: string\n /**\n * The package name to locate. Typed optional for the same reason as parentDir: the pnpm\n * list JSON can omit `name`/`from` fields (e.g. when the root package.json has no name),\n * producing an undefined pkgName at runtime despite the TypeScript type.\n */\n pkgName?: string\n requiredRange?: string\n /**\n * When true, skip the BFS-based `downwardSearch`. Use for layouts that are guaranteed flat\n * (e.g. pnpm's `.pnpm` virtual store), where the downward walk burns thousands of `readdir`\n * / `lstat` calls and finds nothing.\n */\n skipDownwardSearch?: boolean\n }): Promise<Package | null> {\n if (!parentDir || !pkgName) {\n return null\n }\n\n const found = await this.searchForPackage(parentDir, pkgName, requiredRange, skipDownwardSearch)\n if (found) {\n return found\n }\n\n // Second pass: find any installed version of the package when the declared-range search\n // returns nothing. This handles package manager `overrides` (Bun, npm, pnpm, Yarn) that\n // resolve a transitive dependency to a version intentionally outside its declared range.\n // File-system results are already cached, so this pass costs only JS overhead.\n if (requiredRange) {\n const overrideResult = await this.searchForPackage(parentDir, pkgName, undefined, skipDownwardSearch)\n if (overrideResult) {\n log.debug(\n { pkg: pkgName, declared: requiredRange, installed: overrideResult.packageJson.version },\n \"accepting installed package version that doesn't satisfy the declared range\"\n )\n this.logSummary[LogMessageByKey.PKG_VERSION_OVERRIDDEN].push(`${pkgName}@${overrideResult.packageJson.version} (declared ${requiredRange})`)\n return overrideResult\n }\n }\n\n return null\n }\n\n private async searchForPackage(parentDir: string, pkgName: string, requiredRange: string | undefined, skipDownwardSearch: boolean): Promise<Package | null> {\n // 1) check direct parent node_modules/pkgName first\n const direct = path.join(path.resolve(parentDir), \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[direct]) {\n const json = await this.json[direct]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(direct), packageJson: json }\n }\n }\n\n // 2) upward hoisted search, then 3) downward non-hoisted search\n const upward = await this.upwardSearch(parentDir, pkgName, requiredRange)\n if (upward) {\n return upward\n }\n if (skipDownwardSearch) {\n return null\n }\n return (await this.downwardSearch(parentDir, pkgName, requiredRange)) || null\n }\n\n private semverSatisfies(found: string, range?: string): boolean {\n if (isEmptyOrSpaces(range) || range === \"*\") {\n return true\n }\n\n if (range === found) {\n return true\n }\n\n if (semver.validRange(range) == null) {\n // ignore, we can't verify non-semver ranges\n // e.g. git urls, file:, patch:, etc. Example:\n // \"@ai-sdk/google\": \"patch:@ai-sdk/google@npm%3A2.0.43#~/.yarn/patches/@ai-sdk-google-npm-2.0.43-689ed559b3.patch\"\n log.debug({ found, range }, \"unable to validate semver version range, assuming match\")\n return true\n }\n\n try {\n return semver.satisfies(found, range)\n } catch {\n // fallback: simple equality or basic prefix handling (^, ~)\n if (range.startsWith(\"^\") || range.startsWith(\"~\")) {\n const r = range.slice(1)\n return r === found\n }\n // if range is like \"8.x\" or \"8.*\" match major\n const m = range.match(/^(\\d+)[.(*|x)]*/)\n const fm = found.match(/^(\\d+)\\./)\n if (m && fm) {\n return m[1] === fm[1]\n }\n return false\n }\n }\n\n /**\n * Upward search (hoisted)\n */\n private async upwardSearch(parentDir: string, pkgName: string, requiredRange?: string): Promise<Package | null> {\n let current = path.resolve(parentDir)\n const root = path.parse(current).root\n while (true) {\n const candidate = path.join(current, \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[candidate]) {\n const json = await this.json[candidate]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(candidate), packageJson: json }\n }\n // otherwise keep searching upward (we may find a different hoisted version)\n }\n if (current === root) {\n break\n }\n const parent = path.dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n return null\n }\n\n /**\n * Breadth-first downward search from parentDir/node_modules\n * Looks for node_modules/\\*\\/node_modules/pkgName (and deeper)\n */\n private async downwardSearch(parentDir: string, pkgName: string, requiredRange?: string, maxExplored = 2000, maxDepth = 6): Promise<Package | null> {\n const start = path.join(path.resolve(parentDir), \"node_modules\")\n if (!(await this.exists[start]) || !(await this.lstat[start])?.isDirectory()) {\n return null\n }\n\n const visited = new Set<string>()\n const queue: Array<{ dir: string; depth: number }> = [{ dir: start, depth: 0 }]\n let explored = 0\n\n while (queue.length > 0) {\n const { dir, depth } = queue.shift()!\n if (explored++ > maxExplored) {\n break\n }\n if (depth > maxDepth) {\n continue\n }\n let entries: string[]\n try {\n entries = await fs.readdir(dir)\n } catch {\n continue\n }\n for (const entry of entries) {\n if (entry.startsWith(\".\")) {\n continue\n }\n const entryPath = path.join(dir, entry)\n if (entry.startsWith(\"@\")) {\n const found = await this.processScope(entryPath, pkgName, requiredRange, depth, visited, queue)\n if (found) {\n return found\n }\n continue\n }\n const found = await this.processEntry(entryPath, pkgName, requiredRange, depth, visited, queue)\n if (found) {\n return found\n }\n }\n }\n\n return null\n }\n\n /** Handle a non-scoped entry directory inside a node_modules folder. */\n private async processEntry(\n entryPath: string,\n pkgName: string,\n requiredRange: string | undefined,\n depth: number,\n visited: Set<string>,\n queue: Array<{ dir: string; depth: number }>\n ): Promise<Package | null> {\n const stat = await this.lstat[entryPath]\n if (!stat?.isDirectory()) {\n return null\n }\n\n // Check entry/node_modules/pkgName (nested dep under a package)\n const nested = path.join(entryPath, \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[nested]) {\n const json = await this.json[nested]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(nested), packageJson: json }\n }\n }\n\n // Check entry/pkgName directly (some flat layouts place pkgName as a sibling)\n const direct = path.join(entryPath, pkgName, \"package.json\")\n if (await this.exists[direct]) {\n const json = await this.json[direct]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(direct), packageJson: json }\n }\n }\n\n await this.enqueueIfExists(path.join(entryPath, \"node_modules\"), depth, visited, queue)\n return null\n }\n\n /** Handle a scoped-package directory (@scope) inside a node_modules folder. */\n private async processScope(\n scopePath: string,\n pkgName: string,\n requiredRange: string | undefined,\n depth: number,\n visited: Set<string>,\n queue: Array<{ dir: string; depth: number }>\n ): Promise<Package | null> {\n if (!(await this.exists[scopePath]) || !(await this.lstat[scopePath])?.isDirectory()) {\n return null\n }\n let scopeEntries: string[]\n try {\n scopeEntries = await fs.readdir(scopePath)\n } catch {\n return null\n }\n for (const sc of scopeEntries) {\n const scPath = path.join(scopePath, sc)\n const candidatePkgJson = path.join(scPath, \"node_modules\", pkgName, \"package.json\")\n if (await this.exists[candidatePkgJson]) {\n const json = await this.json[candidatePkgJson]\n if (json && this.semverSatisfies(json.version, requiredRange)) {\n return { packageDir: path.dirname(candidatePkgJson), packageJson: json }\n }\n }\n await this.enqueueIfExists(path.join(scPath, \"node_modules\"), depth, visited, queue)\n }\n return null\n }\n\n /** Enqueue a node_modules directory for BFS only if it exists on disk and hasn't been visited. */\n private async enqueueIfExists(nmPath: string, depth: number, visited: Set<string>, queue: Array<{ dir: string; depth: number }>): Promise<void> {\n if (!visited.has(nmPath) && (await this.exists[nmPath]) && (await this.lstat[nmPath])?.isDirectory()) {\n visited.add(nmPath)\n queue.push({ dir: nmPath, depth: depth + 1 })\n }\n }\n}\n"]}
|
|
@@ -106,8 +106,9 @@ export declare abstract class NodeModulesCollector<ProdDepType extends Dependenc
|
|
|
106
106
|
* Executes a command and streams its output to a file.
|
|
107
107
|
*
|
|
108
108
|
* Spawns a child process to execute the specified command with arguments, capturing stdout
|
|
109
|
-
* to a file.
|
|
110
|
-
*
|
|
109
|
+
* to a file. On Windows, wraps the invocation in `powershell.exe -EncodedCommand` (UTF-16LE
|
|
110
|
+
* base64) to avoid spawning `.cmd` shims directly and to eliminate shell-injection surface area.
|
|
111
|
+
* Enables corepack strict mode by default but allows process.env overrides.
|
|
111
112
|
*
|
|
112
113
|
* Special handling for `npm list` exit code 1, which is expected in certain scenarios.
|
|
113
114
|
*
|
|
@@ -119,10 +120,18 @@ export declare abstract class NodeModulesCollector<ProdDepType extends Dependenc
|
|
|
119
120
|
* @throws {Error} If the child process spawn fails or exits with a non-zero code
|
|
120
121
|
*/
|
|
121
122
|
protected streamCollectorCommandToFile(command: string, args: string[], cwd: string, tempOutputFile: string): Promise<void>;
|
|
122
|
-
/**
|
|
123
|
-
* Windows-only. Wraps .cmd files and executables at paths containing spaces in a temporary .bat
|
|
124
|
-
* file so that cmd.exe spawns them correctly. Returns the original command/args unchanged when
|
|
125
|
-
* no wrapping is required. Must only be called on win32.
|
|
126
|
-
*/
|
|
127
|
-
private resolveWindowsCommand;
|
|
128
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Build the argv for invoking a Windows command through `powershell.exe -EncodedCommand`.
|
|
126
|
+
*
|
|
127
|
+
* Each token is wrapped in a PowerShell single-quoted string (with embedded single quotes doubled),
|
|
128
|
+
* so no character is interpreted by a shell. The script:
|
|
129
|
+
* - pins `[Console]::OutputEncoding` to UTF-8 *without* a BOM so the JSON dependency tree is not
|
|
130
|
+
* corrupted by the console's OEM code page (and no BOM is prepended to break `JSON.parse`),
|
|
131
|
+
* - invokes the command via the call operator `&`,
|
|
132
|
+
* - re-emits the command's own exit code via `exit $LASTEXITCODE` (e.g. `npm list` returns 1 in
|
|
133
|
+
* expected scenarios, which the caller's shouldIgnore logic relies on).
|
|
134
|
+
*
|
|
135
|
+
* The whole script is base64-encoded as UTF-16LE per PowerShell's `-EncodedCommand` contract.
|
|
136
|
+
*/
|
|
137
|
+
export declare function buildPowerShellEncodedArgs(command: string, args: string[]): string[];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NodeModulesCollector = void 0;
|
|
4
|
+
exports.buildPowerShellEncodedArgs = buildPowerShellEncodedArgs;
|
|
4
5
|
const builder_util_1 = require("builder-util");
|
|
5
6
|
const childProcess = require("child_process");
|
|
6
|
-
const crypto_1 = require("crypto");
|
|
7
7
|
const fs = require("fs-extra");
|
|
8
8
|
const fs_extra_1 = require("fs-extra");
|
|
9
9
|
const lazy_val_1 = require("lazy-val");
|
|
@@ -24,7 +24,7 @@ class NodeModulesCollector {
|
|
|
24
24
|
const command = (0, packageManager_1.getPackageManagerCommand)(manager);
|
|
25
25
|
const config = (await this.asyncExec(command, ["config", "list"])).stdout;
|
|
26
26
|
if (config == null) {
|
|
27
|
-
builder_util_1.log.debug({ manager }, "unable to determine
|
|
27
|
+
builder_util_1.log.debug({ manager }, "unable to determine node-linker setting; assuming non-hoisted (virtual store) layout");
|
|
28
28
|
return false;
|
|
29
29
|
}
|
|
30
30
|
const lines = Object.fromEntries(config.split("\n").map(line => line.split("=").map(s => s.trim())));
|
|
@@ -82,7 +82,7 @@ class NodeModulesCollector {
|
|
|
82
82
|
interval: 2000,
|
|
83
83
|
backoff: 2000,
|
|
84
84
|
shouldRetry: async (error) => {
|
|
85
|
-
var _a;
|
|
85
|
+
var _a, _b;
|
|
86
86
|
const fields = { error: error.message, tempOutputFile, cwd: this.rootDir, packageManager: pm };
|
|
87
87
|
if (!(await (0, builder_util_1.exists)(tempOutputFile))) {
|
|
88
88
|
builder_util_1.log.debug(fields, "dependency tree output file missing, retrying");
|
|
@@ -104,7 +104,8 @@ class NodeModulesCollector {
|
|
|
104
104
|
else {
|
|
105
105
|
fields.content = fileContent;
|
|
106
106
|
}
|
|
107
|
-
|
|
107
|
+
// Both indicate truncated/polluted PM output (a transient that re-running the command clears).
|
|
108
|
+
if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes("Unexpected end of JSON input")) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes("No JSON content found in output"))) {
|
|
108
109
|
builder_util_1.log.debug(fields, "JSON parse error in dependency tree, retrying");
|
|
109
110
|
return true;
|
|
110
111
|
}
|
|
@@ -297,8 +298,9 @@ class NodeModulesCollector {
|
|
|
297
298
|
* Executes a command and streams its output to a file.
|
|
298
299
|
*
|
|
299
300
|
* Spawns a child process to execute the specified command with arguments, capturing stdout
|
|
300
|
-
* to a file.
|
|
301
|
-
*
|
|
301
|
+
* to a file. On Windows, wraps the invocation in `powershell.exe -EncodedCommand` (UTF-16LE
|
|
302
|
+
* base64) to avoid spawning `.cmd` shims directly and to eliminate shell-injection surface area.
|
|
303
|
+
* Enables corepack strict mode by default but allows process.env overrides.
|
|
302
304
|
*
|
|
303
305
|
* Special handling for `npm list` exit code 1, which is expected in certain scenarios.
|
|
304
306
|
*
|
|
@@ -310,46 +312,63 @@ class NodeModulesCollector {
|
|
|
310
312
|
* @throws {Error} If the child process spawn fails or exits with a non-zero code
|
|
311
313
|
*/
|
|
312
314
|
async streamCollectorCommandToFile(command, args, cwd, tempOutputFile) {
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
+
// Derive execName from the original command so the npm-list shouldIgnore check below keys off the
|
|
316
|
+
// real invocation (e.g. "npm"), not the "powershell" wrapper we spawn on Windows.
|
|
315
317
|
const execName = path.basename(command, path.extname(command));
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
// On non-Windows, shell:false means args are passed directly to the process with no shell
|
|
324
|
-
// interpretation, so the metacharacter guard is only necessary on Windows.
|
|
325
|
-
if (isWindows) {
|
|
326
|
-
// Guard against cmd.exe metacharacters. Parentheses are intentionally excluded because they
|
|
327
|
-
// appear in legitimate Windows paths (e.g. "C:\Program Files (x86)").
|
|
328
|
-
const SHELL_INJECTION_RE = /[;&|`${}[\]<>!%^]/;
|
|
329
|
-
for (const arg of args) {
|
|
330
|
-
if (SHELL_INJECTION_RE.test(arg)) {
|
|
331
|
-
throw new Error(`Refusing to spawn "${command}": argument "${arg}" contains shell metacharacters. Possible injection attempt.`);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
318
|
+
// On Windows the package-manager command is typically a `.cmd` shim (npm.cmd/pnpm.cmd/yarn.cmd),
|
|
319
|
+
// which Node can no longer spawn directly (CVE-2024-27980). Rather than spawn with `shell: true` —
|
|
320
|
+
// which emits the DEP0190 "args with shell" deprecation warning and forces manual metacharacter
|
|
321
|
+
// escaping — wrap the invocation in a single PowerShell `-EncodedCommand`. The base64 (UTF-16LE)
|
|
322
|
+
// payload sidesteps every shell-quoting layer, and `powershell.exe` is a real executable we spawn
|
|
323
|
+
// directly with no shell. See buildPowerShellEncodedArgs for the UTF-8 / exit-code handling.
|
|
324
|
+
const [spawnCommand, spawnArgs] = process.platform === "win32" ? ["powershell.exe", buildPowerShellEncodedArgs(command, args)] : [command, args];
|
|
335
325
|
await new Promise((resolve, reject) => {
|
|
336
326
|
const outStream = (0, fs_extra_1.createWriteStream)(tempOutputFile);
|
|
337
|
-
const child = childProcess.spawn(
|
|
327
|
+
const child = childProcess.spawn(spawnCommand, spawnArgs, {
|
|
338
328
|
cwd,
|
|
339
329
|
// Package manager invocations do not need signing/publishing credentials.
|
|
340
330
|
env: { COREPACK_ENABLE_STRICT: "0", ...(0, builder_util_1.stripSensitiveEnvVars)(process.env) },
|
|
341
|
-
shell: isWindows, // shell: true is required on Windows — see https://github.com/electron-userland/electron-builder/issues/9488
|
|
342
331
|
});
|
|
343
332
|
let stderr = "";
|
|
333
|
+
// The process can close before all piped stdout has been flushed to disk. Resolving on the
|
|
334
|
+
// child's "close" alone races the write stream and lets the caller read a TRUNCATED file
|
|
335
|
+
// (manifesting as "No JSON content found in output"). Gate the settle on BOTH the child exit
|
|
336
|
+
// (for the code/stderr) and the write stream's "finish" (all bytes flushed).
|
|
337
|
+
let exitCode = null;
|
|
338
|
+
let childClosed = false;
|
|
339
|
+
let streamFinished = false;
|
|
340
|
+
let settled = false;
|
|
341
|
+
// `pipe` ends `outStream` when stdout EOFs, which triggers its "finish" once flushed.
|
|
344
342
|
child.stdout.pipe(outStream);
|
|
345
343
|
child.stderr.on("data", chunk => {
|
|
346
344
|
stderr += chunk.toString();
|
|
347
345
|
});
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
346
|
+
const fail = (err) => {
|
|
347
|
+
if (settled) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
settled = true;
|
|
351
|
+
// Best-effort cleanup: stop the child and close the stream so we don't
|
|
352
|
+
// waste CPU writing to a broken fd after rejection.
|
|
353
|
+
try {
|
|
354
|
+
child.kill();
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
// ignore
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
outStream.destroy();
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
// ignore
|
|
364
|
+
}
|
|
365
|
+
reject(err);
|
|
366
|
+
};
|
|
367
|
+
const settle = () => {
|
|
368
|
+
if (settled || !childClosed || !streamFinished) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const code = exitCode;
|
|
353
372
|
// https://github.com/npm/npm/issues/17624
|
|
354
373
|
const shouldIgnore = code === 1 && "npm" === execName.toLowerCase() && args.includes("list");
|
|
355
374
|
if (shouldIgnore) {
|
|
@@ -365,38 +384,45 @@ class NodeModulesCollector {
|
|
|
365
384
|
this.cache.logSummary[moduleManager_1.LogMessageByKey.PKG_COLLECTOR_OUTPUT].push(stderr);
|
|
366
385
|
}
|
|
367
386
|
}
|
|
387
|
+
settled = true;
|
|
368
388
|
const shouldResolve = code === 0 || shouldIgnore;
|
|
369
389
|
return shouldResolve ? resolve() : reject(new Error(`Node module collector process exited with code ${code}:\n${stderr}`));
|
|
390
|
+
};
|
|
391
|
+
outStream.on("error", err => fail(new Error(`Node module collector failed writing output (${command}): ${err.message}`)));
|
|
392
|
+
outStream.on("finish", () => {
|
|
393
|
+
streamFinished = true;
|
|
394
|
+
settle();
|
|
395
|
+
});
|
|
396
|
+
child.on("error", err => {
|
|
397
|
+
fail(new Error(`Node module collector spawn (${command} ${JSON.stringify(args)}) failed: ${err.message}`));
|
|
398
|
+
});
|
|
399
|
+
child.on("close", code => {
|
|
400
|
+
exitCode = code;
|
|
401
|
+
childClosed = true;
|
|
402
|
+
settle();
|
|
370
403
|
});
|
|
371
404
|
});
|
|
372
405
|
}
|
|
373
|
-
/**
|
|
374
|
-
* Windows-only. Wraps .cmd files and executables at paths containing spaces in a temporary .bat
|
|
375
|
-
* file so that cmd.exe spawns them correctly. Returns the original command/args unchanged when
|
|
376
|
-
* no wrapping is required. Must only be called on win32.
|
|
377
|
-
*/
|
|
378
|
-
async resolveWindowsCommand(command, args) {
|
|
379
|
-
if (process.platform !== "win32") {
|
|
380
|
-
throw new Error("resolveWindowsCommand should only be called on Windows platforms");
|
|
381
|
-
}
|
|
382
|
-
const ext = path.extname(command).toLowerCase();
|
|
383
|
-
// Wrap .cmd files and any Windows executable path that contains spaces (e.g. extensionless
|
|
384
|
-
// shims from tools like Volta installed at "C:\Program Files\Volta\") to ensure the path is
|
|
385
|
-
// quoted correctly when passed to `spawn(..., { shell: true })`.
|
|
386
|
-
const needsWrap = ext === ".cmd" || command.includes(" ");
|
|
387
|
-
if (!needsWrap) {
|
|
388
|
-
return { command, args };
|
|
389
|
-
}
|
|
390
|
-
const execName = path.basename(command, ext);
|
|
391
|
-
const tempBatFile = await this.tempDirManager.getTempFile({
|
|
392
|
-
prefix: execName + "-" + (0, crypto_1.randomBytes)(8).toString("hex"),
|
|
393
|
-
suffix: ".bat",
|
|
394
|
-
});
|
|
395
|
-
const escapedCommand = command.replace(/"/g, `""`);
|
|
396
|
-
const batScript = `@echo off\r\n"${escapedCommand}" %*\r\n`; // <-- CRLF required for .bat
|
|
397
|
-
await fs.writeFile(tempBatFile, batScript, { encoding: "utf8", mode: 0o600 });
|
|
398
|
-
return { command: "cmd.exe", args: ["/c", `"${tempBatFile}"`, ...args] };
|
|
399
|
-
}
|
|
400
406
|
}
|
|
401
407
|
exports.NodeModulesCollector = NodeModulesCollector;
|
|
408
|
+
/**
|
|
409
|
+
* Build the argv for invoking a Windows command through `powershell.exe -EncodedCommand`.
|
|
410
|
+
*
|
|
411
|
+
* Each token is wrapped in a PowerShell single-quoted string (with embedded single quotes doubled),
|
|
412
|
+
* so no character is interpreted by a shell. The script:
|
|
413
|
+
* - pins `[Console]::OutputEncoding` to UTF-8 *without* a BOM so the JSON dependency tree is not
|
|
414
|
+
* corrupted by the console's OEM code page (and no BOM is prepended to break `JSON.parse`),
|
|
415
|
+
* - invokes the command via the call operator `&`,
|
|
416
|
+
* - re-emits the command's own exit code via `exit $LASTEXITCODE` (e.g. `npm list` returns 1 in
|
|
417
|
+
* expected scenarios, which the caller's shouldIgnore logic relies on).
|
|
418
|
+
*
|
|
419
|
+
* The whole script is base64-encoded as UTF-16LE per PowerShell's `-EncodedCommand` contract.
|
|
420
|
+
*/
|
|
421
|
+
function buildPowerShellEncodedArgs(command, args) {
|
|
422
|
+
const psQuote = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
423
|
+
const invocation = ["&", psQuote(command), ...args.map(psQuote)].join(" ");
|
|
424
|
+
const script = `[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new($false); ${invocation}; exit $LASTEXITCODE`;
|
|
425
|
+
const encoded = Buffer.from(script, "utf16le").toString("base64");
|
|
426
|
+
return ["-NoProfile", "-NonInteractive", "-EncodedCommand", encoded];
|
|
427
|
+
}
|
|
402
428
|
//# sourceMappingURL=nodeModulesCollector.js.map
|