app-builder-lib 26.1.0 → 26.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/asar/asarUtil.js +78 -10
- package/out/asar/asarUtil.js.map +1 -1
- package/out/codeSign/macCodeSign.js +2 -1
- package/out/codeSign/macCodeSign.js.map +1 -1
- package/out/codeSign/windowsCodeSign.js +1 -1
- package/out/codeSign/windowsCodeSign.js.map +1 -1
- package/out/electron/search-module.js +1 -1
- package/out/electron/search-module.js.map +1 -1
- package/out/fileMatcher.js +1 -1
- package/out/fileMatcher.js.map +1 -1
- package/out/linuxPackager.js +1 -1
- package/out/linuxPackager.js.map +1 -1
- package/out/macPackager.js +31 -6
- package/out/macPackager.js.map +1 -1
- package/out/node-module-collector/bunNodeModulesCollector.d.ts +11 -0
- package/out/node-module-collector/bunNodeModulesCollector.js +22 -0
- package/out/node-module-collector/bunNodeModulesCollector.js.map +1 -0
- package/out/node-module-collector/index.d.ts +18 -6
- package/out/node-module-collector/index.js +102 -28
- package/out/node-module-collector/index.js.map +1 -1
- package/out/node-module-collector/moduleCache.d.ts +21 -0
- package/out/node-module-collector/moduleCache.js +16 -0
- package/out/node-module-collector/moduleCache.js.map +1 -0
- package/out/node-module-collector/nodeModulesCollector.d.ts +48 -13
- package/out/node-module-collector/nodeModulesCollector.js +184 -59
- package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/npmNodeModulesCollector.d.ts +10 -3
- package/out/node-module-collector/npmNodeModulesCollector.js +95 -13
- package/out/node-module-collector/npmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/packageManager.d.ts +2 -2
- package/out/node-module-collector/packageManager.js +44 -22
- package/out/node-module-collector/packageManager.js.map +1 -1
- package/out/node-module-collector/pnpmNodeModulesCollector.d.ts +4 -4
- package/out/node-module-collector/pnpmNodeModulesCollector.js +43 -23
- package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/types.d.ts +25 -1
- package/out/node-module-collector/types.js.map +1 -1
- package/out/node-module-collector/yarnBerryNodeModulesCollector.d.ts +15 -0
- package/out/node-module-collector/yarnBerryNodeModulesCollector.js +83 -0
- package/out/node-module-collector/yarnBerryNodeModulesCollector.js.map +1 -0
- package/out/node-module-collector/yarnNodeModulesCollector.d.ts +12 -2
- package/out/node-module-collector/yarnNodeModulesCollector.js +234 -5
- package/out/node-module-collector/yarnNodeModulesCollector.js.map +1 -1
- package/out/options/PlatformSpecificBuildOptions.d.ts +2 -1
- package/out/options/PlatformSpecificBuildOptions.js.map +1 -1
- package/out/options/macOptions.d.ts +2 -0
- package/out/options/macOptions.js.map +1 -1
- package/out/options/winOptions.d.ts +3 -2
- package/out/options/winOptions.js.map +1 -1
- package/out/packager.d.ts +6 -1
- package/out/packager.js +27 -2
- package/out/packager.js.map +1 -1
- package/out/platformPackager.d.ts +5 -0
- package/out/platformPackager.js +50 -0
- package/out/platformPackager.js.map +1 -1
- package/out/publish/PublishManager.js +2 -2
- package/out/publish/PublishManager.js.map +1 -1
- package/out/targets/AppxTarget.js +1 -1
- package/out/targets/AppxTarget.js.map +1 -1
- package/out/targets/LinuxTargetHelper.js +2 -1
- package/out/targets/LinuxTargetHelper.js.map +1 -1
- package/out/targets/MsiTarget.js +1 -1
- package/out/targets/MsiTarget.js.map +1 -1
- package/out/targets/nsis/NsisTarget.js +2 -2
- package/out/targets/nsis/NsisTarget.js.map +1 -1
- package/out/targets/nsis/nsisUtil.js +7 -1
- package/out/targets/nsis/nsisUtil.js.map +1 -1
- package/out/targets/snap.js +13 -2
- package/out/targets/snap.js.map +1 -1
- package/out/util/appFileCopier.js +17 -10
- package/out/util/appFileCopier.js.map +1 -1
- package/out/util/macosIconComposer.d.ts +10 -0
- package/out/util/macosIconComposer.js +95 -0
- package/out/util/macosIconComposer.js.map +1 -0
- package/out/util/yarn.d.ts +3 -2
- package/out/util/yarn.js +16 -12
- package/out/util/yarn.js.map +1 -1
- package/out/version.d.ts +1 -1
- package/out/version.js +1 -1
- package/out/version.js.map +1 -1
- package/out/winPackager.d.ts +1 -1
- package/out/winPackager.js +26 -9
- package/out/winPackager.js.map +1 -1
- package/package.json +9 -9
- package/scheme.json +9 -9
- package/templates/nsis/uninstaller.nsh +7 -0
|
@@ -1,27 +1,62 @@
|
|
|
1
|
-
import type { NodeModuleInfo, DependencyGraph, Dependency } from "./types";
|
|
2
1
|
import { TmpDir } from "builder-util";
|
|
2
|
+
import { CancellationToken } from "builder-util-runtime";
|
|
3
|
+
import * as fs from "fs-extra";
|
|
4
|
+
import { Lazy } from "lazy-val";
|
|
5
|
+
import { type ModuleCache } from "./moduleCache";
|
|
3
6
|
import { PM } from "./packageManager";
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
import type { Dependency, DependencyGraph, NodeModuleInfo, PackageJson } from "./types";
|
|
8
|
+
export declare abstract class NodeModulesCollector<ProdDepType extends Dependency<ProdDepType, OptionalDepType>, OptionalDepType> {
|
|
9
|
+
protected readonly rootDir: string;
|
|
6
10
|
private readonly tempDirManager;
|
|
7
11
|
private nodeModules;
|
|
8
|
-
protected allDependencies: Map<string,
|
|
12
|
+
protected allDependencies: Map<string, ProdDepType>;
|
|
9
13
|
protected productionGraph: DependencyGraph;
|
|
14
|
+
protected pkgJsonCache: Map<string, string>;
|
|
15
|
+
protected memoResolvedModules: Map<string, Promise<string | null>>;
|
|
16
|
+
protected cache: ModuleCache;
|
|
17
|
+
protected isHoisted: Lazy<boolean>;
|
|
18
|
+
protected appPkgJson: Lazy<PackageJson>;
|
|
10
19
|
constructor(rootDir: string, tempDirManager: TmpDir);
|
|
11
|
-
getNodeModules(
|
|
20
|
+
getNodeModules({ cancellationToken, packageName }: {
|
|
21
|
+
cancellationToken: CancellationToken;
|
|
22
|
+
packageName: string;
|
|
23
|
+
}): Promise<NodeModuleInfo[]>;
|
|
12
24
|
abstract readonly installOptions: {
|
|
13
25
|
manager: PM;
|
|
14
26
|
lockfile: string;
|
|
15
27
|
};
|
|
16
28
|
protected abstract getArgs(): string[];
|
|
17
|
-
protected abstract parseDependenciesTree(jsonBlob: string):
|
|
18
|
-
protected abstract extractProductionDependencyGraph(tree: Dependency<
|
|
19
|
-
protected abstract collectAllDependencies(tree: Dependency<
|
|
20
|
-
protected getDependenciesTree(): Promise<
|
|
21
|
-
protected
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
protected abstract parseDependenciesTree(jsonBlob: string): Promise<ProdDepType>;
|
|
30
|
+
protected abstract extractProductionDependencyGraph(tree: Dependency<ProdDepType, OptionalDepType>, dependencyId: string): Promise<void>;
|
|
31
|
+
protected abstract collectAllDependencies(tree: Dependency<ProdDepType, OptionalDepType>, appPackageName: string): Promise<void>;
|
|
32
|
+
protected getDependenciesTree(pm: PM): Promise<ProdDepType>;
|
|
33
|
+
protected existsMemoized(filePath: string): Promise<boolean>;
|
|
34
|
+
protected readJsonMemoized(filePath: string): Promise<PackageJson>;
|
|
35
|
+
protected lstatMemoized(filePath: string): Promise<fs.Stats>;
|
|
36
|
+
protected realpathMemoized(filePath: string): Promise<string>;
|
|
37
|
+
protected resolvePath(filePath: string): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Resolves a package to its filesystem location using Node.js module resolution.
|
|
40
|
+
* Returns the directory containing the package, not the package.json path.
|
|
41
|
+
*/
|
|
42
|
+
protected resolvePackageDir: (packageName: string, fromDir: string) => string | null;
|
|
43
|
+
protected requireMemoized(pkgPath: string): PackageJson;
|
|
44
|
+
protected existsSyncMemoized(filePath: string): boolean;
|
|
45
|
+
protected cacheKey(pkg: ProdDepType): string;
|
|
46
|
+
protected packageVersionString(pkg: ProdDepType): string;
|
|
47
|
+
/**
|
|
48
|
+
* Parse a dependency identifier like "@scope/pkg@1.2.3" or "pkg@1.2.3"
|
|
49
|
+
*/
|
|
50
|
+
protected parseNameVersion(identifier: string): {
|
|
51
|
+
name: string;
|
|
52
|
+
version: string;
|
|
53
|
+
};
|
|
54
|
+
protected getTreeFromWorkspaces(tree: ProdDepType): Promise<ProdDepType>;
|
|
55
|
+
private transformToHoisterTree;
|
|
24
56
|
private _getNodeModules;
|
|
25
|
-
|
|
57
|
+
asyncExec(command: string, args: string[], cwd?: string): Promise<{
|
|
58
|
+
stdout: string | undefined;
|
|
59
|
+
stderr: string | undefined;
|
|
60
|
+
}>;
|
|
26
61
|
streamCollectorCommandToJsonFile(command: string, args: string[], cwd: string, tempOutputFile: string): Promise<void>;
|
|
27
62
|
}
|
|
@@ -1,14 +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");
|
|
8
|
-
const packageManager_1 = require("./packageManager");
|
|
9
5
|
const child_process_1 = 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
10
|
const util_1 = require("util");
|
|
11
|
-
const
|
|
11
|
+
const hoist_1 = require("./hoist");
|
|
12
|
+
const moduleCache_1 = require("./moduleCache");
|
|
13
|
+
const packageManager_1 = require("./packageManager");
|
|
12
14
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
13
15
|
class NodeModulesCollector {
|
|
14
16
|
constructor(rootDir, tempDirManager) {
|
|
@@ -17,18 +19,72 @@ class NodeModulesCollector {
|
|
|
17
19
|
this.nodeModules = [];
|
|
18
20
|
this.allDependencies = new Map();
|
|
19
21
|
this.productionGraph = {};
|
|
22
|
+
this.pkgJsonCache = new Map();
|
|
23
|
+
this.memoResolvedModules = new Map();
|
|
24
|
+
// Unified cache for all file system and module operations
|
|
25
|
+
this.cache = (0, moduleCache_1.createModuleCache)();
|
|
26
|
+
this.isHoisted = new lazy_val_1.Lazy(async () => {
|
|
27
|
+
const command = (0, packageManager_1.getPackageManagerCommand)(this.installOptions.manager);
|
|
28
|
+
const config = (await this.asyncExec(command, ["config", "list"])).stdout;
|
|
29
|
+
if (config == null) {
|
|
30
|
+
builder_util_1.log.debug({ manager: this.installOptions.manager }, "unable to determine if node_modules are hoisted: no config output. falling back to hoisted mode");
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const lines = Object.fromEntries(config.split("\n").map(line => line.split("=").map(s => s.trim())));
|
|
34
|
+
if (lines["node-linker"] === "hoisted") {
|
|
35
|
+
builder_util_1.log.debug({ manager: this.installOptions.manager }, "node_modules are hoisted");
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
});
|
|
40
|
+
this.appPkgJson = new lazy_val_1.Lazy(async () => {
|
|
41
|
+
const appPkgPath = path.join(this.rootDir, "package.json");
|
|
42
|
+
return this.readJsonMemoized(appPkgPath);
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* Resolves a package to its filesystem location using Node.js module resolution.
|
|
46
|
+
* Returns the directory containing the package, not the package.json path.
|
|
47
|
+
*/
|
|
48
|
+
this.resolvePackageDir = (packageName, fromDir) => {
|
|
49
|
+
const cacheKey = `${packageName}::${fromDir}`;
|
|
50
|
+
// Check memoization cache
|
|
51
|
+
if (this.cache.requireResolve.has(cacheKey)) {
|
|
52
|
+
return this.cache.requireResolve.get(cacheKey);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
// require.resolve finds the main entry point, so we look for package.json instead
|
|
56
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
|
|
57
|
+
paths: [fromDir, this.rootDir],
|
|
58
|
+
});
|
|
59
|
+
const result = path.dirname(packageJsonPath);
|
|
60
|
+
this.cache.requireResolve.set(cacheKey, result);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
builder_util_1.log.warn({ packageName, fromDir, error: error.message }, "could not resolve package");
|
|
65
|
+
this.cache.requireResolve.set(cacheKey, null);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
20
69
|
}
|
|
21
|
-
async getNodeModules() {
|
|
22
|
-
const tree = await this.getDependenciesTree();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.
|
|
70
|
+
async getNodeModules({ cancellationToken, packageName }) {
|
|
71
|
+
const tree = await this.getDependenciesTree(this.installOptions.manager);
|
|
72
|
+
if (cancellationToken.cancelled) {
|
|
73
|
+
throw new Error("getNodeModules cancelled after fetching dependency tree");
|
|
74
|
+
}
|
|
75
|
+
await this.collectAllDependencies(tree, packageName);
|
|
76
|
+
const realTree = await this.getTreeFromWorkspaces(tree);
|
|
77
|
+
await this.extractProductionDependencyGraph(realTree, packageName);
|
|
78
|
+
if (cancellationToken.cancelled) {
|
|
79
|
+
throw new Error("getNodeModules cancelled after building production graph");
|
|
80
|
+
}
|
|
81
|
+
const hoisterResult = (0, hoist_1.hoist)(this.transformToHoisterTree(this.productionGraph, packageName), { check: true });
|
|
82
|
+
await this._getNodeModules(hoisterResult.dependencies, this.nodeModules);
|
|
83
|
+
builder_util_1.log.debug({ packageName, depCount: this.nodeModules.length }, "node modules collection complete");
|
|
28
84
|
return this.nodeModules;
|
|
29
85
|
}
|
|
30
|
-
async getDependenciesTree() {
|
|
31
|
-
const command = (0, packageManager_1.getPackageManagerCommand)(
|
|
86
|
+
async getDependenciesTree(pm) {
|
|
87
|
+
const command = (0, packageManager_1.getPackageManagerCommand)(pm);
|
|
32
88
|
const args = this.getArgs();
|
|
33
89
|
const tempOutputFile = await this.tempDirManager.getTempFile({
|
|
34
90
|
prefix: path.basename(command, path.extname(command)),
|
|
@@ -36,81 +92,147 @@ class NodeModulesCollector {
|
|
|
36
92
|
});
|
|
37
93
|
return (0, builder_util_1.retry)(async () => {
|
|
38
94
|
await this.streamCollectorCommandToJsonFile(command, args, this.rootDir, tempOutputFile);
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return this.parseDependenciesTree(dependencies);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
builder_util_1.log.debug({ message: error.message || error.stack, shellOutput: dependencies }, "error parsing dependencies tree");
|
|
45
|
-
throw new Error(`Failed to parse dependencies tree: ${error.message || error.stack}. Use DEBUG=electron-builder env var to see the dependency query output.`);
|
|
46
|
-
}
|
|
95
|
+
const shellOutput = await fs.readFile(tempOutputFile, { encoding: "utf8" });
|
|
96
|
+
return await this.parseDependenciesTree(shellOutput);
|
|
47
97
|
}, {
|
|
48
|
-
retries:
|
|
98
|
+
retries: 1,
|
|
49
99
|
interval: 2000,
|
|
50
100
|
backoff: 2000,
|
|
51
101
|
shouldRetry: async (error) => {
|
|
52
102
|
var _a;
|
|
53
|
-
|
|
54
|
-
|
|
103
|
+
const logFields = { error: error.message, tempOutputFile, cwd: this.rootDir };
|
|
104
|
+
if (!(await this.existsMemoized(tempOutputFile))) {
|
|
105
|
+
builder_util_1.log.debug(logFields, "dependency tree output file missing, retrying");
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
const fileContent = await fs.readFile(tempOutputFile, { encoding: "utf8" });
|
|
109
|
+
const fields = { ...logFields, fileContent };
|
|
110
|
+
if (fileContent.trim().length === 0) {
|
|
111
|
+
builder_util_1.log.debug(fields, "dependency tree output file empty, retrying");
|
|
55
112
|
return true;
|
|
56
113
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// If the output file is empty or contains invalid JSON, we retry
|
|
60
|
-
// This can happen if the command fails or if the output is not as expected
|
|
61
|
-
builder_util_1.log.error({ error: error.message || error.stack, tempOutputFile }, "dependency tree output file is empty, retrying");
|
|
114
|
+
if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes("Unexpected end of JSON input")) {
|
|
115
|
+
builder_util_1.log.debug(fields, "JSON parse error in dependency tree, retrying");
|
|
62
116
|
return true;
|
|
63
117
|
}
|
|
118
|
+
builder_util_1.log.error(fields, "error parsing dependencies tree");
|
|
64
119
|
return false;
|
|
65
120
|
},
|
|
66
121
|
});
|
|
67
122
|
}
|
|
68
|
-
|
|
123
|
+
async existsMemoized(filePath) {
|
|
124
|
+
if (!this.cache.exists.has(filePath)) {
|
|
125
|
+
this.cache.exists.set(filePath, await (0, builder_util_1.exists)(filePath));
|
|
126
|
+
}
|
|
127
|
+
return this.cache.exists.get(filePath);
|
|
128
|
+
}
|
|
129
|
+
async readJsonMemoized(filePath) {
|
|
130
|
+
if (!this.cache.packageJson.has(filePath)) {
|
|
131
|
+
this.cache.packageJson.set(filePath, await (0, fs_extra_1.readJson)(filePath));
|
|
132
|
+
}
|
|
133
|
+
return this.cache.packageJson.get(filePath);
|
|
134
|
+
}
|
|
135
|
+
async lstatMemoized(filePath) {
|
|
136
|
+
if (!this.cache.lstat.has(filePath)) {
|
|
137
|
+
this.cache.lstat.set(filePath, await fs.lstat(filePath));
|
|
138
|
+
}
|
|
139
|
+
return this.cache.lstat.get(filePath);
|
|
140
|
+
}
|
|
141
|
+
async realpathMemoized(filePath) {
|
|
142
|
+
if (!this.cache.realPath.has(filePath)) {
|
|
143
|
+
this.cache.realPath.set(filePath, await fs.realpath(filePath));
|
|
144
|
+
}
|
|
145
|
+
return this.cache.realPath.get(filePath);
|
|
146
|
+
}
|
|
147
|
+
async resolvePath(filePath) {
|
|
148
|
+
// Check if we've already resolved this path
|
|
149
|
+
if (this.cache.realPath.has(filePath)) {
|
|
150
|
+
return this.cache.realPath.get(filePath);
|
|
151
|
+
}
|
|
69
152
|
try {
|
|
70
|
-
const stats =
|
|
153
|
+
const stats = await this.lstatMemoized(filePath);
|
|
71
154
|
if (stats.isSymbolicLink()) {
|
|
72
|
-
|
|
155
|
+
const resolved = await this.realpathMemoized(filePath);
|
|
156
|
+
this.cache.realPath.set(filePath, resolved);
|
|
157
|
+
return resolved;
|
|
73
158
|
}
|
|
74
159
|
else {
|
|
160
|
+
this.cache.realPath.set(filePath, filePath);
|
|
75
161
|
return filePath;
|
|
76
162
|
}
|
|
77
163
|
}
|
|
78
164
|
catch (error) {
|
|
79
|
-
builder_util_1.log.debug({ message: error.message || error.stack }, "error resolving path");
|
|
165
|
+
builder_util_1.log.debug({ filePath, message: error.message || error.stack }, "error resolving path");
|
|
166
|
+
this.cache.realPath.set(filePath, filePath);
|
|
80
167
|
return filePath;
|
|
81
168
|
}
|
|
82
169
|
}
|
|
83
|
-
|
|
170
|
+
requireMemoized(pkgPath) {
|
|
171
|
+
if (!this.cache.packageJson.has(pkgPath)) {
|
|
172
|
+
this.cache.packageJson.set(pkgPath, require(pkgPath));
|
|
173
|
+
}
|
|
174
|
+
return this.cache.packageJson.get(pkgPath);
|
|
175
|
+
}
|
|
176
|
+
existsSyncMemoized(filePath) {
|
|
177
|
+
if (!this.cache.exists.has(filePath)) {
|
|
178
|
+
this.cache.exists.set(filePath, fs.existsSync(filePath));
|
|
179
|
+
}
|
|
180
|
+
return this.cache.exists.get(filePath);
|
|
181
|
+
}
|
|
182
|
+
cacheKey(pkg) {
|
|
183
|
+
const rel = path.relative(this.rootDir, pkg.path);
|
|
184
|
+
return `${pkg.name}::${pkg.version}::${rel !== null && rel !== void 0 ? rel : "."}`;
|
|
185
|
+
}
|
|
186
|
+
packageVersionString(pkg) {
|
|
187
|
+
return `${pkg.name}@${pkg.version}`;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Parse a dependency identifier like "@scope/pkg@1.2.3" or "pkg@1.2.3"
|
|
191
|
+
*/
|
|
192
|
+
parseNameVersion(identifier) {
|
|
193
|
+
const lastAt = identifier.lastIndexOf("@");
|
|
194
|
+
if (lastAt <= 0) {
|
|
195
|
+
// fallback for scoped packages or malformed strings
|
|
196
|
+
return { name: identifier, version: "unknown" };
|
|
197
|
+
}
|
|
198
|
+
const name = identifier.slice(0, lastAt);
|
|
199
|
+
const version = identifier.slice(lastAt + 1);
|
|
200
|
+
return { name, version };
|
|
201
|
+
}
|
|
202
|
+
async getTreeFromWorkspaces(tree) {
|
|
84
203
|
if (tree.workspaces && tree.dependencies) {
|
|
85
|
-
const packageJson =
|
|
204
|
+
const packageJson = await this.appPkgJson.value;
|
|
86
205
|
const dependencyName = packageJson.name;
|
|
87
206
|
for (const [key, value] of Object.entries(tree.dependencies)) {
|
|
88
207
|
if (key === dependencyName) {
|
|
208
|
+
builder_util_1.log.debug({ key, path: value.path }, "returning workspace tree for root dependency");
|
|
89
209
|
return value;
|
|
90
210
|
}
|
|
91
211
|
}
|
|
92
212
|
}
|
|
93
213
|
return tree;
|
|
94
214
|
}
|
|
95
|
-
|
|
215
|
+
transformToHoisterTree(obj, key, nodes = new Map()) {
|
|
96
216
|
let node = nodes.get(key);
|
|
97
|
-
const name =
|
|
217
|
+
const { name, version } = this.parseNameVersion(key);
|
|
98
218
|
if (!node) {
|
|
99
219
|
node = {
|
|
100
220
|
name,
|
|
101
221
|
identName: name,
|
|
102
|
-
reference:
|
|
222
|
+
reference: version,
|
|
103
223
|
dependencies: new Set(),
|
|
104
|
-
peerNames: new Set(
|
|
224
|
+
peerNames: new Set(),
|
|
105
225
|
};
|
|
106
226
|
nodes.set(key, node);
|
|
107
|
-
|
|
108
|
-
|
|
227
|
+
const deps = (obj[key] || {}).dependencies || [];
|
|
228
|
+
for (const dep of deps) {
|
|
229
|
+
const child = this.transformToHoisterTree(obj, dep, nodes);
|
|
230
|
+
node.dependencies.add(child);
|
|
109
231
|
}
|
|
110
232
|
}
|
|
111
233
|
return node;
|
|
112
234
|
}
|
|
113
|
-
_getNodeModules(dependencies, result) {
|
|
235
|
+
async _getNodeModules(dependencies, result) {
|
|
114
236
|
var _a;
|
|
115
237
|
if (dependencies.size === 0) {
|
|
116
238
|
return;
|
|
@@ -124,26 +246,30 @@ class NodeModulesCollector {
|
|
|
124
246
|
}
|
|
125
247
|
// fix npm list issue
|
|
126
248
|
// https://github.com/npm/cli/issues/8535
|
|
127
|
-
if (!
|
|
249
|
+
if (!(await (0, builder_util_1.exists)(p))) {
|
|
128
250
|
builder_util_1.log.debug({ name: d.name, reference, p }, "dependency path does not exist");
|
|
129
251
|
continue;
|
|
130
252
|
}
|
|
131
253
|
const node = {
|
|
132
254
|
name: d.name,
|
|
133
255
|
version: reference,
|
|
134
|
-
dir: this.resolvePath(p),
|
|
256
|
+
dir: await this.resolvePath(p),
|
|
135
257
|
};
|
|
136
258
|
result.push(node);
|
|
137
259
|
if (d.dependencies.size > 0) {
|
|
138
260
|
node.dependencies = [];
|
|
139
|
-
this._getNodeModules(d.dependencies, node.dependencies);
|
|
261
|
+
await this._getNodeModules(d.dependencies, node.dependencies);
|
|
140
262
|
}
|
|
141
263
|
}
|
|
142
264
|
result.sort((a, b) => a.name.localeCompare(b.name));
|
|
143
265
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
266
|
+
async asyncExec(command, args, cwd = this.rootDir) {
|
|
267
|
+
var _a, _b, _c, _d;
|
|
268
|
+
const payload = await execAsync([`"${command}"`, ...args].join(" "), { cwd, maxBuffer: 100 * 1024 * 1024, encoding: "utf8" }).catch(err => {
|
|
269
|
+
builder_util_1.log.error({ err }, "failed to execute command");
|
|
270
|
+
return { stdout: undefined, stderr: err.message };
|
|
271
|
+
});
|
|
272
|
+
return { stdout: (_b = (_a = payload.stdout) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : undefined, stderr: (_d = (_c = payload.stderr) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : undefined };
|
|
147
273
|
}
|
|
148
274
|
async streamCollectorCommandToJsonFile(command, args, cwd, tempOutputFile) {
|
|
149
275
|
const execName = path.basename(command, path.extname(command));
|
|
@@ -162,7 +288,7 @@ class NodeModulesCollector {
|
|
|
162
288
|
args = ["/c", tempBatFile, ...args];
|
|
163
289
|
}
|
|
164
290
|
await new Promise((resolve, reject) => {
|
|
165
|
-
const outStream = (0,
|
|
291
|
+
const outStream = (0, fs_extra_1.createWriteStream)(tempOutputFile);
|
|
166
292
|
const child = (0, child_process_1.spawn)(command, args, {
|
|
167
293
|
cwd,
|
|
168
294
|
shell: false, // required to prevent console logs polution from shell profile loading when `true`
|
|
@@ -173,21 +299,20 @@ class NodeModulesCollector {
|
|
|
173
299
|
stderr += chunk.toString();
|
|
174
300
|
});
|
|
175
301
|
child.on("error", err => {
|
|
176
|
-
reject(new Error(`
|
|
302
|
+
reject(new Error(`Node module collector spawn failed: ${err.message}`));
|
|
177
303
|
});
|
|
178
304
|
child.on("close", code => {
|
|
179
305
|
outStream.close();
|
|
180
306
|
// https://github.com/npm/npm/issues/17624
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
resolve();
|
|
185
|
-
return;
|
|
307
|
+
const shouldIgnore = code === 1 && "npm" === execName.toLowerCase() && args.includes("list");
|
|
308
|
+
if (shouldIgnore) {
|
|
309
|
+
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
310
|
}
|
|
187
|
-
if (
|
|
188
|
-
|
|
311
|
+
if (stderr.length > 0) {
|
|
312
|
+
builder_util_1.log.debug({ stderr }, "note: there was node module collector output on stderr");
|
|
189
313
|
}
|
|
190
|
-
|
|
314
|
+
const shouldResolve = code === 0 || shouldIgnore;
|
|
315
|
+
return shouldResolve ? resolve() : reject(new Error(`Node module collector process exited with code ${code}:\n${stderr}`));
|
|
191
316
|
});
|
|
192
317
|
});
|
|
193
318
|
}
|
|
@@ -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 { CancellationToken } from \"builder-util-runtime\"\nimport { exec, spawn } from \"child_process\"\nimport * as fs from \"fs-extra\"\nimport { createWriteStream, readJson } from \"fs-extra\"\nimport { Lazy } from \"lazy-val\"\nimport * as path from \"path\"\nimport { promisify } from \"util\"\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\"\n\nconst execAsync = promisify(exec)\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 // Unified cache for all file system and module operations\n protected cache: ModuleCache = createModuleCache()\n\n protected isHoisted = new Lazy<boolean>(async () => {\n const command = getPackageManagerCommand(this.installOptions.manager)\n\n const config = (await this.asyncExec(command, [\"config\", \"list\"])).stdout\n if (config == null) {\n log.debug({ manager: this.installOptions.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: this.installOptions.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)\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.streamCollectorCommandToJsonFile(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 resolvePackageDir = (packageName: string, fromDir: string): string | null => {\n const cacheKey = `${packageName}::${fromDir}`\n\n // Check memoization cache\n if (this.cache.requireResolve.has(cacheKey)) {\n return this.cache.requireResolve.get(cacheKey)!\n }\n\n try {\n // require.resolve finds the main entry point, so we look for package.json instead\n const packageJsonPath = require.resolve(`${packageName}/package.json`, {\n paths: [fromDir, this.rootDir],\n })\n const result = path.dirname(packageJsonPath)\n this.cache.requireResolve.set(cacheKey, result)\n return result\n } catch (error: any) {\n log.warn({ packageName, fromDir, error: error.message }, \"could not resolve package\")\n this.cache.requireResolve.set(cacheKey, null)\n return null\n }\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): Promise<ProdDepType> {\n if (tree.workspaces && tree.dependencies) {\n const packageJson = await this.appPkgJson.value\n const dependencyName = packageJson.name\n\n for (const [key, value] of Object.entries(tree.dependencies)) {\n if (key === dependencyName) {\n log.debug({ key, path: value.path }, \"returning workspace tree for root dependency\")\n return value\n }\n }\n }\n\n return 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 payload = await execAsync([`\"${command}\"`, ...args].join(\" \"), { cwd, maxBuffer: 100 * 1024 * 1024, encoding: \"utf8\" }).catch(err => {\n log.error({ err }, \"failed to execute command\")\n return { stdout: undefined, stderr: err.message }\n })\n return { stdout: payload.stdout?.trim() ?? undefined, stderr: payload.stderr?.trim() ?? undefined }\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(`Node module collector spawn failed: ${err.message}`))\n })\n\n child.on(\"close\", code => {\n outStream.close()\n // https://github.com/npm/npm/issues/17624\n const shouldIgnore = code === 1 && \"npm\" === execName.toLowerCase() && args.includes(\"list\")\n if (shouldIgnore) {\n log.debug(null, \"`npm list` returned non-zero exit code, but it MIGHT be expected (https://github.com/npm/npm/issues/17624). Check stderr for details.\")\n }\n if (stderr.length > 0) {\n log.debug({ stderr }, \"note: there was node module collector output on stderr\")\n }\n const shouldResolve = code === 0 || shouldIgnore\n return shouldResolve ? resolve() : reject(new Error(`Node module collector process exited with code ${code}:\\n${stderr}`))\n })\n })\n }\n}\n"]}
|
|
@@ -7,7 +7,14 @@ export declare class NpmNodeModulesCollector extends NodeModulesCollector<NpmDep
|
|
|
7
7
|
lockfile: string;
|
|
8
8
|
};
|
|
9
9
|
protected getArgs(): string[];
|
|
10
|
-
protected
|
|
11
|
-
protected
|
|
12
|
-
protected
|
|
10
|
+
protected getDependenciesTree(pm: PM): Promise<NpmDependency>;
|
|
11
|
+
protected collectAllDependencies(tree: NpmDependency): Promise<void>;
|
|
12
|
+
protected extractProductionDependencyGraph(tree: NpmDependency, dependencyId: string): Promise<void>;
|
|
13
|
+
protected isProdDependency(packageName: string, tree: NpmDependency): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Builds a dependency tree using only package.json dependencies and optionalDependencies.
|
|
16
|
+
* This skips devDependencies and uses Node.js module resolution (require.resolve).
|
|
17
|
+
*/
|
|
18
|
+
protected buildNodeModulesTreeManually(baseDir: string): Promise<NpmDependency>;
|
|
19
|
+
protected parseDependenciesTree(jsonBlob: string): Promise<NpmDependency>;
|
|
13
20
|
}
|