app-builder-lib 26.3.4 → 26.3.5
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/node-module-collector/moduleCache.d.ts +21 -18
- package/out/node-module-collector/moduleCache.js +53 -12
- package/out/node-module-collector/moduleCache.js.map +1 -1
- package/out/node-module-collector/nodeModulesCollector.d.ts +21 -22
- package/out/node-module-collector/nodeModulesCollector.js +178 -118
- package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/npmNodeModulesCollector.js +12 -13
- package/out/node-module-collector/npmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/pnpmNodeModulesCollector.js +10 -15
- package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/yarnNodeModulesCollector.js +42 -54
- package/out/node-module-collector/yarnNodeModulesCollector.js.map +1 -1
- package/out/targets/nsis/nsisUtil.js +10 -8
- package/out/targets/nsis/nsisUtil.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/package.json +8 -8
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
1
|
import { PackageJson } from "./types";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import * as fs from "fs-extra";
|
|
3
|
+
type PackageJsonCache = Record<string, Promise<PackageJson>>;
|
|
4
|
+
type RealPathCache = Record<string, Promise<string>>;
|
|
5
|
+
type ExistsCache = Record<string, Promise<boolean>>;
|
|
6
|
+
type LstatCache = Record<string, Promise<fs.Stats>>;
|
|
7
|
+
type RequireResolveCache = Record<string, Promise<string | null>>;
|
|
8
|
+
export declare class ModuleCache {
|
|
7
9
|
/** Cache for package.json contents (readJson/require) */
|
|
8
|
-
packageJson:
|
|
10
|
+
readonly packageJson: PackageJsonCache;
|
|
9
11
|
/** Cache for resolved real paths (realpath) */
|
|
10
|
-
realPath:
|
|
12
|
+
readonly realPath: RealPathCache;
|
|
11
13
|
/** Cache for file/directory existence checks */
|
|
12
|
-
exists:
|
|
14
|
+
readonly exists: ExistsCache;
|
|
13
15
|
/** Cache for lstat results */
|
|
14
|
-
lstat:
|
|
16
|
+
readonly lstat: LstatCache;
|
|
15
17
|
/** Cache for require.resolve results (key: "packageName::fromDir") */
|
|
16
|
-
requireResolve:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
readonly requireResolve: RequireResolveCache;
|
|
19
|
+
private readonly packageJsonMap;
|
|
20
|
+
private readonly realPathMap;
|
|
21
|
+
private readonly existsMap;
|
|
22
|
+
private readonly lstatMap;
|
|
23
|
+
private readonly requireResolveMap;
|
|
24
|
+
constructor();
|
|
25
|
+
private createAsyncProxy;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -1,16 +1,57 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
exports.ModuleCache = void 0;
|
|
4
|
+
const builder_util_1 = require("builder-util");
|
|
5
|
+
const fs = require("fs-extra");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
class ModuleCache {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.packageJsonMap = new Map();
|
|
10
|
+
this.realPathMap = new Map();
|
|
11
|
+
this.existsMap = new Map();
|
|
12
|
+
this.lstatMap = new Map();
|
|
13
|
+
this.requireResolveMap = new Map();
|
|
14
|
+
this.packageJson = this.createAsyncProxy(this.packageJsonMap, (path) => fs.readJson(path));
|
|
15
|
+
this.exists = this.createAsyncProxy(this.existsMap, (path) => (0, builder_util_1.exists)(path));
|
|
16
|
+
this.lstat = this.createAsyncProxy(this.lstatMap, (path) => fs.lstat(path));
|
|
17
|
+
this.requireResolve = this.createAsyncProxy(this.requireResolveMap, (path) => require.resolve(path));
|
|
18
|
+
this.realPath = this.createAsyncProxy(this.realPathMap, async (path) => {
|
|
19
|
+
const p = (0, path_1.resolve)(path);
|
|
20
|
+
try {
|
|
21
|
+
const stats = await this.lstat[p];
|
|
22
|
+
if (stats.isSymbolicLink()) {
|
|
23
|
+
return await fs.realpath(p);
|
|
24
|
+
}
|
|
25
|
+
return p;
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
builder_util_1.log.debug({ filePath: p, message: error.message || error.stack }, "error resolving path");
|
|
29
|
+
}
|
|
30
|
+
return p;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// this allows dot-notation access while still supporting async retrieval
|
|
34
|
+
// e.g., cache.packageJson[somePath] returns Promise<PackageJson>
|
|
35
|
+
createAsyncProxy(map, compute) {
|
|
36
|
+
return new Proxy({}, {
|
|
37
|
+
async get(_, key) {
|
|
38
|
+
if (map.has(key)) {
|
|
39
|
+
return Promise.resolve(map.get(key));
|
|
40
|
+
}
|
|
41
|
+
return await Promise.resolve(compute(key)).then(value => {
|
|
42
|
+
map.set(key, value);
|
|
43
|
+
return value;
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
set(_, key, value) {
|
|
47
|
+
map.set(key, value);
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
has(_, key) {
|
|
51
|
+
return map.has(key);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
15
55
|
}
|
|
56
|
+
exports.ModuleCache = ModuleCache;
|
|
16
57
|
//# sourceMappingURL=moduleCache.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moduleCache.js","sourceRoot":"","sources":["../../src/node-module-collector/moduleCache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"moduleCache.js","sourceRoot":"","sources":["../../src/node-module-collector/moduleCache.ts"],"names":[],"mappings":"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","sourcesContent":["import { exists, log } from \"builder-util\"\nimport { PackageJson } from \"./types\"\nimport * as fs from \"fs-extra\"\nimport { resolve } from \"path\"\n\n// Type aliases for clarity\ntype PackageJsonCache = Record<string, Promise<PackageJson>>\ntype RealPathCache = Record<string, Promise<string>>\ntype ExistsCache = Record<string, Promise<boolean>>\ntype LstatCache = Record<string, Promise<fs.Stats>>\ntype RequireResolveCache = Record<string, Promise<string | null>>\n\nexport class ModuleCache {\n /** Cache for package.json contents (readJson/require) */\n readonly packageJson: PackageJsonCache\n /** Cache for resolved real paths (realpath) */\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 require.resolve results (key: \"packageName::fromDir\") */\n readonly requireResolve: RequireResolveCache\n\n private readonly packageJsonMap: Map<string, PackageJson> = 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> = new Map()\n private readonly requireResolveMap: Map<string, string | null> = new Map()\n\n constructor() {\n this.packageJson = this.createAsyncProxy(this.packageJsonMap, (path: string) => fs.readJson(path))\n this.exists = this.createAsyncProxy(this.existsMap, (path: string) => exists(path))\n this.lstat = this.createAsyncProxy(this.lstatMap, (path: string) => fs.lstat(path))\n this.requireResolve = this.createAsyncProxy(this.requireResolveMap, (path: string) => require.resolve(path))\n this.realPath = this.createAsyncProxy(this.realPathMap, async (path: string) => {\n const p = resolve(path)\n try {\n const stats = await this.lstat[p]\n if (stats.isSymbolicLink()) {\n return await fs.realpath(p)\n }\n return p\n } catch (error: any) {\n log.debug({ filePath: p, message: error.message || error.stack }, \"error resolving path\")\n }\n return p\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"]}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { TmpDir } from "builder-util";
|
|
2
2
|
import { CancellationToken } from "builder-util-runtime";
|
|
3
|
-
import * as fs from "fs-extra";
|
|
4
3
|
import { Lazy } from "lazy-val";
|
|
4
|
+
import { ModuleCache } from "./moduleCache";
|
|
5
5
|
import { PM } from "./packageManager";
|
|
6
|
-
import type { Dependency, DependencyGraph, NodeModuleInfo
|
|
6
|
+
import type { Dependency, DependencyGraph, NodeModuleInfo } from "./types";
|
|
7
|
+
type Result = {
|
|
8
|
+
packageDir: string;
|
|
9
|
+
version: string;
|
|
10
|
+
} | null;
|
|
7
11
|
export declare abstract class NodeModulesCollector<ProdDepType extends Dependency<ProdDepType, OptionalDepType>, OptionalDepType> {
|
|
8
12
|
protected readonly rootDir: string;
|
|
9
13
|
private readonly tempDirManager;
|
|
10
14
|
private readonly nodeModules;
|
|
11
15
|
protected readonly allDependencies: Map<string, ProdDepType>;
|
|
12
16
|
protected readonly productionGraph: DependencyGraph;
|
|
13
|
-
|
|
14
|
-
protected
|
|
15
|
-
protected appPkgJson: Lazy<PackageJson>;
|
|
17
|
+
protected readonly cache: ModuleCache;
|
|
18
|
+
protected isHoisted: Lazy<boolean>;
|
|
16
19
|
constructor(rootDir: string, tempDirManager: TmpDir);
|
|
17
20
|
getNodeModules({ cancellationToken, packageName }: {
|
|
18
21
|
cancellationToken: CancellationToken;
|
|
@@ -27,23 +30,6 @@ export declare abstract class NodeModulesCollector<ProdDepType extends Dependenc
|
|
|
27
30
|
protected abstract extractProductionDependencyGraph(tree: Dependency<ProdDepType, OptionalDepType>, dependencyId: string): Promise<void>;
|
|
28
31
|
protected abstract collectAllDependencies(tree: Dependency<ProdDepType, OptionalDepType>, appPackageName: string): Promise<void>;
|
|
29
32
|
protected getDependenciesTree(pm: PM): Promise<ProdDepType>;
|
|
30
|
-
protected existsMemoized(filePath: string): Promise<boolean>;
|
|
31
|
-
protected readJsonMemoized(filePath: string): Promise<PackageJson>;
|
|
32
|
-
protected lstatMemoized(filePath: string): Promise<fs.Stats>;
|
|
33
|
-
protected realpathMemoized(filePath: string): Promise<string>;
|
|
34
|
-
protected requireMemoized(pkgPath: string): PackageJson;
|
|
35
|
-
protected existsSyncMemoized(filePath: string): boolean;
|
|
36
|
-
protected resolvePath(filePath: string): Promise<string>;
|
|
37
|
-
/**
|
|
38
|
-
* Resolve a package directory purely from the filesystem.
|
|
39
|
-
* Does NOT attempt to load the module or resolve an "exports" entrypoint.
|
|
40
|
-
* Good for Yarn 4 because a package may not be resolvable as a module,
|
|
41
|
-
* but still exists on disk.
|
|
42
|
-
*/
|
|
43
|
-
protected resolvePackage(packageName: string, fromDir: string): Promise<{
|
|
44
|
-
entry: string;
|
|
45
|
-
packageDir: string;
|
|
46
|
-
} | null>;
|
|
47
33
|
protected cacheKey(pkg: ProdDepType): string;
|
|
48
34
|
protected packageVersionString(pkg: ProdDepType): string;
|
|
49
35
|
/**
|
|
@@ -61,4 +47,17 @@ export declare abstract class NodeModulesCollector<ProdDepType extends Dependenc
|
|
|
61
47
|
stderr: string | undefined;
|
|
62
48
|
}>;
|
|
63
49
|
streamCollectorCommandToFile(command: string, args: string[], cwd: string, tempOutputFile: string): Promise<void>;
|
|
50
|
+
protected locatePackageVersion(parentDir: string, pkgName: string, requiredRange?: string): Promise<Result | null>;
|
|
51
|
+
protected readPackageVersion(pkgJsonPath: string): Promise<string | null>;
|
|
52
|
+
protected semverSatisfies(found: string, range?: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Upward search (hoisted)
|
|
55
|
+
*/
|
|
56
|
+
private upwardSearch;
|
|
57
|
+
/**
|
|
58
|
+
* Breadth-first downward search from parentDir/node_modules
|
|
59
|
+
* Looks for node_modules/\*\/node_modules/pkgName (and deeper)
|
|
60
|
+
*/
|
|
61
|
+
private downwardSearch;
|
|
64
62
|
}
|
|
63
|
+
export {};
|
|
@@ -7,6 +7,7 @@ const fs = require("fs-extra");
|
|
|
7
7
|
const fs_extra_1 = require("fs-extra");
|
|
8
8
|
const lazy_val_1 = require("lazy-val");
|
|
9
9
|
const path = require("path");
|
|
10
|
+
const semver = require("semver");
|
|
10
11
|
const hoist_1 = require("./hoist");
|
|
11
12
|
const moduleCache_1 = require("./moduleCache");
|
|
12
13
|
const packageManager_1 = require("./packageManager");
|
|
@@ -17,14 +18,12 @@ class NodeModulesCollector {
|
|
|
17
18
|
this.nodeModules = [];
|
|
18
19
|
this.allDependencies = new Map();
|
|
19
20
|
this.productionGraph = {};
|
|
20
|
-
|
|
21
|
-
this.cache = (0, moduleCache_1.createModuleCache)();
|
|
21
|
+
this.cache = new moduleCache_1.ModuleCache();
|
|
22
22
|
this.isHoisted = new lazy_val_1.Lazy(async () => {
|
|
23
|
-
var _a;
|
|
24
23
|
const { manager } = this.installOptions;
|
|
25
24
|
const command = (0, packageManager_1.getPackageManagerCommand)(manager);
|
|
26
|
-
const config = (
|
|
27
|
-
if (
|
|
25
|
+
const config = (await this.asyncExec(command, ["config", "list"])).stdout;
|
|
26
|
+
if (config == null) {
|
|
28
27
|
builder_util_1.log.debug({ manager }, "unable to determine if node_modules are hoisted: no config output. falling back to hoisted mode");
|
|
29
28
|
return false;
|
|
30
29
|
}
|
|
@@ -35,10 +34,6 @@ class NodeModulesCollector {
|
|
|
35
34
|
}
|
|
36
35
|
return false;
|
|
37
36
|
});
|
|
38
|
-
this.appPkgJson = new lazy_val_1.Lazy(async () => {
|
|
39
|
-
const appPkgPath = path.join(this.rootDir, "package.json");
|
|
40
|
-
return this.readJsonMemoized(appPkgPath);
|
|
41
|
-
});
|
|
42
37
|
}
|
|
43
38
|
async getNodeModules({ cancellationToken, packageName }) {
|
|
44
39
|
const tree = await this.getDependenciesTree(this.installOptions.manager);
|
|
@@ -76,7 +71,7 @@ class NodeModulesCollector {
|
|
|
76
71
|
shouldRetry: async (error) => {
|
|
77
72
|
var _a;
|
|
78
73
|
const logFields = { error: error.message, tempOutputFile, cwd: this.rootDir };
|
|
79
|
-
if (!(await this.
|
|
74
|
+
if (!(await this.cache.exists[tempOutputFile])) {
|
|
80
75
|
builder_util_1.log.debug(logFields, "dependency tree output file missing, retrying");
|
|
81
76
|
return true;
|
|
82
77
|
}
|
|
@@ -95,109 +90,6 @@ class NodeModulesCollector {
|
|
|
95
90
|
},
|
|
96
91
|
});
|
|
97
92
|
}
|
|
98
|
-
async existsMemoized(filePath) {
|
|
99
|
-
if (!this.cache.exists.has(filePath)) {
|
|
100
|
-
this.cache.exists.set(filePath, await (0, builder_util_1.exists)(filePath));
|
|
101
|
-
}
|
|
102
|
-
return this.cache.exists.get(filePath);
|
|
103
|
-
}
|
|
104
|
-
async readJsonMemoized(filePath) {
|
|
105
|
-
if (!this.cache.packageJson.has(filePath)) {
|
|
106
|
-
this.cache.packageJson.set(filePath, await (0, fs_extra_1.readJson)(filePath));
|
|
107
|
-
}
|
|
108
|
-
return this.cache.packageJson.get(filePath);
|
|
109
|
-
}
|
|
110
|
-
async lstatMemoized(filePath) {
|
|
111
|
-
if (!this.cache.lstat.has(filePath)) {
|
|
112
|
-
this.cache.lstat.set(filePath, await fs.lstat(filePath));
|
|
113
|
-
}
|
|
114
|
-
return this.cache.lstat.get(filePath);
|
|
115
|
-
}
|
|
116
|
-
async realpathMemoized(filePath) {
|
|
117
|
-
if (!this.cache.realPath.has(filePath)) {
|
|
118
|
-
this.cache.realPath.set(filePath, await fs.realpath(filePath));
|
|
119
|
-
}
|
|
120
|
-
return this.cache.realPath.get(filePath);
|
|
121
|
-
}
|
|
122
|
-
requireMemoized(pkgPath) {
|
|
123
|
-
if (!this.cache.packageJson.has(pkgPath)) {
|
|
124
|
-
this.cache.packageJson.set(pkgPath, require(pkgPath));
|
|
125
|
-
}
|
|
126
|
-
return this.cache.packageJson.get(pkgPath);
|
|
127
|
-
}
|
|
128
|
-
existsSyncMemoized(filePath) {
|
|
129
|
-
if (!this.cache.exists.has(filePath)) {
|
|
130
|
-
this.cache.exists.set(filePath, fs.existsSync(filePath));
|
|
131
|
-
}
|
|
132
|
-
return this.cache.exists.get(filePath);
|
|
133
|
-
}
|
|
134
|
-
async resolvePath(filePath) {
|
|
135
|
-
// Check if we've already resolved this path
|
|
136
|
-
if (this.cache.realPath.has(filePath)) {
|
|
137
|
-
return this.cache.realPath.get(filePath);
|
|
138
|
-
}
|
|
139
|
-
try {
|
|
140
|
-
const stats = await this.lstatMemoized(filePath);
|
|
141
|
-
if (stats.isSymbolicLink()) {
|
|
142
|
-
const resolved = await this.realpathMemoized(filePath);
|
|
143
|
-
this.cache.realPath.set(filePath, resolved);
|
|
144
|
-
return resolved;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
this.cache.realPath.set(filePath, filePath);
|
|
148
|
-
return filePath;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
builder_util_1.log.debug({ filePath, message: error.message || error.stack }, "error resolving path");
|
|
153
|
-
this.cache.realPath.set(filePath, filePath);
|
|
154
|
-
return filePath;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Resolve a package directory purely from the filesystem.
|
|
159
|
-
* Does NOT attempt to load the module or resolve an "exports" entrypoint.
|
|
160
|
-
* Good for Yarn 4 because a package may not be resolvable as a module,
|
|
161
|
-
* but still exists on disk.
|
|
162
|
-
*/
|
|
163
|
-
async resolvePackage(packageName, fromDir) {
|
|
164
|
-
const cacheKey = `${packageName}::${fromDir}`;
|
|
165
|
-
if (this.cache.requireResolve.has(cacheKey)) {
|
|
166
|
-
return this.cache.requireResolve.get(cacheKey);
|
|
167
|
-
}
|
|
168
|
-
// 1. NESTED under fromDir/node_modules/<name>
|
|
169
|
-
let candidate = path.join(fromDir, "node_modules", packageName);
|
|
170
|
-
let pkgJson = path.join(candidate, "package.json");
|
|
171
|
-
if (await this.existsMemoized(pkgJson)) {
|
|
172
|
-
this.cache.requireResolve.set(cacheKey, { entry: pkgJson, packageDir: candidate });
|
|
173
|
-
return { entry: pkgJson, packageDir: candidate };
|
|
174
|
-
}
|
|
175
|
-
// 2. HOISTED under rootDir/node_modules/<name>
|
|
176
|
-
candidate = path.join(this.rootDir, "node_modules", packageName);
|
|
177
|
-
pkgJson = path.join(candidate, "package.json");
|
|
178
|
-
if (await this.existsMemoized(pkgJson)) {
|
|
179
|
-
this.cache.requireResolve.set(cacheKey, { entry: pkgJson, packageDir: candidate });
|
|
180
|
-
return { entry: pkgJson, packageDir: candidate };
|
|
181
|
-
}
|
|
182
|
-
// 3. FALLBACK: try parent directories BFS (classic Node-style search)
|
|
183
|
-
let current = fromDir;
|
|
184
|
-
while (true) {
|
|
185
|
-
const nm = path.join(current, "node_modules", packageName);
|
|
186
|
-
const pkg = path.join(nm, "package.json");
|
|
187
|
-
if (await this.existsMemoized(pkg)) {
|
|
188
|
-
this.cache.requireResolve.set(cacheKey, { entry: pkg, packageDir: nm });
|
|
189
|
-
return { entry: pkg, packageDir: nm };
|
|
190
|
-
}
|
|
191
|
-
const parent = path.dirname(current);
|
|
192
|
-
if (parent === current) {
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
current = parent;
|
|
196
|
-
}
|
|
197
|
-
// 4. LAST RESORT: DO NOT throw — just return null
|
|
198
|
-
this.cache.requireResolve.set(cacheKey, null);
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
93
|
cacheKey(pkg) {
|
|
202
94
|
const rel = path.relative(this.rootDir, pkg.path);
|
|
203
95
|
return `${pkg.name}::${pkg.version}::${rel !== null && rel !== void 0 ? rel : "."}`;
|
|
@@ -225,7 +117,7 @@ class NodeModulesCollector {
|
|
|
225
117
|
}
|
|
226
118
|
if ((_a = tree.dependencies) === null || _a === void 0 ? void 0 : _a[packageName]) {
|
|
227
119
|
const { name, path, dependencies } = tree.dependencies[packageName];
|
|
228
|
-
builder_util_1.log.debug({ name, path, dependencies: JSON.stringify(dependencies) }, "pruning root app/self reference from workspace tree
|
|
120
|
+
builder_util_1.log.debug({ name, path, dependencies: JSON.stringify(dependencies) }, "pruning root app/self reference from workspace tree");
|
|
229
121
|
for (const [name, pkg] of Object.entries(dependencies !== null && dependencies !== void 0 ? dependencies : {})) {
|
|
230
122
|
tree.dependencies[name] = pkg;
|
|
231
123
|
this.allDependencies.set(this.packageVersionString(pkg), pkg);
|
|
@@ -263,19 +155,19 @@ class NodeModulesCollector {
|
|
|
263
155
|
const reference = [...d.references][0];
|
|
264
156
|
const p = (_a = this.allDependencies.get(`${d.name}@${reference}`)) === null || _a === void 0 ? void 0 : _a.path;
|
|
265
157
|
if (p === undefined) {
|
|
266
|
-
builder_util_1.log.
|
|
158
|
+
builder_util_1.log.warn({ name: d.name, reference }, "cannot find path for dependency");
|
|
267
159
|
continue;
|
|
268
160
|
}
|
|
269
161
|
// fix npm list issue
|
|
270
162
|
// https://github.com/npm/cli/issues/8535
|
|
271
|
-
if (!(await
|
|
163
|
+
if (!(await this.cache.exists[p])) {
|
|
272
164
|
builder_util_1.log.debug({ name: d.name, reference, p }, "dependency path does not exist");
|
|
273
165
|
continue;
|
|
274
166
|
}
|
|
275
167
|
const node = {
|
|
276
168
|
name: d.name,
|
|
277
169
|
version: reference,
|
|
278
|
-
dir: await this.
|
|
170
|
+
dir: await this.cache.realPath[p],
|
|
279
171
|
};
|
|
280
172
|
result.push(node);
|
|
281
173
|
if (d.dependencies.size > 0) {
|
|
@@ -314,7 +206,6 @@ class NodeModulesCollector {
|
|
|
314
206
|
command = "cmd.exe";
|
|
315
207
|
args = ["/c", tempBatFile, ...args];
|
|
316
208
|
}
|
|
317
|
-
builder_util_1.log.debug({ command, args, cwd, tempOutputFile }, "spawning node module collector process");
|
|
318
209
|
await new Promise((resolve, reject) => {
|
|
319
210
|
const outStream = (0, fs_extra_1.createWriteStream)(tempOutputFile);
|
|
320
211
|
const child = childProcess.spawn(command, args, {
|
|
@@ -344,6 +235,175 @@ class NodeModulesCollector {
|
|
|
344
235
|
});
|
|
345
236
|
});
|
|
346
237
|
}
|
|
238
|
+
async locatePackageVersion(parentDir, pkgName, requiredRange) {
|
|
239
|
+
// 1) check direct parent node_modules/pkgName first
|
|
240
|
+
const direct = path.join(path.resolve(parentDir), "node_modules", pkgName, "package.json");
|
|
241
|
+
if (await this.cache.exists[direct]) {
|
|
242
|
+
const ver = await this.readPackageVersion(direct);
|
|
243
|
+
if (ver && this.semverSatisfies(ver, requiredRange)) {
|
|
244
|
+
return { packageDir: path.dirname(direct), version: ver };
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// 2) upward hoisted search, then 3) downward non-hoisted search
|
|
248
|
+
return (await this.upwardSearch(parentDir, pkgName, requiredRange)) || (await this.downwardSearch(parentDir, pkgName, requiredRange)) || null;
|
|
249
|
+
}
|
|
250
|
+
async readPackageVersion(pkgJsonPath) {
|
|
251
|
+
return await this.cache.packageJson[pkgJsonPath].then(pkg => pkg.version).catch(() => null);
|
|
252
|
+
}
|
|
253
|
+
semverSatisfies(found, range) {
|
|
254
|
+
if (!range || range === "*" || range === "") {
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
if (range === found) {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
if (semver.validRange(range) == null) {
|
|
261
|
+
// ignore, we can't verify non-semver ranges
|
|
262
|
+
// e.g. git urls, file:, patch:, etc. Example:
|
|
263
|
+
// "@ai-sdk/google": "patch:@ai-sdk/google@npm%3A2.0.43#~/.yarn/patches/@ai-sdk-google-npm-2.0.43-689ed559b3.patch"
|
|
264
|
+
builder_util_1.log.debug({ found, range }, "unable to validate semver version range, assuming match");
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
return semver.satisfies(found, range);
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
// fallback: simple equality or basic prefix handling (^, ~)
|
|
272
|
+
if (range.startsWith("^") || range.startsWith("~")) {
|
|
273
|
+
const r = range.slice(1);
|
|
274
|
+
return r === found;
|
|
275
|
+
}
|
|
276
|
+
// if range is like "8.x" or "8.*" match major
|
|
277
|
+
const m = range.match(/^(\d+)[.(*|x)]*/);
|
|
278
|
+
const fm = found.match(/^(\d+)\./);
|
|
279
|
+
if (m && fm) {
|
|
280
|
+
return m[1] === fm[1];
|
|
281
|
+
}
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Upward search (hoisted)
|
|
287
|
+
*/
|
|
288
|
+
async upwardSearch(parentDir, pkgName, requiredRange) {
|
|
289
|
+
let current = path.resolve(parentDir);
|
|
290
|
+
const root = path.parse(current).root;
|
|
291
|
+
while (true) {
|
|
292
|
+
const candidate = path.join(current, "node_modules", pkgName, "package.json");
|
|
293
|
+
if (await this.cache.exists[candidate]) {
|
|
294
|
+
const ver = await this.readPackageVersion(candidate);
|
|
295
|
+
if (ver && this.semverSatisfies(ver, requiredRange)) {
|
|
296
|
+
return { packageDir: path.dirname(candidate), version: ver };
|
|
297
|
+
}
|
|
298
|
+
// otherwise keep searching upward (we may find a different hoisted version)
|
|
299
|
+
}
|
|
300
|
+
if (current === root) {
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
const parent = path.dirname(current);
|
|
304
|
+
if (parent === current) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
current = parent;
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Breadth-first downward search from parentDir/node_modules
|
|
313
|
+
* Looks for node_modules/\*\/node_modules/pkgName (and deeper)
|
|
314
|
+
*/
|
|
315
|
+
async downwardSearch(parentDir, pkgName, requiredRange, maxExplored = 2000, maxDepth = 6) {
|
|
316
|
+
const start = path.join(path.resolve(parentDir), "node_modules");
|
|
317
|
+
if (!(await this.cache.exists[start]) || !(await this.cache.lstat[start]).isDirectory()) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
const visited = new Set();
|
|
321
|
+
const queue = [{ dir: start, depth: 0 }];
|
|
322
|
+
let explored = 0;
|
|
323
|
+
while (queue.length > 0) {
|
|
324
|
+
const { dir, depth } = queue.shift();
|
|
325
|
+
if (explored++ > maxExplored) {
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
if (depth > maxDepth) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
let entries;
|
|
332
|
+
try {
|
|
333
|
+
entries = await fs.readdir(dir);
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
for (const entry of entries) {
|
|
339
|
+
if (entry.startsWith(".")) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const entryPath = path.join(dir, entry);
|
|
343
|
+
// handle scoped packages @scope/name
|
|
344
|
+
if (entry.startsWith("@")) {
|
|
345
|
+
// queue the scope directory itself to explore its children
|
|
346
|
+
if ((await this.cache.exists[entryPath]) && (await this.cache.lstat[entryPath]).isDirectory()) {
|
|
347
|
+
const scopeEntries = await fs.readdir(entryPath);
|
|
348
|
+
for (const sc of scopeEntries) {
|
|
349
|
+
const scPath = path.join(entryPath, sc);
|
|
350
|
+
// check scPath/node_modules/pkgName
|
|
351
|
+
const candidatePkgJson = path.join(scPath, "node_modules", pkgName, "package.json");
|
|
352
|
+
if (await this.cache.exists[candidatePkgJson]) {
|
|
353
|
+
const ver = await this.readPackageVersion(candidatePkgJson);
|
|
354
|
+
if (ver && this.semverSatisfies(ver, requiredRange)) {
|
|
355
|
+
return { packageDir: path.dirname(candidatePkgJson), version: ver };
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// enqueue scPath/node_modules to explore further
|
|
359
|
+
const scNodeModules = path.join(scPath, "node_modules");
|
|
360
|
+
if ((await this.cache.exists[scNodeModules]) && (await this.cache.lstat[scNodeModules]).isDirectory()) {
|
|
361
|
+
if (!visited.has(scNodeModules)) {
|
|
362
|
+
visited.add(scNodeModules);
|
|
363
|
+
queue.push({ dir: scNodeModules, depth: depth + 1 });
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
// check for direct candidate: entry/node_modules/pkgName
|
|
371
|
+
try {
|
|
372
|
+
const stat = await this.cache.lstat[entryPath];
|
|
373
|
+
if (!stat.isDirectory()) {
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const candidatePkgJson = path.join(entryPath, "node_modules", pkgName, "package.json");
|
|
381
|
+
if (await this.cache.exists[candidatePkgJson]) {
|
|
382
|
+
const ver = await this.readPackageVersion(candidatePkgJson);
|
|
383
|
+
if (ver && this.semverSatisfies(ver, requiredRange)) {
|
|
384
|
+
return { packageDir: path.dirname(candidatePkgJson), version: ver };
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// also check entry/node_modules directly for pkgName (some layouts)
|
|
388
|
+
const candidateDirect = path.join(entryPath, pkgName, "package.json");
|
|
389
|
+
if (await this.cache.exists[candidateDirect]) {
|
|
390
|
+
const ver = await this.readPackageVersion(candidateDirect);
|
|
391
|
+
if (ver && this.semverSatisfies(ver, requiredRange)) {
|
|
392
|
+
return { packageDir: path.dirname(candidateDirect), version: ver };
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// enqueue entry/node_modules for deeper traversal
|
|
396
|
+
const nextNodeModules = path.join(entryPath, "node_modules");
|
|
397
|
+
if ((await this.cache.exists[nextNodeModules]) && (await this.cache.lstat[nextNodeModules]).isDirectory()) {
|
|
398
|
+
if (!visited.has(nextNodeModules)) {
|
|
399
|
+
visited.add(nextNodeModules);
|
|
400
|
+
queue.push({ dir: nextNodeModules, depth: depth + 1 });
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
347
407
|
}
|
|
348
408
|
exports.NodeModulesCollector = NodeModulesCollector;
|
|
349
409
|
//# sourceMappingURL=nodeModulesCollector.js.map
|