next-bun-compile 0.6.8 → 0.6.10
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/dist/cli.js +1 -1
- package/dist/{index-mx555e90.js → index-rx8tn52q.js} +203 -14
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -113,9 +113,17 @@ function generateStubs(standaloneDir) {
|
|
|
113
113
|
}
|
|
114
114
|
function findTurbopackAliases(standaloneNextDir) {
|
|
115
115
|
const seen = new Map;
|
|
116
|
+
const ensure = (alias) => {
|
|
117
|
+
let e = seen.get(alias);
|
|
118
|
+
if (!e) {
|
|
119
|
+
e = { target: alias.replace(/-[0-9a-f]{16}$/, ""), subpaths: new Set };
|
|
120
|
+
seen.set(alias, e);
|
|
121
|
+
}
|
|
122
|
+
return e;
|
|
123
|
+
};
|
|
116
124
|
const serverDir = join(standaloneNextDir, "server");
|
|
117
125
|
if (existsSync(serverDir)) {
|
|
118
|
-
const re = /["']([^"'\s/]+-[0-9a-f]{16})(?:\/[^"'\s]+)?["']/g;
|
|
126
|
+
const re = /["']([^"'\s/]+-[0-9a-f]{16})(?:\/([^"'\s]+))?["']/g;
|
|
119
127
|
for (const f of walkDir(serverDir)) {
|
|
120
128
|
if (!f.absolutePath.endsWith(".js"))
|
|
121
129
|
continue;
|
|
@@ -127,10 +135,9 @@ function findTurbopackAliases(standaloneNextDir) {
|
|
|
127
135
|
}
|
|
128
136
|
let m;
|
|
129
137
|
while (m = re.exec(content)) {
|
|
130
|
-
const
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
seen.set(alias, alias.replace(/-[0-9a-f]{16}$/, ""));
|
|
138
|
+
const entry = ensure(m[1]);
|
|
139
|
+
if (m[2])
|
|
140
|
+
entry.subpaths.add(m[2]);
|
|
134
141
|
}
|
|
135
142
|
}
|
|
136
143
|
}
|
|
@@ -145,23 +152,94 @@ function findTurbopackAliases(standaloneNextDir) {
|
|
|
145
152
|
try {
|
|
146
153
|
if (!lstatSync(aliasPath).isSymbolicLink())
|
|
147
154
|
continue;
|
|
148
|
-
seen.set(name,
|
|
155
|
+
seen.set(name, {
|
|
156
|
+
target: basename(realpathSync(aliasPath)),
|
|
157
|
+
subpaths: new Set
|
|
158
|
+
});
|
|
149
159
|
} catch {
|
|
150
160
|
continue;
|
|
151
161
|
}
|
|
152
162
|
}
|
|
153
163
|
}
|
|
154
|
-
return Array.from(seen, ([alias, target]) => ({
|
|
164
|
+
return Array.from(seen, ([alias, { target, subpaths }]) => ({
|
|
165
|
+
alias,
|
|
166
|
+
target,
|
|
167
|
+
subpaths: Array.from(subpaths)
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
function buildCanonicalResolutions(externalRoot, aliases) {
|
|
171
|
+
const out = new Map;
|
|
172
|
+
const findFile = (dir, candidates) => {
|
|
173
|
+
for (const c of candidates) {
|
|
174
|
+
if (!c)
|
|
175
|
+
continue;
|
|
176
|
+
const p = join(dir, c);
|
|
177
|
+
if (existsSync(p) && statSync(p).isFile())
|
|
178
|
+
return c.replace(/\\/g, "/");
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
};
|
|
182
|
+
const resolveMain = (canonicalDir) => {
|
|
183
|
+
const pkgPath = join(canonicalDir, "package.json");
|
|
184
|
+
let main = "index.js";
|
|
185
|
+
if (existsSync(pkgPath)) {
|
|
186
|
+
try {
|
|
187
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
188
|
+
if (typeof pkg.main === "string")
|
|
189
|
+
main = pkg.main;
|
|
190
|
+
} catch {}
|
|
191
|
+
}
|
|
192
|
+
return findFile(canonicalDir, [
|
|
193
|
+
main,
|
|
194
|
+
main + ".js",
|
|
195
|
+
main + ".cjs",
|
|
196
|
+
main + ".mjs",
|
|
197
|
+
join(main, "index.js"),
|
|
198
|
+
join(main, "index.cjs"),
|
|
199
|
+
join(main, "index.mjs"),
|
|
200
|
+
"index.js",
|
|
201
|
+
"index.cjs",
|
|
202
|
+
"index.mjs"
|
|
203
|
+
]);
|
|
204
|
+
};
|
|
205
|
+
const resolveSub = (canonicalDir, sub) => {
|
|
206
|
+
const stripped = sub.replace(/\.(?:js|cjs|mjs|json)$/, "");
|
|
207
|
+
return findFile(canonicalDir, [
|
|
208
|
+
sub,
|
|
209
|
+
stripped + ".js",
|
|
210
|
+
stripped + ".mjs",
|
|
211
|
+
stripped + ".cjs",
|
|
212
|
+
stripped + ".json",
|
|
213
|
+
join(stripped, "index.js"),
|
|
214
|
+
join(stripped, "index.mjs"),
|
|
215
|
+
join(stripped, "index.cjs")
|
|
216
|
+
]);
|
|
217
|
+
};
|
|
218
|
+
for (const { alias, target, subpaths } of aliases) {
|
|
219
|
+
const canonicalDir = join(externalRoot, target);
|
|
220
|
+
if (!existsSync(canonicalDir))
|
|
221
|
+
continue;
|
|
222
|
+
const main = resolveMain(canonicalDir);
|
|
223
|
+
if (main) {
|
|
224
|
+
out.set(alias, `.next/node_modules/${target}/${main}`);
|
|
225
|
+
}
|
|
226
|
+
for (const sub of subpaths) {
|
|
227
|
+
const file = resolveSub(canonicalDir, sub);
|
|
228
|
+
if (file) {
|
|
229
|
+
out.set(`${alias}/${sub}`, `.next/node_modules/${target}/${file}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return out;
|
|
155
234
|
}
|
|
156
|
-
function rewriteTurbopackAliases(standaloneNextDir, aliases) {
|
|
157
|
-
if (aliases.length === 0)
|
|
235
|
+
function rewriteTurbopackAliases(standaloneNextDir, aliases, resolutions) {
|
|
236
|
+
if (aliases.length === 0 || resolutions.size === 0)
|
|
158
237
|
return;
|
|
159
238
|
const serverDir = join(standaloneNextDir, "server");
|
|
160
239
|
if (!existsSync(serverDir))
|
|
161
240
|
return;
|
|
162
241
|
const escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
163
|
-
const pattern = new RegExp(`(["'])(
|
|
164
|
-
const targetByAlias = new Map(aliases.map((a) => [a.alias, a.target]));
|
|
242
|
+
const pattern = new RegExp(`(["'])((?:` + aliases.map((a) => escape(a.alias)).join("|") + `)(?:/[^"']+)?)\\1`, "g");
|
|
165
243
|
let rewritten = 0;
|
|
166
244
|
for (const f of walkDir(serverDir)) {
|
|
167
245
|
if (!f.absolutePath.endsWith(".js"))
|
|
@@ -172,7 +250,12 @@ function rewriteTurbopackAliases(standaloneNextDir, aliases) {
|
|
|
172
250
|
} catch {
|
|
173
251
|
continue;
|
|
174
252
|
}
|
|
175
|
-
const next = content.replace(pattern, (
|
|
253
|
+
const next = content.replace(pattern, (match, quote, spec) => {
|
|
254
|
+
const rel = resolutions.get(spec);
|
|
255
|
+
if (!rel)
|
|
256
|
+
return match;
|
|
257
|
+
return `${quote}__NBC_BASE__/${rel}${quote}`;
|
|
258
|
+
});
|
|
176
259
|
if (next !== content) {
|
|
177
260
|
writeFileSync(f.absolutePath, next);
|
|
178
261
|
rewritten++;
|
|
@@ -343,7 +426,6 @@ function generateEntryPoint(options) {
|
|
|
343
426
|
}));
|
|
344
427
|
const standaloneNextDir = join(serverDir, ".next");
|
|
345
428
|
const turbopackAliases = findTurbopackAliases(standaloneNextDir);
|
|
346
|
-
rewriteTurbopackAliases(standaloneNextDir, turbopackAliases);
|
|
347
429
|
const aliasNames = new Set(turbopackAliases.map((a) => a.alias));
|
|
348
430
|
const runtimeFiles = walkDir(standaloneNextDir).filter((f) => {
|
|
349
431
|
const m = f.relativePath.replace(/\\/g, "/").match(/^node_modules\/([^/]+)/);
|
|
@@ -369,6 +451,8 @@ function generateEntryPoint(options) {
|
|
|
369
451
|
if (externalModules.length > 0) {
|
|
370
452
|
console.log(`next-bun-compile: Embedding ${externalModules.length} external modules for SSR`);
|
|
371
453
|
}
|
|
454
|
+
const canonicalResolutions = buildCanonicalResolutions(externalDir, turbopackAliases);
|
|
455
|
+
rewriteTurbopackAliases(standaloneNextDir, turbopackAliases, canonicalResolutions);
|
|
372
456
|
const ctx = JSON.parse(readFileSync(join(distDir, "bun-compile-ctx.json"), "utf-8"));
|
|
373
457
|
const { assetPrefix } = ctx;
|
|
374
458
|
const assetsToEmbed = assetPrefix ? [...publicFiles, ...runtimeFiles] : [...staticFiles, ...publicFiles, ...runtimeFiles];
|
|
@@ -410,11 +494,103 @@ ${mapEntries.join(`
|
|
|
410
494
|
const serverEntry = `import { assetMap } from "./assets.generated.js";
|
|
411
495
|
const path = require("path");
|
|
412
496
|
const fs = require("fs");
|
|
497
|
+
const Module = require("module");
|
|
413
498
|
|
|
414
499
|
const baseDir = path.dirname(process.execPath);
|
|
415
500
|
process.chdir(baseDir);
|
|
416
501
|
process.env.NODE_ENV = "production";
|
|
417
502
|
|
|
503
|
+
// Install a fallback Module._resolveFilename hook. bun's compiled-binary
|
|
504
|
+
// resolver doesn't walk node_modules from inside a node_modules entry, so
|
|
505
|
+
// once execution enters an extracted package (sharp/lib/index.js → require
|
|
506
|
+
// of detect-libc, @img/sharp-linux-x64/sharp.node, etc.) bun gives up. This
|
|
507
|
+
// hook runs ONLY when bun's resolver throws and reimplements Node-compatible
|
|
508
|
+
// resolution from scratch — walk node_modules, read package.json main,
|
|
509
|
+
// honor exports maps. Generic: every externalized package's internal deps
|
|
510
|
+
// get resolved without per-package patching.
|
|
511
|
+
const __nbcOrigResolveFilename = Module._resolveFilename;
|
|
512
|
+
function __nbcStatFile(p) {
|
|
513
|
+
try { return fs.statSync(p).isFile() ? p : null; } catch { return null; }
|
|
514
|
+
}
|
|
515
|
+
function __nbcResolveMain(pkgDir, pkgJson) {
|
|
516
|
+
const main = pkgJson && typeof pkgJson.main === "string" ? pkgJson.main : "index.js";
|
|
517
|
+
return __nbcStatFile(path.join(pkgDir, main))
|
|
518
|
+
|| __nbcStatFile(path.join(pkgDir, main + ".js"))
|
|
519
|
+
|| __nbcStatFile(path.join(pkgDir, main + ".cjs"))
|
|
520
|
+
|| __nbcStatFile(path.join(pkgDir, main + ".mjs"))
|
|
521
|
+
|| __nbcStatFile(path.join(pkgDir, main, "index.js"))
|
|
522
|
+
|| __nbcStatFile(path.join(pkgDir, "index.js"))
|
|
523
|
+
|| __nbcStatFile(path.join(pkgDir, "index.cjs"));
|
|
524
|
+
}
|
|
525
|
+
function __nbcResolveSubpath(pkgDir, pkgJson, sub) {
|
|
526
|
+
// Honor exports map (CJS-relevant conditions only)
|
|
527
|
+
if (pkgJson && pkgJson.exports && typeof pkgJson.exports === "object") {
|
|
528
|
+
const key = "./" + sub;
|
|
529
|
+
const entry = pkgJson.exports[key];
|
|
530
|
+
if (entry) {
|
|
531
|
+
let target = typeof entry === "string"
|
|
532
|
+
? entry
|
|
533
|
+
: entry.require || entry.node || entry.default;
|
|
534
|
+
if (typeof target === "string" && target.startsWith("./")) {
|
|
535
|
+
const f = __nbcStatFile(path.join(pkgDir, target.slice(2)));
|
|
536
|
+
if (f) return f;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
return __nbcStatFile(path.join(pkgDir, sub))
|
|
541
|
+
|| __nbcStatFile(path.join(pkgDir, sub + ".js"))
|
|
542
|
+
|| __nbcStatFile(path.join(pkgDir, sub + ".cjs"))
|
|
543
|
+
|| __nbcStatFile(path.join(pkgDir, sub + ".mjs"))
|
|
544
|
+
|| __nbcStatFile(path.join(pkgDir, sub + ".json"))
|
|
545
|
+
|| __nbcStatFile(path.join(pkgDir, sub, "index.js"))
|
|
546
|
+
|| __nbcStatFile(path.join(pkgDir, sub, "index.cjs"));
|
|
547
|
+
}
|
|
548
|
+
function __nbcResolvePackage(request, fromDir) {
|
|
549
|
+
let pkgName, sub = "";
|
|
550
|
+
if (request[0] === "@") {
|
|
551
|
+
const m = request.match(/^(@[^/]+\\/[^/]+)(?:\\/(.+))?$/);
|
|
552
|
+
if (!m) return null;
|
|
553
|
+
pkgName = m[1]; sub = m[2] || "";
|
|
554
|
+
} else {
|
|
555
|
+
const idx = request.indexOf("/");
|
|
556
|
+
if (idx === -1) { pkgName = request; }
|
|
557
|
+
else { pkgName = request.slice(0, idx); sub = request.slice(idx + 1); }
|
|
558
|
+
}
|
|
559
|
+
let dir = fromDir;
|
|
560
|
+
while (dir.length > 1) {
|
|
561
|
+
const pkgDir = path.join(dir, "node_modules", pkgName);
|
|
562
|
+
if (fs.existsSync(pkgDir)) {
|
|
563
|
+
let pkgJson = null;
|
|
564
|
+
const pkgJsonPath = path.join(pkgDir, "package.json");
|
|
565
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
566
|
+
try { pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8")); } catch {}
|
|
567
|
+
}
|
|
568
|
+
const resolved = sub
|
|
569
|
+
? __nbcResolveSubpath(pkgDir, pkgJson, sub)
|
|
570
|
+
: __nbcResolveMain(pkgDir, pkgJson);
|
|
571
|
+
if (resolved) return resolved;
|
|
572
|
+
}
|
|
573
|
+
const parent = path.dirname(dir);
|
|
574
|
+
if (parent === dir) break;
|
|
575
|
+
dir = parent;
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
580
|
+
try {
|
|
581
|
+
return __nbcOrigResolveFilename.call(this, request, parent, isMain, options);
|
|
582
|
+
} catch (err) {
|
|
583
|
+
// Only attempt fallback for bare package specifiers
|
|
584
|
+
if (typeof request !== "string" || request[0] === "." || request[0] === "/" || /^[a-z]+:/.test(request)) {
|
|
585
|
+
throw err;
|
|
586
|
+
}
|
|
587
|
+
const fromDir = parent && parent.filename ? path.dirname(parent.filename) : process.cwd();
|
|
588
|
+
const resolved = __nbcResolvePackage(request, fromDir);
|
|
589
|
+
if (resolved) return resolved;
|
|
590
|
+
throw err;
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
|
|
418
594
|
const nextConfig = ${configMatch[1]};
|
|
419
595
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig);
|
|
420
596
|
|
|
@@ -433,7 +609,20 @@ async function extractAssets() {
|
|
|
433
609
|
if (fs.existsSync(fullPath)) continue;
|
|
434
610
|
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
435
611
|
const embedded = assetMap.get(urlPath);
|
|
436
|
-
if (embedded)
|
|
612
|
+
if (!embedded) continue;
|
|
613
|
+
// Server chunks may contain __NBC_BASE__ placeholders injected at
|
|
614
|
+
// build time by rewriteTurbopackAliases. Substitute the real baseDir
|
|
615
|
+
// before writing so bun resolves the absolute paths at chunk load.
|
|
616
|
+
if (diskPath.startsWith(".next/server/")) {
|
|
617
|
+
const text = await Bun.file(embedded).text();
|
|
618
|
+
if (text.indexOf("__NBC_BASE__") !== -1) {
|
|
619
|
+
await Bun.write(fullPath, text.split("__NBC_BASE__").join(baseDir));
|
|
620
|
+
n++;
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
await Bun.write(fullPath, Bun.file(embedded));
|
|
625
|
+
n++;
|
|
437
626
|
}
|
|
438
627
|
if (n > 0) console.log(\`Extracted \${n} assets\`);
|
|
439
628
|
}
|
package/dist/index.js
CHANGED