app-builder-lib 26.4.0 → 26.5.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 +105 -73
- package/out/asar/asarUtil.js.map +1 -1
- package/out/macPackager.js +5 -0
- package/out/macPackager.js.map +1 -1
- package/out/node-module-collector/bunNodeModulesCollector.d.ts +4 -5
- package/out/node-module-collector/bunNodeModulesCollector.js +5 -9
- package/out/node-module-collector/bunNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/hoist.js +7 -4
- package/out/node-module-collector/hoist.js.map +1 -1
- package/out/node-module-collector/index.d.ts +5 -4
- package/out/node-module-collector/index.js +6 -3
- package/out/node-module-collector/index.js.map +1 -1
- package/out/node-module-collector/moduleManager.d.ts +52 -0
- package/out/node-module-collector/moduleManager.js +227 -0
- package/out/node-module-collector/moduleManager.js.map +1 -0
- package/out/node-module-collector/nodeModulesCollector.d.ts +97 -24
- package/out/node-module-collector/nodeModulesCollector.js +154 -183
- package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/npmNodeModulesCollector.d.ts +3 -10
- package/out/node-module-collector/npmNodeModulesCollector.js +14 -88
- package/out/node-module-collector/npmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/packageManager.d.ts +2 -1
- package/out/node-module-collector/packageManager.js +2 -0
- package/out/node-module-collector/packageManager.js.map +1 -1
- package/out/node-module-collector/pnpmNodeModulesCollector.d.ts +1 -1
- package/out/node-module-collector/pnpmNodeModulesCollector.js +14 -21
- package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/traversalNodeModulesCollector.d.ts +18 -0
- package/out/node-module-collector/traversalNodeModulesCollector.js +119 -0
- package/out/node-module-collector/traversalNodeModulesCollector.js.map +1 -0
- package/out/node-module-collector/types.d.ts +5 -10
- package/out/node-module-collector/types.js.map +1 -1
- package/out/node-module-collector/yarnBerryNodeModulesCollector.js +3 -3
- package/out/node-module-collector/yarnBerryNodeModulesCollector.js.map +1 -1
- package/out/node-module-collector/yarnNodeModulesCollector.d.ts +1 -2
- package/out/node-module-collector/yarnNodeModulesCollector.js +4 -30
- package/out/node-module-collector/yarnNodeModulesCollector.js.map +1 -1
- package/out/options/macOptions.d.ts +5 -0
- package/out/options/macOptions.js.map +1 -1
- package/out/publish/PublishManager.js +3 -2
- package/out/publish/PublishManager.js.map +1 -1
- package/out/targets/archive.js.map +1 -1
- package/out/util/appFileCopier.js +16 -12
- package/out/util/appFileCopier.js.map +1 -1
- package/out/util/packageDependencies.js +2 -1
- package/out/util/packageDependencies.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 +9 -10
- package/scheme.json +7 -0
- package/out/node-module-collector/moduleCache.d.ts +0 -27
- package/out/node-module-collector/moduleCache.js +0 -65
- package/out/node-module-collector/moduleCache.js.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { PackageJson } from "./types";
|
|
2
|
+
import * as fs from "fs-extra";
|
|
3
|
+
export type Package = {
|
|
4
|
+
packageDir: string;
|
|
5
|
+
packageJson: PackageJson;
|
|
6
|
+
};
|
|
7
|
+
type JsonCache = Record<string, Promise<PackageJson | null>>;
|
|
8
|
+
type RealPathCache = Record<string, Promise<string>>;
|
|
9
|
+
type ExistsCache = Record<string, Promise<boolean>>;
|
|
10
|
+
type LstatCache = Record<string, Promise<fs.Stats | null>>;
|
|
11
|
+
type PackageCache = Record<string, Promise<Package | null>>;
|
|
12
|
+
export declare class ModuleManager {
|
|
13
|
+
/** Cache for package.json contents (readJson) */
|
|
14
|
+
readonly json: JsonCache;
|
|
15
|
+
/** Cache for resolved real paths (if symlink, realpath; otherwise resolve) */
|
|
16
|
+
readonly realPath: RealPathCache;
|
|
17
|
+
/** Cache for file/directory existence checks */
|
|
18
|
+
readonly exists: ExistsCache;
|
|
19
|
+
/** Cache for lstat results */
|
|
20
|
+
readonly lstat: LstatCache;
|
|
21
|
+
/** Cache for package lookups (key: "packageName||fromDir||semverRange"). Use helper function `versionedCacheKey` */
|
|
22
|
+
readonly packageData: PackageCache;
|
|
23
|
+
private readonly jsonMap;
|
|
24
|
+
private readonly realPathMap;
|
|
25
|
+
private readonly existsMap;
|
|
26
|
+
private readonly lstatMap;
|
|
27
|
+
private readonly packageDataMap;
|
|
28
|
+
constructor();
|
|
29
|
+
private createAsyncProxy;
|
|
30
|
+
versionedCacheKey(pkg: {
|
|
31
|
+
name: string;
|
|
32
|
+
path: string;
|
|
33
|
+
semver?: string;
|
|
34
|
+
}): string;
|
|
35
|
+
protected locatePackageVersionFromCacheKey(key: string): Promise<Package | null>;
|
|
36
|
+
locatePackageVersion({ parentDir, pkgName, requiredRange }: {
|
|
37
|
+
parentDir: string;
|
|
38
|
+
pkgName: string;
|
|
39
|
+
requiredRange?: string;
|
|
40
|
+
}): Promise<Package | null>;
|
|
41
|
+
private semverSatisfies;
|
|
42
|
+
/**
|
|
43
|
+
* Upward search (hoisted)
|
|
44
|
+
*/
|
|
45
|
+
private upwardSearch;
|
|
46
|
+
/**
|
|
47
|
+
* Breadth-first downward search from parentDir/node_modules
|
|
48
|
+
* Looks for node_modules/\*\/node_modules/pkgName (and deeper)
|
|
49
|
+
*/
|
|
50
|
+
private downwardSearch;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModuleManager = void 0;
|
|
4
|
+
const builder_util_1 = require("builder-util");
|
|
5
|
+
const fs = require("fs-extra");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const semver = require("semver");
|
|
8
|
+
class ModuleManager {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.jsonMap = new Map();
|
|
11
|
+
this.realPathMap = new Map();
|
|
12
|
+
this.existsMap = new Map();
|
|
13
|
+
this.lstatMap = new Map();
|
|
14
|
+
this.packageDataMap = new Map();
|
|
15
|
+
this.exists = this.createAsyncProxy(this.existsMap, (p) => (0, builder_util_1.exists)(p));
|
|
16
|
+
this.json = this.createAsyncProxy(this.jsonMap, (p) => fs.readJson(p).catch(() => null));
|
|
17
|
+
this.lstat = this.createAsyncProxy(this.lstatMap, (p) => fs.lstat(p).catch(() => null));
|
|
18
|
+
this.packageData = this.createAsyncProxy(this.packageDataMap, (p) => this.locatePackageVersionFromCacheKey(p).catch(() => null));
|
|
19
|
+
this.realPath = this.createAsyncProxy(this.realPathMap, async (p) => {
|
|
20
|
+
const filePath = path.resolve(p);
|
|
21
|
+
const stat = await this.lstat[filePath];
|
|
22
|
+
return (stat === null || stat === void 0 ? void 0 : stat.isSymbolicLink()) ? fs.realpath(filePath) : filePath;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// this allows dot-notation access while still supporting async retrieval
|
|
26
|
+
// e.g., cache.packageJson[somePath] returns Promise<PackageJson>
|
|
27
|
+
createAsyncProxy(map, compute) {
|
|
28
|
+
return new Proxy({}, {
|
|
29
|
+
async get(_, key) {
|
|
30
|
+
if (map.has(key)) {
|
|
31
|
+
return Promise.resolve(map.get(key));
|
|
32
|
+
}
|
|
33
|
+
return await Promise.resolve(compute(key)).then(value => {
|
|
34
|
+
map.set(key, value);
|
|
35
|
+
return value;
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
set(_, key, value) {
|
|
39
|
+
map.set(key, value);
|
|
40
|
+
return true;
|
|
41
|
+
},
|
|
42
|
+
has(_, key) {
|
|
43
|
+
return map.has(key);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
versionedCacheKey(pkg) {
|
|
48
|
+
return [pkg.name, pkg.path, pkg.semver || ""].join("||");
|
|
49
|
+
}
|
|
50
|
+
async locatePackageVersionFromCacheKey(key) {
|
|
51
|
+
const [name, fromDir, semverRange] = key.split("||");
|
|
52
|
+
const result = await this.locatePackageVersion({ parentDir: fromDir, pkgName: name, requiredRange: semverRange });
|
|
53
|
+
if (result == null) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return { ...result, packageDir: await this.realPath[result.packageDir] };
|
|
57
|
+
}
|
|
58
|
+
async locatePackageVersion({ parentDir, pkgName, requiredRange }) {
|
|
59
|
+
// 1) check direct parent node_modules/pkgName first
|
|
60
|
+
const direct = path.join(path.resolve(parentDir), "node_modules", pkgName, "package.json");
|
|
61
|
+
if (await this.exists[direct]) {
|
|
62
|
+
const json = await this.json[direct];
|
|
63
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
64
|
+
return { packageDir: path.dirname(direct), packageJson: json };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// 2) upward hoisted search, then 3) downward non-hoisted search
|
|
68
|
+
return (await this.upwardSearch(parentDir, pkgName, requiredRange)) || (await this.downwardSearch(parentDir, pkgName, requiredRange)) || null;
|
|
69
|
+
}
|
|
70
|
+
semverSatisfies(found, range) {
|
|
71
|
+
if ((0, builder_util_1.isEmptyOrSpaces)(range) || range === "*") {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
if (range === found) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (semver.validRange(range) == null) {
|
|
78
|
+
// ignore, we can't verify non-semver ranges
|
|
79
|
+
// e.g. git urls, file:, patch:, etc. Example:
|
|
80
|
+
// "@ai-sdk/google": "patch:@ai-sdk/google@npm%3A2.0.43#~/.yarn/patches/@ai-sdk-google-npm-2.0.43-689ed559b3.patch"
|
|
81
|
+
builder_util_1.log.debug({ found, range }, "unable to validate semver version range, assuming match");
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
return semver.satisfies(found, range);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// fallback: simple equality or basic prefix handling (^, ~)
|
|
89
|
+
if (range.startsWith("^") || range.startsWith("~")) {
|
|
90
|
+
const r = range.slice(1);
|
|
91
|
+
return r === found;
|
|
92
|
+
}
|
|
93
|
+
// if range is like "8.x" or "8.*" match major
|
|
94
|
+
const m = range.match(/^(\d+)[.(*|x)]*/);
|
|
95
|
+
const fm = found.match(/^(\d+)\./);
|
|
96
|
+
if (m && fm) {
|
|
97
|
+
return m[1] === fm[1];
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Upward search (hoisted)
|
|
104
|
+
*/
|
|
105
|
+
async upwardSearch(parentDir, pkgName, requiredRange) {
|
|
106
|
+
let current = path.resolve(parentDir);
|
|
107
|
+
const root = path.parse(current).root;
|
|
108
|
+
while (true) {
|
|
109
|
+
const candidate = path.join(current, "node_modules", pkgName, "package.json");
|
|
110
|
+
if (await this.exists[candidate]) {
|
|
111
|
+
const json = await this.json[candidate];
|
|
112
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
113
|
+
return { packageDir: path.dirname(candidate), packageJson: json };
|
|
114
|
+
}
|
|
115
|
+
// otherwise keep searching upward (we may find a different hoisted version)
|
|
116
|
+
}
|
|
117
|
+
if (current === root) {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
const parent = path.dirname(current);
|
|
121
|
+
if (parent === current) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
current = parent;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Breadth-first downward search from parentDir/node_modules
|
|
130
|
+
* Looks for node_modules/\*\/node_modules/pkgName (and deeper)
|
|
131
|
+
*/
|
|
132
|
+
async downwardSearch(parentDir, pkgName, requiredRange, maxExplored = 2000, maxDepth = 6) {
|
|
133
|
+
var _a, _b, _c, _d;
|
|
134
|
+
const start = path.join(path.resolve(parentDir), "node_modules");
|
|
135
|
+
if (!(await this.exists[start]) || !((_a = (await this.lstat[start])) === null || _a === void 0 ? void 0 : _a.isDirectory())) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const visited = new Set();
|
|
139
|
+
const queue = [{ dir: start, depth: 0 }];
|
|
140
|
+
let explored = 0;
|
|
141
|
+
while (queue.length > 0) {
|
|
142
|
+
const { dir, depth } = queue.shift();
|
|
143
|
+
if (explored++ > maxExplored) {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
if (depth > maxDepth) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
let entries;
|
|
150
|
+
try {
|
|
151
|
+
entries = await fs.readdir(dir);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
for (const entry of entries) {
|
|
157
|
+
if (entry.startsWith(".")) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const entryPath = path.join(dir, entry);
|
|
161
|
+
// handle scoped packages @scope/name
|
|
162
|
+
if (entry.startsWith("@")) {
|
|
163
|
+
// queue the scope directory itself to explore its children
|
|
164
|
+
if ((await this.exists[entryPath]) && ((_b = (await this.lstat[entryPath])) === null || _b === void 0 ? void 0 : _b.isDirectory())) {
|
|
165
|
+
const scopeEntries = await fs.readdir(entryPath);
|
|
166
|
+
for (const sc of scopeEntries) {
|
|
167
|
+
const scPath = path.join(entryPath, sc);
|
|
168
|
+
// check scPath/node_modules/pkgName
|
|
169
|
+
const candidatePkgJson = path.join(scPath, "node_modules", pkgName, "package.json");
|
|
170
|
+
if (await this.exists[candidatePkgJson]) {
|
|
171
|
+
const json = await this.json[candidatePkgJson];
|
|
172
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
173
|
+
return { packageDir: path.dirname(candidatePkgJson), packageJson: json };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// enqueue scPath/node_modules to explore further
|
|
177
|
+
const scNodeModules = path.join(scPath, "node_modules");
|
|
178
|
+
if ((await this.exists[scNodeModules]) && ((_c = (await this.lstat[scNodeModules])) === null || _c === void 0 ? void 0 : _c.isDirectory())) {
|
|
179
|
+
if (!visited.has(scNodeModules)) {
|
|
180
|
+
visited.add(scNodeModules);
|
|
181
|
+
queue.push({ dir: scNodeModules, depth: depth + 1 });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
// check for direct candidate: entry/node_modules/pkgName
|
|
189
|
+
try {
|
|
190
|
+
const stat = await this.lstat[entryPath];
|
|
191
|
+
if (!(stat === null || stat === void 0 ? void 0 : stat.isDirectory())) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const candidatePkgJson = path.join(entryPath, "node_modules", pkgName, "package.json");
|
|
199
|
+
if (await this.exists[candidatePkgJson]) {
|
|
200
|
+
const json = await this.json[candidatePkgJson];
|
|
201
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
202
|
+
return { packageDir: path.dirname(candidatePkgJson), packageJson: json };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// also check entry/node_modules directly for pkgName (some layouts)
|
|
206
|
+
const candidateDirect = path.join(entryPath, pkgName, "package.json");
|
|
207
|
+
if (await this.exists[candidateDirect]) {
|
|
208
|
+
const json = await this.json[candidateDirect];
|
|
209
|
+
if (json && this.semverSatisfies(json.version, requiredRange)) {
|
|
210
|
+
return { packageDir: path.dirname(candidateDirect), packageJson: json };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// enqueue entry/node_modules for deeper traversal
|
|
214
|
+
const nextNodeModules = path.join(entryPath, "node_modules");
|
|
215
|
+
if ((await this.exists[nextNodeModules]) && ((_d = (await this.lstat[nextNodeModules])) === null || _d === void 0 ? void 0 : _d.isDirectory())) {
|
|
216
|
+
if (!visited.has(nextNodeModules)) {
|
|
217
|
+
visited.add(nextNodeModules);
|
|
218
|
+
queue.push({ dir: nextNodeModules, depth: depth + 1 });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.ModuleManager = ModuleManager;
|
|
227
|
+
//# sourceMappingURL=moduleManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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 } 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 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>>\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\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\n constructor() {\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 // 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({ parentDir, pkgName, requiredRange }: { parentDir: string; pkgName: string; requiredRange?: string }): 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 return (await this.upwardSearch(parentDir, pkgName, requiredRange)) || (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,24 +1,33 @@
|
|
|
1
1
|
import { TmpDir } from "builder-util";
|
|
2
|
-
import { CancellationToken } from "builder-util-runtime";
|
|
3
2
|
import { Lazy } from "lazy-val";
|
|
4
|
-
import {
|
|
3
|
+
import { ModuleManager } from "./moduleManager";
|
|
5
4
|
import { PM } from "./packageManager";
|
|
6
|
-
import type { Dependency, DependencyGraph, NodeModuleInfo } from "./types";
|
|
7
|
-
type Result = {
|
|
8
|
-
packageDir: string;
|
|
9
|
-
version: string;
|
|
10
|
-
} | null;
|
|
5
|
+
import type { Dependency, DependencyGraph, NodeModuleInfo, PackageJson } from "./types";
|
|
11
6
|
export declare abstract class NodeModulesCollector<ProdDepType extends Dependency<ProdDepType, OptionalDepType>, OptionalDepType> {
|
|
12
7
|
protected readonly rootDir: string;
|
|
13
8
|
private readonly tempDirManager;
|
|
14
9
|
private readonly nodeModules;
|
|
15
10
|
protected readonly allDependencies: Map<string, ProdDepType>;
|
|
16
11
|
protected readonly productionGraph: DependencyGraph;
|
|
17
|
-
protected readonly cache:
|
|
12
|
+
protected readonly cache: ModuleManager;
|
|
18
13
|
protected isHoisted: Lazy<boolean>;
|
|
19
14
|
constructor(rootDir: string, tempDirManager: TmpDir);
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves and collects all Node.js modules for a given package.
|
|
17
|
+
*
|
|
18
|
+
* This method orchestrates the entire module collection process by:
|
|
19
|
+
* 1. Fetching the dependency tree from the package manager
|
|
20
|
+
* 2. Collecting all dependencies recursively
|
|
21
|
+
* 3. Extracting workspace references if applicable
|
|
22
|
+
* 4. Building a production dependency graph
|
|
23
|
+
* 5. Hoisting the dependencies to their final locations
|
|
24
|
+
* 6. Resolving and returning module information
|
|
25
|
+
*
|
|
26
|
+
* @param options - Configuration object
|
|
27
|
+
* @param options.packageName - The name of the package to collect modules for
|
|
28
|
+
* @returns Promise resolving to an array of NodeModuleInfo objects representing all collected modules
|
|
29
|
+
*/
|
|
30
|
+
getNodeModules({ packageName }: {
|
|
22
31
|
packageName: string;
|
|
23
32
|
}): Promise<NodeModuleInfo[]>;
|
|
24
33
|
abstract readonly installOptions: {
|
|
@@ -26,20 +35,81 @@ export declare abstract class NodeModulesCollector<ProdDepType extends Dependenc
|
|
|
26
35
|
lockfile: string;
|
|
27
36
|
};
|
|
28
37
|
protected abstract getArgs(): string[];
|
|
29
|
-
protected abstract parseDependenciesTree(jsonBlob: string): Promise<ProdDepType>;
|
|
30
38
|
protected abstract extractProductionDependencyGraph(tree: Dependency<ProdDepType, OptionalDepType>, dependencyId: string): Promise<void>;
|
|
31
39
|
protected abstract collectAllDependencies(tree: Dependency<ProdDepType, OptionalDepType>, appPackageName: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Retrieves the dependency tree from the package manager.
|
|
42
|
+
*
|
|
43
|
+
* Executes the appropriate package manager command to fetch the dependency tree and writes
|
|
44
|
+
* the output to a temporary file. Includes retry logic to handle transient failures such as
|
|
45
|
+
* incomplete JSON output or missing files. Will retry up to 1 time with exponential backoff.
|
|
46
|
+
*
|
|
47
|
+
* @param pm - The package manager to use (npm, yarn, pnpm, etc.)
|
|
48
|
+
* @returns Promise resolving to the parsed dependency tree
|
|
49
|
+
* @throws {Error} If the dependency tree cannot be retrieved after retries
|
|
50
|
+
*/
|
|
32
51
|
protected getDependenciesTree(pm: PM): Promise<ProdDepType>;
|
|
52
|
+
/**
|
|
53
|
+
* Parses the dependencies tree from shell command output.
|
|
54
|
+
*
|
|
55
|
+
**/
|
|
56
|
+
protected parseDependenciesTree(shellOutput: string): ProdDepType | Promise<ProdDepType>;
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* This method attempts to extract and parse JSON data from shell output that may contain
|
|
60
|
+
* additional non-JSON content (like warnings or informational messages). It first tries
|
|
61
|
+
* to parse the entire output as JSON, and if that fails, it intelligently searches for
|
|
62
|
+
* JSON content within the output by:
|
|
63
|
+
* 1. Finding the first line that starts with `{` or `[`
|
|
64
|
+
* 2. Tracking bracket depth to find the matching closing bracket
|
|
65
|
+
* 3. Extracting only the valid JSON portion
|
|
66
|
+
*
|
|
67
|
+
* @param shellOutput - The raw output from a shell command, potentially containing JSON
|
|
68
|
+
* @returns The parsed dependencies tree object
|
|
69
|
+
* @throws {Error} If no JSON content is found in the output
|
|
70
|
+
* @throws {Error} If no matching closing bracket is found in the output
|
|
71
|
+
* @throws {SyntaxError} If the extracted content is not valid JSON
|
|
72
|
+
*/
|
|
73
|
+
protected extractJsonFromPollutedOutput<T>(shellOutput: string): T;
|
|
33
74
|
protected cacheKey(pkg: Pick<ProdDepType, "name" | "version" | "path">): string;
|
|
34
75
|
protected packageVersionString(pkg: Pick<ProdDepType, "name" | "version">): string;
|
|
76
|
+
/**
|
|
77
|
+
* Determines if a given dependency is a production dependency of a package.
|
|
78
|
+
*
|
|
79
|
+
* Checks both the dependencies and optionalDependencies of a package to see if
|
|
80
|
+
* the specified dependency name is listed.
|
|
81
|
+
*
|
|
82
|
+
* @param depName - The name of the dependency to check
|
|
83
|
+
* @param pkg - The package to search for the dependency in
|
|
84
|
+
* @returns True if the dependency is found in either dependencies or optionalDependencies, false otherwise
|
|
85
|
+
*/
|
|
35
86
|
protected isProdDependency(depName: string, pkg: ProdDepType): boolean;
|
|
87
|
+
protected locatePackageWithVersion(depTree: Pick<ProdDepType, "name" | "version" | "path">): Promise<{
|
|
88
|
+
packageDir: string;
|
|
89
|
+
packageJson: PackageJson;
|
|
90
|
+
} | null>;
|
|
36
91
|
/**
|
|
37
|
-
*
|
|
92
|
+
* Parses a dependency identifier string into name and version components.
|
|
93
|
+
*
|
|
94
|
+
* Handles both scoped packages (e.g., "@scope/pkg@1.2.3") and regular packages (e.g., "pkg@1.2.3").
|
|
95
|
+
* If the identifier is malformed or cannot be parsed, defaults to treating the entire string as
|
|
96
|
+
* the package name with an "unknown" version.
|
|
38
97
|
*/
|
|
39
98
|
protected parseNameVersion(identifier: string): {
|
|
40
99
|
name: string;
|
|
41
100
|
version: string;
|
|
42
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Retrieves the dependency tree and handles workspace package self-references.
|
|
104
|
+
*
|
|
105
|
+
* If the project is a workspace project, this method removes the root package's self-reference
|
|
106
|
+
* from the dependency tree to avoid circular dependencies. It promotes the root package's
|
|
107
|
+
* direct dependencies to the top level of the tree.
|
|
108
|
+
*
|
|
109
|
+
* @param tree - The original dependency tree
|
|
110
|
+
* @param packageName - The name of the package to check for and remove from the tree
|
|
111
|
+
* @returns Promise resolving to the pruned dependency tree
|
|
112
|
+
*/
|
|
43
113
|
protected getTreeFromWorkspaces(tree: ProdDepType, packageName: string): Promise<ProdDepType>;
|
|
44
114
|
private transformToHoisterTree;
|
|
45
115
|
private _getNodeModules;
|
|
@@ -47,18 +117,21 @@ export declare abstract class NodeModulesCollector<ProdDepType extends Dependenc
|
|
|
47
117
|
stdout: string | undefined;
|
|
48
118
|
stderr: string | undefined;
|
|
49
119
|
}>;
|
|
50
|
-
streamCollectorCommandToFile(command: string, args: string[], cwd: string, tempOutputFile: string): Promise<void>;
|
|
51
|
-
protected locatePackageVersion(parentDir: string, pkgName: string, requiredRange?: string): Promise<Result | null>;
|
|
52
|
-
protected readPackageVersion(pkgJsonPath: string): Promise<string | null>;
|
|
53
|
-
protected semverSatisfies(found: string, range?: string): boolean;
|
|
54
120
|
/**
|
|
55
|
-
*
|
|
121
|
+
* Executes a command and streams its output to a file.
|
|
122
|
+
*
|
|
123
|
+
* Spawns a child process to execute the specified command with arguments, capturing stdout
|
|
124
|
+
* to a file. Handles Windows-specific quirks by wrapping .cmd files in a temporary .bat file
|
|
125
|
+
* when necessary. Enables corepack strict mode by default but allows process.env overrides.
|
|
126
|
+
*
|
|
127
|
+
* Special handling for `npm list` exit code 1, which is expected in certain scenarios.
|
|
128
|
+
*
|
|
129
|
+
* @param command - The command to execute
|
|
130
|
+
* @param args - Array of command-line arguments
|
|
131
|
+
* @param cwd - The working directory to execute the command in
|
|
132
|
+
* @param tempOutputFile - The path to the temporary file where stdout will be written
|
|
133
|
+
* @returns Promise that resolves when the command completes successfully or rejects if it fails
|
|
134
|
+
* @throws {Error} If the child process spawn fails or exits with a non-zero code
|
|
56
135
|
*/
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Breadth-first downward search from parentDir/node_modules
|
|
60
|
-
* Looks for node_modules/\*\/node_modules/pkgName (and deeper)
|
|
61
|
-
*/
|
|
62
|
-
private downwardSearch;
|
|
136
|
+
streamCollectorCommandToFile(command: string, args: string[], cwd: string, tempOutputFile: string): Promise<void>;
|
|
63
137
|
}
|
|
64
|
-
export {};
|