mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-05-05 01:32:35 +00:00
157 lines
4.6 KiB
JavaScript
157 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import {
|
|
cpSync,
|
|
existsSync,
|
|
lstatSync,
|
|
mkdirSync,
|
|
readFileSync,
|
|
rmSync,
|
|
writeFileSync,
|
|
} from "node:fs";
|
|
import { basename, dirname, join, relative } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
const ROOT = join(__dirname, "..");
|
|
|
|
const STANDALONE_DIR = join(ROOT, ".next", "standalone");
|
|
const ELECTRON_STANDALONE_DIR = join(ROOT, ".next", "electron-standalone");
|
|
const STATIC_SRC = join(ROOT, ".next", "static");
|
|
const STATIC_DEST = join(ELECTRON_STANDALONE_DIR, ".next", "static");
|
|
const PUBLIC_SRC = join(ROOT, "public");
|
|
const PUBLIC_DEST = join(ELECTRON_STANDALONE_DIR, "public");
|
|
|
|
function resolveStandaloneBundleDir() {
|
|
const directServer = join(STANDALONE_DIR, "server.js");
|
|
if (existsSync(directServer)) {
|
|
return STANDALONE_DIR;
|
|
}
|
|
|
|
const nestedCandidates = [
|
|
join(STANDALONE_DIR, "projects", "OmniRoute"),
|
|
join(STANDALONE_DIR, basename(ROOT)),
|
|
];
|
|
|
|
for (const candidate of nestedCandidates) {
|
|
if (existsSync(join(candidate, "server.js"))) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
throw new Error(
|
|
`Standalone server bundle not found in ${STANDALONE_DIR}. Run \`npm run build\` first.`
|
|
);
|
|
}
|
|
|
|
function createPathPattern(filePath) {
|
|
return filePath
|
|
.replace(/\\/g, "/")
|
|
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
.replace(/\//g, "[\\\\/]");
|
|
}
|
|
|
|
function sanitizeBuildPaths(bundleDir) {
|
|
const buildRoot = ROOT.replace(/\\/g, "/");
|
|
const bundleRoot = bundleDir.replace(/\\/g, "/");
|
|
const replacements = [buildRoot, bundleRoot];
|
|
const targets = [
|
|
join(ELECTRON_STANDALONE_DIR, "server.js"),
|
|
join(ELECTRON_STANDALONE_DIR, ".next", "required-server-files.json"),
|
|
];
|
|
|
|
for (const filePath of targets) {
|
|
if (!existsSync(filePath)) continue;
|
|
|
|
let content = readFileSync(filePath, "utf8");
|
|
let updated = content;
|
|
|
|
for (const original of replacements) {
|
|
updated = updated.replace(new RegExp(createPathPattern(original), "g"), ".");
|
|
}
|
|
|
|
if (updated !== content) {
|
|
writeFileSync(filePath, updated, "utf8");
|
|
}
|
|
}
|
|
}
|
|
|
|
function ensurePackage(pkgPath, sourcePath) {
|
|
if (existsSync(pkgPath) || !existsSync(sourcePath)) return;
|
|
mkdirSync(dirname(pkgPath), { recursive: true });
|
|
cpSync(sourcePath, pkgPath, { recursive: true, dereference: true });
|
|
}
|
|
|
|
function removeGeneratedElectronArtifacts() {
|
|
const generatedDirs = [join(ELECTRON_STANDALONE_DIR, "electron", "dist-electron")];
|
|
|
|
for (const dir of generatedDirs) {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
function assertBundleIsPackagable(bundleDir) {
|
|
const nodeModulesPath = join(bundleDir, "node_modules");
|
|
if (!existsSync(nodeModulesPath)) return;
|
|
|
|
if (lstatSync(nodeModulesPath).isSymbolicLink()) {
|
|
throw new Error(
|
|
[
|
|
"Next standalone emitted app/node_modules as a symlink.",
|
|
"electron-builder preserves extraResources symlinks, which would make the packaged app",
|
|
"depend on the original build machine path at runtime.",
|
|
"",
|
|
`Offending path: ${nodeModulesPath}`,
|
|
"Use a real node_modules directory in the build worktree before packaging Electron.",
|
|
].join("\n")
|
|
);
|
|
}
|
|
}
|
|
|
|
function logContextualError(error) {
|
|
const message = error instanceof Error ? error.message : String(error);
|
|
console.error(`[electron] failed to prepare standalone bundle: ${message}`);
|
|
process.exitCode = 1;
|
|
}
|
|
|
|
process.on("uncaughtException", logContextualError);
|
|
|
|
const bundleDir = resolveStandaloneBundleDir();
|
|
assertBundleIsPackagable(bundleDir);
|
|
|
|
rmSync(ELECTRON_STANDALONE_DIR, { recursive: true, force: true });
|
|
mkdirSync(ELECTRON_STANDALONE_DIR, { recursive: true });
|
|
|
|
cpSync(bundleDir, ELECTRON_STANDALONE_DIR, {
|
|
recursive: true,
|
|
dereference: true,
|
|
});
|
|
|
|
sanitizeBuildPaths(bundleDir);
|
|
|
|
if (existsSync(STATIC_SRC)) {
|
|
mkdirSync(dirname(STATIC_DEST), { recursive: true });
|
|
cpSync(STATIC_SRC, STATIC_DEST, { recursive: true, dereference: true });
|
|
}
|
|
|
|
if (existsSync(PUBLIC_SRC)) {
|
|
cpSync(PUBLIC_SRC, PUBLIC_DEST, { recursive: true, dereference: true });
|
|
}
|
|
|
|
removeGeneratedElectronArtifacts();
|
|
|
|
ensurePackage(
|
|
join(ELECTRON_STANDALONE_DIR, "node_modules", "@swc", "helpers"),
|
|
join(ROOT, "node_modules", "@swc", "helpers")
|
|
);
|
|
|
|
// removed better-sqlite3 to ensure ABI compatibility via electron-builder
|
|
const bundledSqlite = join(ELECTRON_STANDALONE_DIR, "node_modules", "better-sqlite3");
|
|
if (existsSync(bundledSqlite)) {
|
|
rmSync(bundledSqlite, { recursive: true, force: true });
|
|
}
|
|
|
|
console.log(
|
|
`[electron] prepared standalone bundle: ${relative(ROOT, ELECTRON_STANDALONE_DIR) || "."}`
|
|
);
|