@yao-pkg/pkg 6.12.0 → 6.13.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/lib-es5/common.js +94 -1
- package/lib-es5/detector.js +4 -2
- package/lib-es5/esm-transformer.js +202 -0
- package/lib-es5/follow.js +154 -55
- package/lib-es5/index.js +10 -8
- package/lib-es5/mach-o.js +1 -1
- package/lib-es5/options.js +2 -1
- package/lib-es5/packer.js +1 -1
- package/lib-es5/producer.js +3 -4
- package/lib-es5/resolver.js +142 -0
- package/lib-es5/sea.js +13 -6
- package/lib-es5/walker.js +127 -21
- package/package.json +6 -4
package/lib-es5/common.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.toNormalizedRealPath = exports.removeUplevels = exports.stripSnapshot = exports.insideSnapshot = exports.snapshotify = exports.substituteDenominator = exports.retrieveDenominator = exports.isDotNODE = exports.isDotJSON = exports.isDotJS = exports.isPackageJson = exports.normalizePath = exports.isRootPath = exports.ALIAS_AS_RESOLVABLE = exports.ALIAS_AS_RELATIVE = exports.STORE_STAT = exports.STORE_LINKS = exports.STORE_CONTENT = exports.STORE_BLOB = void 0;
|
|
6
|
+
exports.isESMFile = exports.isESMPackage = exports.toNormalizedRealPath = exports.removeUplevels = exports.stripSnapshot = exports.insideSnapshot = exports.snapshotify = exports.substituteDenominator = exports.retrieveDenominator = exports.unlikelyJavascript = exports.isDotNODE = exports.isDotJSON = exports.isDotJS = exports.isPackageJson = exports.normalizePath = exports.isRootPath = exports.ALIAS_AS_RESOLVABLE = exports.ALIAS_AS_RELATIVE = exports.STORE_STAT = exports.STORE_LINKS = exports.STORE_CONTENT = exports.STORE_BLOB = void 0;
|
|
7
7
|
const assert_1 = __importDefault(require("assert"));
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
@@ -93,6 +93,19 @@ function isDotNODE(file) {
|
|
|
93
93
|
return path_1.default.extname(file) === '.node';
|
|
94
94
|
}
|
|
95
95
|
exports.isDotNODE = isDotNODE;
|
|
96
|
+
function unlikelyJavascript(file) {
|
|
97
|
+
const ext = path_1.default.extname(file);
|
|
98
|
+
// Check single extensions
|
|
99
|
+
if (['.css', '.html', '.json', '.vue'].includes(ext)) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
// Check for .d.ts files (compound extension)
|
|
103
|
+
if (file.endsWith('.d.ts')) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
exports.unlikelyJavascript = unlikelyJavascript;
|
|
96
109
|
function replaceSlashes(file, slash) {
|
|
97
110
|
if (/^.:\\/.test(file)) {
|
|
98
111
|
if (slash === '/') {
|
|
@@ -232,4 +245,84 @@ function toNormalizedRealPath(requestPath) {
|
|
|
232
245
|
return file;
|
|
233
246
|
}
|
|
234
247
|
exports.toNormalizedRealPath = toNormalizedRealPath;
|
|
248
|
+
/**
|
|
249
|
+
* Find the nearest package.json file by walking up the directory tree
|
|
250
|
+
* @param filePath - Starting file path
|
|
251
|
+
* @returns Path to package.json or null if not found
|
|
252
|
+
*/
|
|
253
|
+
function findNearestPackageJson(filePath) {
|
|
254
|
+
let dir = path_1.default.dirname(filePath);
|
|
255
|
+
const { root } = path_1.default.parse(dir);
|
|
256
|
+
while (dir !== root) {
|
|
257
|
+
const packageJsonPath = path_1.default.join(dir, 'package.json');
|
|
258
|
+
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
259
|
+
return packageJsonPath;
|
|
260
|
+
}
|
|
261
|
+
dir = path_1.default.dirname(dir);
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
// Caches for ESM detection performance optimization
|
|
266
|
+
const packageJsonCache = new Map();
|
|
267
|
+
const esmPackageCache = new Map();
|
|
268
|
+
/**
|
|
269
|
+
* Check if a package.json indicates an ESM package
|
|
270
|
+
* @param packageJsonPath - Path to package.json
|
|
271
|
+
* @returns true if "type": "module" is set
|
|
272
|
+
*/
|
|
273
|
+
function isESMPackage(packageJsonPath) {
|
|
274
|
+
// Check cache first
|
|
275
|
+
if (esmPackageCache.has(packageJsonPath)) {
|
|
276
|
+
return esmPackageCache.get(packageJsonPath);
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const content = fs_1.default.readFileSync(packageJsonPath, 'utf8');
|
|
280
|
+
const pkg = JSON.parse(content);
|
|
281
|
+
const result = pkg.type === 'module';
|
|
282
|
+
esmPackageCache.set(packageJsonPath, result);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
esmPackageCache.set(packageJsonPath, false);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
exports.isESMPackage = isESMPackage;
|
|
291
|
+
/**
|
|
292
|
+
* Determine if a file should be treated as ESM
|
|
293
|
+
* Based on file extension and nearest package.json "type" field
|
|
294
|
+
*
|
|
295
|
+
* @param filePath - The file path to check
|
|
296
|
+
* @returns true if file should be treated as ESM
|
|
297
|
+
*/
|
|
298
|
+
function isESMFile(filePath) {
|
|
299
|
+
// .mjs files are always ESM
|
|
300
|
+
if (filePath.endsWith('.mjs')) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
// .cjs files are never ESM
|
|
304
|
+
if (filePath.endsWith('.cjs')) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
// For .js files, check nearest package.json for "type": "module"
|
|
308
|
+
if (filePath.endsWith('.js')) {
|
|
309
|
+
const dir = path_1.default.dirname(filePath);
|
|
310
|
+
// Check cache first
|
|
311
|
+
if (packageJsonCache.has(dir)) {
|
|
312
|
+
const cached = packageJsonCache.get(dir);
|
|
313
|
+
if (cached) {
|
|
314
|
+
return isESMPackage(cached);
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
// Compute and cache
|
|
319
|
+
const packageJsonPath = findNearestPackageJson(filePath);
|
|
320
|
+
packageJsonCache.set(dir, packageJsonPath);
|
|
321
|
+
if (packageJsonPath) {
|
|
322
|
+
return isESMPackage(packageJsonPath);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
exports.isESMFile = isESMFile;
|
|
235
328
|
//# sourceMappingURL=common.js.map
|
package/lib-es5/detector.js
CHANGED
|
@@ -86,6 +86,7 @@ function reconstructSpecifiers(specs) {
|
|
|
86
86
|
return defaults.join(', ');
|
|
87
87
|
}
|
|
88
88
|
function reconstruct(node) {
|
|
89
|
+
// @ts-expect-error Type mismatch due to @babel/types version in @types/babel__generator
|
|
89
90
|
let v = (0, generator_1.default)(node, { comments: false }).code.replace(/\n/g, '');
|
|
90
91
|
let v2;
|
|
91
92
|
while (true) {
|
|
@@ -403,13 +404,14 @@ function parse(body) {
|
|
|
403
404
|
});
|
|
404
405
|
}
|
|
405
406
|
exports.parse = parse;
|
|
406
|
-
function detect(body, visitor) {
|
|
407
|
+
function detect(body, visitor, file) {
|
|
407
408
|
let json;
|
|
408
409
|
try {
|
|
409
410
|
json = parse(body);
|
|
410
411
|
}
|
|
411
412
|
catch (error) {
|
|
412
|
-
|
|
413
|
+
const fileInfo = file ? ` in ${file}` : '';
|
|
414
|
+
log_1.log.warn(`Babel parse has failed: ${error.message}${fileInfo}`);
|
|
413
415
|
}
|
|
414
416
|
if (!json) {
|
|
415
417
|
return;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.transformESMtoCJS = void 0;
|
|
30
|
+
const babel = __importStar(require("@babel/parser"));
|
|
31
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
32
|
+
const esbuild = __importStar(require("esbuild"));
|
|
33
|
+
const log_1 = require("./log");
|
|
34
|
+
const common_1 = require("./common");
|
|
35
|
+
/**
|
|
36
|
+
* Detect ESM features that cannot be safely transformed to CommonJS
|
|
37
|
+
* These include:
|
|
38
|
+
* - Top-level await (no CJS equivalent)
|
|
39
|
+
* - import.meta (no CJS equivalent)
|
|
40
|
+
*
|
|
41
|
+
* @param code - The ESM source code to check
|
|
42
|
+
* @param filename - The filename for error reporting
|
|
43
|
+
* @returns Array of unsupported features found, or null if parse fails
|
|
44
|
+
*/
|
|
45
|
+
function detectUnsupportedESMFeatures(code, filename) {
|
|
46
|
+
try {
|
|
47
|
+
const ast = babel.parse(code, {
|
|
48
|
+
sourceType: 'module',
|
|
49
|
+
plugins: [],
|
|
50
|
+
});
|
|
51
|
+
if (!ast) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const unsupportedFeatures = [];
|
|
55
|
+
// @ts-expect-error Type mismatch due to @babel/types version in @types/babel__traverse
|
|
56
|
+
(0, traverse_1.default)(ast, {
|
|
57
|
+
// Detect import.meta usage
|
|
58
|
+
MetaProperty(path) {
|
|
59
|
+
if (path.node.meta.name === 'import' &&
|
|
60
|
+
path.node.property.name === 'meta') {
|
|
61
|
+
unsupportedFeatures.push({
|
|
62
|
+
feature: 'import.meta',
|
|
63
|
+
line: path.node.loc?.start.line ?? null,
|
|
64
|
+
column: path.node.loc?.start.column ?? null,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
// Detect top-level await
|
|
69
|
+
AwaitExpression(path) {
|
|
70
|
+
// Check if await is at top level (not inside a function)
|
|
71
|
+
let parent = path.parentPath;
|
|
72
|
+
let isTopLevel = true;
|
|
73
|
+
while (parent) {
|
|
74
|
+
if (parent.isFunctionDeclaration() ||
|
|
75
|
+
parent.isFunctionExpression() ||
|
|
76
|
+
parent.isArrowFunctionExpression() ||
|
|
77
|
+
parent.isObjectMethod() ||
|
|
78
|
+
parent.isClassMethod()) {
|
|
79
|
+
isTopLevel = false;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
parent = parent.parentPath;
|
|
83
|
+
}
|
|
84
|
+
if (isTopLevel) {
|
|
85
|
+
unsupportedFeatures.push({
|
|
86
|
+
feature: 'top-level await',
|
|
87
|
+
line: path.node.loc?.start.line ?? null,
|
|
88
|
+
column: path.node.loc?.start.column ?? null,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
// Detect for-await-of at top level
|
|
93
|
+
ForOfStatement(path) {
|
|
94
|
+
if (path.node.await) {
|
|
95
|
+
let parent = path.parentPath;
|
|
96
|
+
let isTopLevel = true;
|
|
97
|
+
while (parent) {
|
|
98
|
+
if (parent.isFunctionDeclaration() ||
|
|
99
|
+
parent.isFunctionExpression() ||
|
|
100
|
+
parent.isArrowFunctionExpression() ||
|
|
101
|
+
parent.isObjectMethod() ||
|
|
102
|
+
parent.isClassMethod()) {
|
|
103
|
+
isTopLevel = false;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
parent = parent.parentPath;
|
|
107
|
+
}
|
|
108
|
+
if (isTopLevel) {
|
|
109
|
+
unsupportedFeatures.push({
|
|
110
|
+
feature: 'top-level for-await-of',
|
|
111
|
+
line: path.node.loc?.start.line ?? null,
|
|
112
|
+
column: path.node.loc?.start.column ?? null,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
return unsupportedFeatures;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
// If we can't parse, return null to let the transform attempt proceed
|
|
122
|
+
log_1.log.debug(`Could not parse ${filename} to detect unsupported ESM features: ${error instanceof Error ? error.message : String(error)}`);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Transform ESM code to CommonJS using esbuild
|
|
128
|
+
* This allows ESM modules to be compiled to bytecode via vm.Script
|
|
129
|
+
* Uses Babel parser for detecting unsupported ESM features, then esbuild for fast transformation
|
|
130
|
+
*
|
|
131
|
+
* @param code - The ESM source code to transform
|
|
132
|
+
* @param filename - The filename for error reporting
|
|
133
|
+
* @returns Object with transformed code and success flag
|
|
134
|
+
*/
|
|
135
|
+
function transformESMtoCJS(code, filename) {
|
|
136
|
+
// Skip files that are unlikely to be JavaScript (e.g., .d.ts, .json, .css)
|
|
137
|
+
// to avoid Babel parse errors
|
|
138
|
+
if ((0, common_1.unlikelyJavascript)(filename)) {
|
|
139
|
+
return {
|
|
140
|
+
code,
|
|
141
|
+
isTransformed: false,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// First, check for unsupported ESM features that can't be safely transformed
|
|
145
|
+
const unsupportedFeatures = detectUnsupportedESMFeatures(code, filename);
|
|
146
|
+
if (unsupportedFeatures && unsupportedFeatures.length > 0) {
|
|
147
|
+
const featureList = unsupportedFeatures
|
|
148
|
+
.map((f) => {
|
|
149
|
+
const location = f.line !== null ? ` at line ${f.line}` : '';
|
|
150
|
+
return ` - ${f.feature}${location}`;
|
|
151
|
+
})
|
|
152
|
+
.join('\n');
|
|
153
|
+
const errorMessage = [
|
|
154
|
+
`Cannot transform ESM module ${filename} to CommonJS:`,
|
|
155
|
+
`The following ESM features have no CommonJS equivalent:`,
|
|
156
|
+
featureList,
|
|
157
|
+
'',
|
|
158
|
+
'These features are not supported when compiling to bytecode.',
|
|
159
|
+
'Consider one of the following:',
|
|
160
|
+
' 1. Refactor to avoid these features',
|
|
161
|
+
' 2. Use --no-bytecode flag to keep the module as source code',
|
|
162
|
+
' 3. Mark the package as public to distribute with sources',
|
|
163
|
+
].join('\n');
|
|
164
|
+
log_1.log.warn(errorMessage);
|
|
165
|
+
// Return untransformed code rather than throwing
|
|
166
|
+
// This allows the file to be included as content instead of bytecode
|
|
167
|
+
return {
|
|
168
|
+
code,
|
|
169
|
+
isTransformed: false,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const result = esbuild.transformSync(code, {
|
|
174
|
+
loader: 'js',
|
|
175
|
+
format: 'cjs',
|
|
176
|
+
target: 'node18',
|
|
177
|
+
sourcemap: false,
|
|
178
|
+
minify: false,
|
|
179
|
+
keepNames: true,
|
|
180
|
+
});
|
|
181
|
+
if (!result || !result.code) {
|
|
182
|
+
log_1.log.warn(`esbuild transform returned no code for ${filename}`);
|
|
183
|
+
return {
|
|
184
|
+
code,
|
|
185
|
+
isTransformed: false,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
code: result.code,
|
|
190
|
+
isTransformed: true,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
log_1.log.warn(`Failed to transform ESM to CJS for ${filename}: ${error instanceof Error ? error.message : String(error)}`);
|
|
195
|
+
return {
|
|
196
|
+
code,
|
|
197
|
+
isTransformed: false,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.transformESMtoCJS = transformESMtoCJS;
|
|
202
|
+
//# sourceMappingURL=esm-transformer.js.map
|
package/lib-es5/follow.js
CHANGED
|
@@ -8,6 +8,7 @@ const resolve_1 = require("resolve");
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const common_1 = require("./common");
|
|
11
|
+
const resolver_1 = require("./resolver");
|
|
11
12
|
const PROOF = 'a-proof-that-main-is-captured.js';
|
|
12
13
|
function parentDirectoriesContain(parent, directory) {
|
|
13
14
|
let currentParent = parent;
|
|
@@ -22,69 +23,167 @@ function parentDirectoriesContain(parent, directory) {
|
|
|
22
23
|
currentParent = newParent;
|
|
23
24
|
}
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if a specifier looks like a valid npm package name
|
|
28
|
+
* npm package names must be lowercase and can only contain:
|
|
29
|
+
* - lowercase letters, digits, hyphens, underscores, dots
|
|
30
|
+
* - can be scoped (@scope/package)
|
|
31
|
+
* This helps filter out generated aliases like "connectNonLiteral"
|
|
32
|
+
*/
|
|
33
|
+
function isValidPackageName(specifier) {
|
|
34
|
+
// Scoped packages: @scope/package
|
|
35
|
+
if (specifier.startsWith('@')) {
|
|
36
|
+
const parts = specifier.split('/');
|
|
37
|
+
if (parts.length < 2)
|
|
38
|
+
return false;
|
|
39
|
+
// Scope must start with @ and both parts must be valid
|
|
40
|
+
return /^@[a-z0-9_.-]+$/.test(parts[0]) && /^[a-z0-9_.-]+$/.test(parts[1]);
|
|
41
|
+
}
|
|
42
|
+
// Regular package: must be lowercase with allowed characters
|
|
43
|
+
// Package name is the part before the first '/' (if any)
|
|
44
|
+
const packageName = specifier.split('/')[0];
|
|
45
|
+
return /^[a-z0-9_.-]+$/.test(packageName);
|
|
46
|
+
}
|
|
25
47
|
function follow(x, opts) {
|
|
26
48
|
// TODO async version
|
|
27
|
-
return new Promise((resolve) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
// Try ESM-aware resolution first for non-relative specifiers
|
|
51
|
+
// Skip if the specifier doesn't look like a valid npm package name
|
|
52
|
+
// (e.g., generated aliases like "connectNonLiteral")
|
|
53
|
+
if (!x.startsWith('.') &&
|
|
54
|
+
!x.startsWith('/') &&
|
|
55
|
+
!path_1.default.isAbsolute(x) &&
|
|
56
|
+
isValidPackageName(x)) {
|
|
57
|
+
try {
|
|
58
|
+
let extensions;
|
|
59
|
+
if (Array.isArray(opts.extensions)) {
|
|
60
|
+
extensions = opts.extensions;
|
|
35
61
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
stat = fs_1.default.statSync(file);
|
|
62
|
+
else if (opts.extensions) {
|
|
63
|
+
extensions = [opts.extensions];
|
|
39
64
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (ex && (ex.code === 'ENOENT' || ex.code === 'ENOTDIR'))
|
|
43
|
-
return false;
|
|
44
|
-
throw ex;
|
|
45
|
-
}
|
|
46
|
-
return stat.isFile() || stat.isFIFO();
|
|
47
|
-
},
|
|
48
|
-
isDirectory: (directory) => {
|
|
49
|
-
if (opts.ignoreFile &&
|
|
50
|
-
parentDirectoriesContain(opts.ignoreFile, directory)) {
|
|
51
|
-
return false;
|
|
65
|
+
else {
|
|
66
|
+
extensions = ['.js', '.json', '.node'];
|
|
52
67
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
const result = (0, resolver_1.resolveModule)(x, {
|
|
69
|
+
basedir: opts.basedir || process.cwd(),
|
|
70
|
+
extensions,
|
|
71
|
+
});
|
|
72
|
+
// Only use ESM resolution result if it's an actual ESM package
|
|
73
|
+
// For CJS packages, fall through to standard CommonJS resolution
|
|
74
|
+
// to ensure all callbacks (catchReadFile, catchPackageFilter) are handled correctly
|
|
75
|
+
if (result.isESM) {
|
|
76
|
+
// This is a real ESM package, handle it here
|
|
77
|
+
if (opts.catchReadFile) {
|
|
78
|
+
// Find the package.json for this resolved module
|
|
79
|
+
let currentDir = path_1.default.dirname(result.resolved);
|
|
80
|
+
while (currentDir !== path_1.default.dirname(currentDir)) {
|
|
81
|
+
const pkgPath = path_1.default.join(currentDir, 'package.json');
|
|
82
|
+
// Honor ignoreFile to ensure correct package marker determination
|
|
83
|
+
if (opts.ignoreFile &&
|
|
84
|
+
path_1.default.normalize(pkgPath) === path_1.default.normalize(opts.ignoreFile)) {
|
|
85
|
+
// Skip this package.json as it's marked to be ignored
|
|
86
|
+
currentDir = path_1.default.dirname(currentDir);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (fs_1.default.existsSync(pkgPath)) {
|
|
90
|
+
// Check if this package.json is in node_modules (not the root package)
|
|
91
|
+
if (currentDir.includes('node_modules')) {
|
|
92
|
+
opts.catchReadFile(pkgPath);
|
|
93
|
+
// Also call catchPackageFilter if provided
|
|
94
|
+
if (opts.catchPackageFilter) {
|
|
95
|
+
const pkgContent = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
|
|
96
|
+
// If package doesn't have a "main" field but we resolved via exports,
|
|
97
|
+
// add a synthetic "main" field so runtime resolution works
|
|
98
|
+
if (!pkgContent.main) {
|
|
99
|
+
const relativePath = path_1.default.relative(currentDir, result.resolved);
|
|
100
|
+
pkgContent.main = `./${relativePath.replace(/\\/g, '/')}`;
|
|
101
|
+
}
|
|
102
|
+
opts.catchPackageFilter(pkgContent, currentDir, currentDir);
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
currentDir = path_1.default.dirname(currentDir);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// ESM package resolved successfully
|
|
111
|
+
resolve(result.resolved);
|
|
112
|
+
return;
|
|
56
113
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
114
|
+
// CJS package - fall through to standard CommonJS resolution
|
|
115
|
+
// to handle all callbacks properly
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// ESM resolution failed - fall through to standard CommonJS resolution
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Use standard CommonJS resolution
|
|
122
|
+
try {
|
|
123
|
+
resolve((0, resolve_1.sync)(x, {
|
|
124
|
+
basedir: opts.basedir,
|
|
125
|
+
extensions: opts.extensions,
|
|
126
|
+
isFile: (file) => {
|
|
127
|
+
if (opts.ignoreFile &&
|
|
128
|
+
path_1.default.join(path_1.default.dirname(opts.ignoreFile), PROOF) === file) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
let stat;
|
|
132
|
+
try {
|
|
133
|
+
stat = fs_1.default.statSync(file);
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
const ex = e;
|
|
137
|
+
if (ex && (ex.code === 'ENOENT' || ex.code === 'ENOTDIR'))
|
|
138
|
+
return false;
|
|
139
|
+
throw ex;
|
|
140
|
+
}
|
|
141
|
+
return stat.isFile() || stat.isFIFO();
|
|
142
|
+
},
|
|
143
|
+
isDirectory: (directory) => {
|
|
144
|
+
if (opts.ignoreFile &&
|
|
145
|
+
parentDirectoriesContain(opts.ignoreFile, directory)) {
|
|
60
146
|
return false;
|
|
61
147
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
148
|
+
let stat;
|
|
149
|
+
try {
|
|
150
|
+
stat = fs_1.default.statSync(directory);
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
const ex = e;
|
|
154
|
+
if (ex && (ex.code === 'ENOENT' || ex.code === 'ENOTDIR')) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
throw ex;
|
|
158
|
+
}
|
|
159
|
+
return stat.isDirectory();
|
|
160
|
+
},
|
|
161
|
+
readFileSync: (file) => {
|
|
162
|
+
if (opts.ignoreFile && opts.ignoreFile === file) {
|
|
163
|
+
return Buffer.from(`{"main":"${PROOF}"}`);
|
|
164
|
+
}
|
|
165
|
+
if (opts.catchReadFile) {
|
|
166
|
+
opts.catchReadFile(file);
|
|
167
|
+
}
|
|
168
|
+
return fs_1.default.readFileSync(file);
|
|
169
|
+
},
|
|
170
|
+
packageFilter: (config, base, dir) => {
|
|
171
|
+
if (opts.catchPackageFilter) {
|
|
172
|
+
opts.catchPackageFilter(config, base, dir);
|
|
173
|
+
}
|
|
174
|
+
return config;
|
|
175
|
+
},
|
|
176
|
+
/** function to synchronously resolve a potential symlink to its real path */
|
|
177
|
+
// realpathSync?: (file: string) => string;
|
|
178
|
+
realpathSync: (file) => {
|
|
179
|
+
const file2 = (0, common_1.toNormalizedRealPath)(file);
|
|
180
|
+
return file2;
|
|
181
|
+
},
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
reject(error);
|
|
186
|
+
}
|
|
88
187
|
});
|
|
89
188
|
}
|
|
90
189
|
exports.follow = follow;
|
package/lib-es5/index.js
CHANGED
|
@@ -149,7 +149,6 @@ async function needViaCache(target) {
|
|
|
149
149
|
return c;
|
|
150
150
|
}
|
|
151
151
|
async function exec(argv2) {
|
|
152
|
-
var _a, _b;
|
|
153
152
|
const argv = (0, minimist_1.default)(argv2, {
|
|
154
153
|
boolean: [
|
|
155
154
|
'b',
|
|
@@ -413,7 +412,10 @@ async function exec(argv2) {
|
|
|
413
412
|
await needWithDryRun(target);
|
|
414
413
|
target.fabricator = fabricatorForTarget(target);
|
|
415
414
|
if (bytecode) {
|
|
416
|
-
await needWithDryRun(
|
|
415
|
+
await needWithDryRun({
|
|
416
|
+
...target.fabricator,
|
|
417
|
+
forceBuild,
|
|
418
|
+
});
|
|
417
419
|
}
|
|
418
420
|
}
|
|
419
421
|
if (dryRunResults.fetched && !dryRunResults.built) {
|
|
@@ -433,7 +435,7 @@ async function exec(argv2) {
|
|
|
433
435
|
try {
|
|
434
436
|
(0, mach_o_1.signMachOExecutable)(signedBinaryPath);
|
|
435
437
|
}
|
|
436
|
-
catch
|
|
438
|
+
catch {
|
|
437
439
|
throw (0, log_1.wasReported)('Cannot generate bytecode', [
|
|
438
440
|
'pkg fails to run "codesign" utility. Due to the mandatory signing',
|
|
439
441
|
'requirement of macOS, executables must be signed. Please ensure the',
|
|
@@ -450,7 +452,7 @@ async function exec(argv2) {
|
|
|
450
452
|
// marker
|
|
451
453
|
let marker;
|
|
452
454
|
if (configJson) {
|
|
453
|
-
options_1.default.set(configJson
|
|
455
|
+
options_1.default.set(configJson?.pkg);
|
|
454
456
|
marker = {
|
|
455
457
|
config: configJson,
|
|
456
458
|
base: path_1.default.dirname(config),
|
|
@@ -458,7 +460,7 @@ async function exec(argv2) {
|
|
|
458
460
|
};
|
|
459
461
|
}
|
|
460
462
|
else {
|
|
461
|
-
options_1.default.set(inputJson
|
|
463
|
+
options_1.default.set(inputJson?.pkg);
|
|
462
464
|
marker = {
|
|
463
465
|
config: inputJson || {},
|
|
464
466
|
base: path_1.default.dirname(input),
|
|
@@ -473,13 +475,13 @@ async function exec(argv2) {
|
|
|
473
475
|
}
|
|
474
476
|
if (argv['public-packages']) {
|
|
475
477
|
params.publicPackages = argv['public-packages'].split(',');
|
|
476
|
-
if (
|
|
478
|
+
if (params.publicPackages?.indexOf('*') !== -1) {
|
|
477
479
|
params.publicPackages = ['*'];
|
|
478
480
|
}
|
|
479
481
|
}
|
|
480
482
|
if (argv['no-dict']) {
|
|
481
483
|
params.noDictionary = argv['no-dict'].split(',');
|
|
482
|
-
if (
|
|
484
|
+
if (params.noDictionary?.indexOf('*') !== -1) {
|
|
483
485
|
params.noDictionary = ['*'];
|
|
484
486
|
}
|
|
485
487
|
}
|
|
@@ -531,7 +533,7 @@ async function exec(argv2) {
|
|
|
531
533
|
// users can always replace the signature if necessary
|
|
532
534
|
(0, mach_o_1.signMachOExecutable)(target.output);
|
|
533
535
|
}
|
|
534
|
-
catch
|
|
536
|
+
catch {
|
|
535
537
|
if (target.arch === 'arm64') {
|
|
536
538
|
log_1.log.warn('Unable to sign the macOS executable', [
|
|
537
539
|
'Due to the mandatory code signing requirement, before the',
|
package/lib-es5/mach-o.js
CHANGED
package/lib-es5/options.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
class Options {
|
|
4
|
+
options;
|
|
4
5
|
constructor() {
|
|
5
6
|
this.options = {
|
|
6
7
|
dictionary: {},
|
|
7
8
|
};
|
|
8
9
|
}
|
|
9
10
|
set(options) {
|
|
10
|
-
this.options = options
|
|
11
|
+
this.options = options ?? this.options;
|
|
11
12
|
}
|
|
12
13
|
get() {
|
|
13
14
|
return this.options;
|
package/lib-es5/packer.js
CHANGED
|
@@ -87,7 +87,7 @@ function packer({ records, entrypoint, bytecode, }) {
|
|
|
87
87
|
}
|
|
88
88
|
else if (store === common_1.STORE_STAT) {
|
|
89
89
|
if (typeof value === 'object') {
|
|
90
|
-
const newStat =
|
|
90
|
+
const newStat = { ...value };
|
|
91
91
|
const buffer = Buffer.from(JSON.stringify(newStat));
|
|
92
92
|
stripes.push({ snap, store, buffer });
|
|
93
93
|
}
|
package/lib-es5/producer.js
CHANGED
|
@@ -127,14 +127,13 @@ function getPrebuildEnvPrefix(pkgName) {
|
|
|
127
127
|
.replace(/^_/, '')}`;
|
|
128
128
|
}
|
|
129
129
|
function nativePrebuildInstall(target, nodeFile) {
|
|
130
|
-
var _a, _b;
|
|
131
130
|
const prebuildInstall = path_1.default.join(__dirname, '../node_modules/.bin/prebuild-install');
|
|
132
131
|
const dir = findPackageJson(nodeFile);
|
|
133
132
|
const packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(dir, 'package.json'), { encoding: 'utf-8' }));
|
|
134
133
|
// only try prebuild-install for packages that actually use it or if
|
|
135
134
|
// explicitly configured via environment variables
|
|
136
135
|
const envPrefix = getPrebuildEnvPrefix(packageJson.name);
|
|
137
|
-
if (
|
|
136
|
+
if (packageJson.dependencies?.['prebuild-install'] == null &&
|
|
138
137
|
![
|
|
139
138
|
`${envPrefix}_binary_host`,
|
|
140
139
|
`${envPrefix}_binary_host_mirror`,
|
|
@@ -155,7 +154,7 @@ function nativePrebuildInstall(target, nodeFile) {
|
|
|
155
154
|
if (!fs_1.default.existsSync(`${nodeFile}.bak`)) {
|
|
156
155
|
fs_1.default.copyFileSync(nodeFile, `${nodeFile}.bak`);
|
|
157
156
|
}
|
|
158
|
-
const napiVersions =
|
|
157
|
+
const napiVersions = packageJson?.binary?.napi_versions;
|
|
159
158
|
const options = [
|
|
160
159
|
'--platform',
|
|
161
160
|
types_1.platform[target.platform],
|
|
@@ -298,7 +297,7 @@ function producer({ backpack, bakes, slash, target, symLinks, doCompress, native
|
|
|
298
297
|
// clone to prevent 'skip' propagate
|
|
299
298
|
// to other targets, since same stripe
|
|
300
299
|
// is used for several targets
|
|
301
|
-
const stripe =
|
|
300
|
+
const stripe = { ...stripes.shift() };
|
|
302
301
|
prevStripe = stripe;
|
|
303
302
|
if (stripe.buffer) {
|
|
304
303
|
if (stripe.store === common_1.STORE_BLOB) {
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveModule = void 0;
|
|
7
|
+
const resolve_1 = require("resolve");
|
|
8
|
+
const resolve_exports_1 = require("resolve.exports");
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const common_1 = require("./common");
|
|
12
|
+
const log_1 = require("./log");
|
|
13
|
+
/**
|
|
14
|
+
* Resolve using package.json "exports" field (ESM-style)
|
|
15
|
+
* @param packageName - Package name (e.g., 'nanoid')
|
|
16
|
+
* @param subpath - Subpath within package (e.g., './url-alphabet')
|
|
17
|
+
* @param packageRoot - Absolute path to package root
|
|
18
|
+
* @returns Resolved path or null if not found
|
|
19
|
+
*/
|
|
20
|
+
function resolveWithExports(packageName, subpath, packageRoot) {
|
|
21
|
+
try {
|
|
22
|
+
const packageJsonPath = path_1.default.join(packageRoot, 'package.json');
|
|
23
|
+
if (!fs_1.default.existsSync(packageJsonPath)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
27
|
+
// Check if package has exports field
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
const pkgAny = pkg;
|
|
30
|
+
if (!pkgAny.exports) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
// Use resolve.exports to handle the exports field
|
|
34
|
+
// For pkg's context, we're bundling CJS code, so try 'require' condition first
|
|
35
|
+
// Then fallback to 'import' for ESM-only packages
|
|
36
|
+
let resolved = (0, resolve_exports_1.exports)(pkgAny, subpath, {
|
|
37
|
+
require: true, // Try require first
|
|
38
|
+
});
|
|
39
|
+
// Fallback to import condition for ESM-only packages
|
|
40
|
+
if (!resolved) {
|
|
41
|
+
resolved = (0, resolve_exports_1.exports)(pkgAny, subpath, {
|
|
42
|
+
require: false, // This enables import condition
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (resolved) {
|
|
46
|
+
// resolved can be a string or array
|
|
47
|
+
const resolvedPath = Array.isArray(resolved) ? resolved[0] : resolved;
|
|
48
|
+
const fullPath = path_1.default.join(packageRoot, resolvedPath);
|
|
49
|
+
if (fs_1.default.existsSync(fullPath)) {
|
|
50
|
+
return fullPath;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
log_1.log.debug(`Failed to resolve with exports field: ${packageName}${subpath}`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Try to resolve a module specifier as an ESM package
|
|
62
|
+
* @param specifier - Module specifier (e.g., 'nanoid', 'nanoid/url-alphabet')
|
|
63
|
+
* @param basedir - Base directory for resolution
|
|
64
|
+
* @returns Resolved path or null
|
|
65
|
+
*/
|
|
66
|
+
function tryResolveESM(specifier, basedir) {
|
|
67
|
+
try {
|
|
68
|
+
// Parse package name and subpath
|
|
69
|
+
let packageName;
|
|
70
|
+
let subpath;
|
|
71
|
+
if (specifier.startsWith('@')) {
|
|
72
|
+
// Scoped package: @org/pkg or @org/pkg/subpath
|
|
73
|
+
const parts = specifier.split('/');
|
|
74
|
+
packageName = `${parts[0]}/${parts[1]}`;
|
|
75
|
+
subpath = parts.length > 2 ? `./${parts.slice(2).join('/')}` : '.';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Regular package: pkg or pkg/subpath
|
|
79
|
+
const slashIndex = specifier.indexOf('/');
|
|
80
|
+
if (slashIndex === -1) {
|
|
81
|
+
packageName = specifier;
|
|
82
|
+
subpath = '.';
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
packageName = specifier.substring(0, slashIndex);
|
|
86
|
+
subpath = `./${specifier.substring(slashIndex + 1)}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Use resolveSync to find the package root (works with pnpm and other layouts)
|
|
90
|
+
// Try to resolve the package.json to get the package root
|
|
91
|
+
try {
|
|
92
|
+
const pkgJsonPath = (0, resolve_1.sync)(path_1.default.join(packageName, 'package.json'), {
|
|
93
|
+
basedir,
|
|
94
|
+
preserveSymlinks: false,
|
|
95
|
+
});
|
|
96
|
+
const packageRoot = path_1.default.dirname(pkgJsonPath);
|
|
97
|
+
// Try to resolve with exports field
|
|
98
|
+
const resolved = resolveWithExports(packageName, subpath, packageRoot);
|
|
99
|
+
if (resolved) {
|
|
100
|
+
return resolved;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// If package.json resolution fails, fall through to return null
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Resolve a module specifier with ESM support
|
|
114
|
+
* Falls back to standard CommonJS resolution if ESM resolution fails
|
|
115
|
+
*
|
|
116
|
+
* @param specifier - Module specifier to resolve
|
|
117
|
+
* @param options - Resolution options
|
|
118
|
+
* @returns Resolved file path and ESM flag
|
|
119
|
+
*/
|
|
120
|
+
function resolveModule(specifier, options) {
|
|
121
|
+
const { basedir, extensions = ['.js', '.json', '.node'] } = options;
|
|
122
|
+
// First, try ESM-style resolution with exports field
|
|
123
|
+
const esmResolved = tryResolveESM(specifier, basedir);
|
|
124
|
+
if (esmResolved) {
|
|
125
|
+
// Use isESMFile which walks up to find the correct package.json
|
|
126
|
+
return {
|
|
127
|
+
resolved: esmResolved,
|
|
128
|
+
isESM: (0, common_1.isESMFile)(esmResolved),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Fallback to standard CommonJS resolution
|
|
132
|
+
const resolved = (0, resolve_1.sync)(specifier, {
|
|
133
|
+
basedir,
|
|
134
|
+
extensions,
|
|
135
|
+
});
|
|
136
|
+
return {
|
|
137
|
+
resolved,
|
|
138
|
+
isESM: false, // CJS resolution
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
exports.resolveModule = resolveModule;
|
|
142
|
+
//# sourceMappingURL=resolver.js.map
|
package/lib-es5/sea.js
CHANGED
|
@@ -21,7 +21,7 @@ const exists = async (path) => {
|
|
|
21
21
|
try {
|
|
22
22
|
return await (0, promises_1.stat)(path);
|
|
23
23
|
}
|
|
24
|
-
catch
|
|
24
|
+
catch {
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
27
|
};
|
|
@@ -75,15 +75,15 @@ async function extract(os, archivePath) {
|
|
|
75
75
|
}
|
|
76
76
|
/** Verify the checksum of downloaded NodeJS archive */
|
|
77
77
|
async function verifyChecksum(filePath, checksumUrl, fileName) {
|
|
78
|
-
var _a;
|
|
79
78
|
const response = await fetch(checksumUrl);
|
|
80
79
|
if (!response.ok) {
|
|
81
80
|
throw new Error(`Failed to download checksum file from ${checksumUrl}`);
|
|
82
81
|
}
|
|
83
82
|
const checksums = await response.text();
|
|
84
|
-
const expectedChecksum =
|
|
83
|
+
const expectedChecksum = checksums
|
|
85
84
|
.split('\n')
|
|
86
|
-
.find((line) => line.includes(fileName))
|
|
85
|
+
.find((line) => line.includes(fileName))
|
|
86
|
+
?.split(' ')[0];
|
|
87
87
|
if (!expectedChecksum) {
|
|
88
88
|
throw new Error(`Checksum for ${fileName} not found`);
|
|
89
89
|
}
|
|
@@ -252,7 +252,14 @@ async function sea(entryPoint, opts) {
|
|
|
252
252
|
// docs: https://nodejs.org/api/single-executable-applications.html
|
|
253
253
|
const blobPath = (0, path_1.join)(tmpDir, 'sea-prep.blob');
|
|
254
254
|
const seaConfigFilePath = (0, path_1.join)(tmpDir, 'sea-config.json');
|
|
255
|
-
const seaConfig =
|
|
255
|
+
const seaConfig = {
|
|
256
|
+
main: entryPoint,
|
|
257
|
+
output: blobPath,
|
|
258
|
+
...{
|
|
259
|
+
...defaultSeaConfig,
|
|
260
|
+
...(opts.seaConfig || {}),
|
|
261
|
+
},
|
|
262
|
+
};
|
|
256
263
|
log_1.log.info('Creating sea-config.json file...');
|
|
257
264
|
await (0, promises_1.writeFile)(seaConfigFilePath, JSON.stringify(seaConfig));
|
|
258
265
|
log_1.log.info('Generating the blob...');
|
|
@@ -269,7 +276,7 @@ async function sea(entryPoint, opts) {
|
|
|
269
276
|
// users can always replace the signature if necessary
|
|
270
277
|
(0, mach_o_1.signMachOExecutable)(output);
|
|
271
278
|
}
|
|
272
|
-
catch
|
|
279
|
+
catch {
|
|
273
280
|
if (target.arch === 'arm64') {
|
|
274
281
|
log_1.log.warn('Unable to sign the macOS executable', [
|
|
275
282
|
'Due to the mandatory code signing requirement, before the',
|
package/lib-es5/walker.js
CHANGED
|
@@ -38,6 +38,7 @@ const colors_1 = require("./colors");
|
|
|
38
38
|
const follow_1 = require("./follow");
|
|
39
39
|
const log_1 = require("./log");
|
|
40
40
|
const detector = __importStar(require("./detector"));
|
|
41
|
+
const esm_transformer_1 = require("./esm-transformer");
|
|
41
42
|
const options_1 = __importDefault(require("./options"));
|
|
42
43
|
// Note: as a developer, you can set the PKG_STRICT_VER variable.
|
|
43
44
|
// this will turn on some assertion in the walker code below
|
|
@@ -63,9 +64,6 @@ function isBuiltin(moduleName) {
|
|
|
63
64
|
: moduleName;
|
|
64
65
|
return module_1.builtinModules.includes(moduleNameWithoutPrefix);
|
|
65
66
|
}
|
|
66
|
-
function unlikelyJavascript(file) {
|
|
67
|
-
return ['.css', '.html', '.json', '.vue'].includes(path_1.default.extname(file));
|
|
68
|
-
}
|
|
69
67
|
function isPublic(config) {
|
|
70
68
|
if (config.private) {
|
|
71
69
|
return false;
|
|
@@ -232,7 +230,7 @@ function stepDetect(record, marker, derivatives) {
|
|
|
232
230
|
return false;
|
|
233
231
|
}
|
|
234
232
|
return true; // can i go inside?
|
|
235
|
-
});
|
|
233
|
+
}, record.file);
|
|
236
234
|
}
|
|
237
235
|
catch (error) {
|
|
238
236
|
log_1.log.error(error.message, record.file);
|
|
@@ -265,6 +263,12 @@ async function findCommonJunctionPoint(file, realFile) {
|
|
|
265
263
|
}
|
|
266
264
|
}
|
|
267
265
|
class Walker {
|
|
266
|
+
params;
|
|
267
|
+
symLinks;
|
|
268
|
+
patches;
|
|
269
|
+
tasks;
|
|
270
|
+
records;
|
|
271
|
+
dictionary;
|
|
268
272
|
constructor() {
|
|
269
273
|
this.tasks = [];
|
|
270
274
|
this.records = {};
|
|
@@ -348,7 +352,7 @@ class Walker {
|
|
|
348
352
|
this.append(task);
|
|
349
353
|
return;
|
|
350
354
|
}
|
|
351
|
-
this.append(
|
|
355
|
+
this.append({ ...task, file: realFile });
|
|
352
356
|
this.appendStat({
|
|
353
357
|
file: task.file,
|
|
354
358
|
store: common_1.STORE_STAT,
|
|
@@ -380,7 +384,7 @@ class Walker {
|
|
|
380
384
|
this.append(task);
|
|
381
385
|
return;
|
|
382
386
|
}
|
|
383
|
-
this.append(
|
|
387
|
+
this.append({ ...task, file: realFile });
|
|
384
388
|
await this.appendSymlink(task.file, realFile);
|
|
385
389
|
this.appendStat({
|
|
386
390
|
file: task.file,
|
|
@@ -389,7 +393,7 @@ class Walker {
|
|
|
389
393
|
}
|
|
390
394
|
async appendFilesFromConfig(marker) {
|
|
391
395
|
const { config, configPath, base } = marker;
|
|
392
|
-
const pkgConfig = config
|
|
396
|
+
const pkgConfig = config?.pkg;
|
|
393
397
|
if (pkgConfig) {
|
|
394
398
|
let { scripts } = pkgConfig;
|
|
395
399
|
if (scripts) {
|
|
@@ -606,7 +610,6 @@ class Walker {
|
|
|
606
610
|
}
|
|
607
611
|
}
|
|
608
612
|
async stepDerivatives_ALIAS_AS_RESOLVABLE(record, marker, derivative) {
|
|
609
|
-
var _a, _b;
|
|
610
613
|
const newPackages = [];
|
|
611
614
|
const catchReadFile = (file) => {
|
|
612
615
|
(0, assert_1.default)((0, common_1.isPackageJson)(file), `walker: ${file} must be package.json`);
|
|
@@ -640,7 +643,7 @@ class Walker {
|
|
|
640
643
|
}
|
|
641
644
|
if (failure) {
|
|
642
645
|
const { toplevel } = marker;
|
|
643
|
-
const mainNotFound = newPackages.length > 0 && !
|
|
646
|
+
const mainNotFound = newPackages.length > 0 && !newPackages[0].marker?.config?.main;
|
|
644
647
|
const debug = !toplevel ||
|
|
645
648
|
derivative.mayExclude ||
|
|
646
649
|
(mainNotFound && derivative.fromDependencies);
|
|
@@ -678,17 +681,33 @@ class Walker {
|
|
|
678
681
|
break;
|
|
679
682
|
}
|
|
680
683
|
}
|
|
684
|
+
// Add all discovered package.json files, not just the one determined by the double-resolution logic
|
|
685
|
+
// This is necessary because ESM resolution may bypass the standard packageFilter mechanism
|
|
686
|
+
// However, only include package.json files that are either:
|
|
687
|
+
// 1. Inside node_modules (dependencies)
|
|
688
|
+
// 2. Inside the base directory of the current marker (application being packaged)
|
|
689
|
+
// This prevents including pkg's own package.json when used from source
|
|
690
|
+
for (const newPackage of newPackages) {
|
|
691
|
+
if (newPackage.marker) {
|
|
692
|
+
const file = newPackage.packageJson;
|
|
693
|
+
const isInNodeModules = file.includes(`${path_1.default.sep}node_modules${path_1.default.sep}`);
|
|
694
|
+
const isInMarkerBase = marker.base && file.startsWith(marker.base);
|
|
695
|
+
if (isInNodeModules || isInMarkerBase) {
|
|
696
|
+
await this.appendBlobOrContent({
|
|
697
|
+
file,
|
|
698
|
+
marker: newPackage.marker,
|
|
699
|
+
store: common_1.STORE_CONTENT,
|
|
700
|
+
reason: record.file,
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
// Keep the original logic for determining the marker for the resolved file
|
|
681
706
|
if (newPackageForNewRecords) {
|
|
682
707
|
if (strictVerify) {
|
|
683
708
|
(0, assert_1.default)(newPackageForNewRecords.packageJson ===
|
|
684
709
|
(0, common_1.normalizePath)(newPackageForNewRecords.packageJson));
|
|
685
710
|
}
|
|
686
|
-
await this.appendBlobOrContent({
|
|
687
|
-
file: newPackageForNewRecords.packageJson,
|
|
688
|
-
marker: newPackageForNewRecords.marker,
|
|
689
|
-
store: common_1.STORE_CONTENT,
|
|
690
|
-
reason: record.file,
|
|
691
|
-
});
|
|
692
711
|
}
|
|
693
712
|
await this.appendBlobOrContent({
|
|
694
713
|
file: newFile,
|
|
@@ -729,7 +748,7 @@ class Walker {
|
|
|
729
748
|
await this.stepActivate(marker, derivatives1);
|
|
730
749
|
await this.stepDerivatives(record, marker, derivatives1);
|
|
731
750
|
if (store === common_1.STORE_BLOB) {
|
|
732
|
-
if (unlikelyJavascript(record.file) || (0, common_1.isDotNODE)(record.file)) {
|
|
751
|
+
if ((0, common_1.unlikelyJavascript)(record.file) || (0, common_1.isDotNODE)(record.file)) {
|
|
733
752
|
await this.appendBlobOrContent({
|
|
734
753
|
file: record.file,
|
|
735
754
|
marker,
|
|
@@ -745,7 +764,9 @@ class Walker {
|
|
|
745
764
|
});
|
|
746
765
|
}
|
|
747
766
|
}
|
|
748
|
-
if (store === common_1.STORE_BLOB ||
|
|
767
|
+
if (store === common_1.STORE_BLOB ||
|
|
768
|
+
(store === common_1.STORE_CONTENT && (0, common_1.isPackageJson)(record.file)) ||
|
|
769
|
+
this.hasPatch(record)) {
|
|
749
770
|
if (!record.body) {
|
|
750
771
|
await stepRead(record);
|
|
751
772
|
this.stepPatch(record);
|
|
@@ -753,6 +774,92 @@ class Walker {
|
|
|
753
774
|
stepStrip(record);
|
|
754
775
|
}
|
|
755
776
|
}
|
|
777
|
+
// Patch package.json files to add synthetic main field if needed
|
|
778
|
+
if (store === common_1.STORE_CONTENT &&
|
|
779
|
+
(0, common_1.isPackageJson)(record.file) &&
|
|
780
|
+
record.body) {
|
|
781
|
+
try {
|
|
782
|
+
const pkgContent = JSON.parse(record.body.toString('utf8'));
|
|
783
|
+
let modified = false;
|
|
784
|
+
// If package has exports but no main, add a synthetic main field
|
|
785
|
+
if (pkgContent.exports && !pkgContent.main) {
|
|
786
|
+
// Try to get main from marker.config first (set by catchPackageFilter in follow.ts)
|
|
787
|
+
if (marker.config?.main) {
|
|
788
|
+
pkgContent.main = marker.config.main;
|
|
789
|
+
modified = true;
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
// Fallback: try to infer main from exports field
|
|
793
|
+
const { exports } = pkgContent;
|
|
794
|
+
if (typeof exports === 'string') {
|
|
795
|
+
pkgContent.main = exports;
|
|
796
|
+
modified = true;
|
|
797
|
+
}
|
|
798
|
+
else if (exports && typeof exports === 'object') {
|
|
799
|
+
// Handle conditional exports
|
|
800
|
+
if (exports['.']) {
|
|
801
|
+
if (typeof exports['.'] === 'string') {
|
|
802
|
+
pkgContent.main = exports['.'];
|
|
803
|
+
modified = true;
|
|
804
|
+
}
|
|
805
|
+
else if (typeof exports['.'] === 'object') {
|
|
806
|
+
// Try to get the best entry point for CJS
|
|
807
|
+
// Prefer: require > node > default
|
|
808
|
+
let mainEntry;
|
|
809
|
+
if (typeof exports['.'].require === 'string' &&
|
|
810
|
+
exports['.'].require) {
|
|
811
|
+
mainEntry = exports['.'].require;
|
|
812
|
+
}
|
|
813
|
+
else if (typeof exports['.'].node === 'string' &&
|
|
814
|
+
exports['.'].node) {
|
|
815
|
+
mainEntry = exports['.'].node;
|
|
816
|
+
}
|
|
817
|
+
else if (typeof exports['.'].default === 'string' &&
|
|
818
|
+
exports['.'].default) {
|
|
819
|
+
mainEntry = exports['.'].default;
|
|
820
|
+
}
|
|
821
|
+
if (mainEntry) {
|
|
822
|
+
pkgContent.main = mainEntry;
|
|
823
|
+
modified = true;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
// If package has "type": "module", we need to change it to "commonjs"
|
|
831
|
+
// because we transform all ESM files to CJS before bytecode compilation
|
|
832
|
+
if (pkgContent.type === 'module') {
|
|
833
|
+
pkgContent.type = 'commonjs';
|
|
834
|
+
modified = true;
|
|
835
|
+
}
|
|
836
|
+
// Only rewrite if we made changes
|
|
837
|
+
if (modified) {
|
|
838
|
+
record.body = Buffer.from(JSON.stringify(pkgContent, null, 2), 'utf8');
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
catch (error) {
|
|
842
|
+
// Ignore JSON parsing errors
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
// Transform ESM to CJS before bytecode compilation
|
|
846
|
+
// Check all JS-like files (.js, .mjs, .cjs) but only transform ESM ones
|
|
847
|
+
if (store === common_1.STORE_BLOB &&
|
|
848
|
+
record.body &&
|
|
849
|
+
((0, common_1.isDotJS)(record.file) || record.file.endsWith('.mjs'))) {
|
|
850
|
+
if ((0, common_1.isESMFile)(record.file)) {
|
|
851
|
+
try {
|
|
852
|
+
const result = (0, esm_transformer_1.transformESMtoCJS)(record.body.toString('utf8'), record.file);
|
|
853
|
+
if (result.isTransformed) {
|
|
854
|
+
record.body = Buffer.from(result.code, 'utf8');
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
catch (error) {
|
|
858
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
859
|
+
throw new Error(`Failed to transform ESM module to CJS for file "${record.file}": ${message}`);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
756
863
|
if (store === common_1.STORE_BLOB) {
|
|
757
864
|
const derivatives2 = [];
|
|
758
865
|
stepDetect(record, marker, derivatives2);
|
|
@@ -834,8 +941,7 @@ class Walker {
|
|
|
834
941
|
}
|
|
835
942
|
}
|
|
836
943
|
async readDictionary(marker) {
|
|
837
|
-
|
|
838
|
-
if (((_a = this.params.noDictionary) === null || _a === void 0 ? void 0 : _a[0]) === '*') {
|
|
944
|
+
if (this.params.noDictionary?.[0] === '*') {
|
|
839
945
|
return;
|
|
840
946
|
}
|
|
841
947
|
const dd = path_1.default.join(__dirname, '../dictionary');
|
|
@@ -843,7 +949,7 @@ class Walker {
|
|
|
843
949
|
for (const file of files) {
|
|
844
950
|
if (/\.js$/.test(file)) {
|
|
845
951
|
const name = file.slice(0, -3);
|
|
846
|
-
if (
|
|
952
|
+
if (this.params.noDictionary?.includes(file)) {
|
|
847
953
|
continue;
|
|
848
954
|
}
|
|
849
955
|
// eslint-disable-next-line import/no-dynamic-require, global-require, @typescript-eslint/no-var-requires
|
|
@@ -851,7 +957,7 @@ class Walker {
|
|
|
851
957
|
this.dictionary[name] = config;
|
|
852
958
|
}
|
|
853
959
|
}
|
|
854
|
-
const pkgConfig =
|
|
960
|
+
const pkgConfig = marker.config?.pkg;
|
|
855
961
|
if (pkgConfig) {
|
|
856
962
|
const { dictionary } = pkgConfig;
|
|
857
963
|
if (dictionary) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yao-pkg/pkg",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.13.0",
|
|
4
4
|
"description": "Package your Node.js project into an executable",
|
|
5
5
|
"main": "lib-es5/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@babel/generator": "^7.23.0",
|
|
26
26
|
"@babel/parser": "^7.23.0",
|
|
27
|
+
"@babel/traverse": "^7.23.0",
|
|
27
28
|
"@babel/types": "^7.23.0",
|
|
29
|
+
"esbuild": "^0.24.0",
|
|
28
30
|
"@yao-pkg/pkg-fetch": "3.5.32",
|
|
29
31
|
"into-stream": "^6.0.0",
|
|
30
32
|
"minimist": "^1.2.6",
|
|
@@ -33,15 +35,16 @@
|
|
|
33
35
|
"picomatch": "^4.0.2",
|
|
34
36
|
"prebuild-install": "^7.1.1",
|
|
35
37
|
"resolve": "^1.22.10",
|
|
38
|
+
"resolve.exports": "^2.0.3",
|
|
36
39
|
"stream-meter": "^1.0.4",
|
|
37
|
-
"tar": "^7.
|
|
40
|
+
"tar": "^7.5.6",
|
|
38
41
|
"tinyglobby": "^0.2.11",
|
|
39
42
|
"unzipper": "^0.12.3"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
42
|
-
"@babel/core": "^7.23.0",
|
|
43
45
|
"@release-it/conventional-changelog": "^7.0.2",
|
|
44
46
|
"@types/babel__generator": "^7.6.5",
|
|
47
|
+
"@types/babel__traverse": "^7.20.3",
|
|
45
48
|
"@types/minimist": "^1.2.2",
|
|
46
49
|
"@types/multistream": "^4.1.0",
|
|
47
50
|
"@types/node": "^16.18.113",
|
|
@@ -52,7 +55,6 @@
|
|
|
52
55
|
"@types/unzipper": "^0.10.10",
|
|
53
56
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
54
57
|
"@typescript-eslint/parser": "^6.7.4",
|
|
55
|
-
"esbuild": "^0.24.0",
|
|
56
58
|
"esbuild-register": "^3.6.0",
|
|
57
59
|
"eslint": "^8.50.0",
|
|
58
60
|
"eslint-config-airbnb-base": "^15.0.0",
|