Files
OmniRoute/scripts/postinstall.mjs
T
diegosouzapw 943a9374b4
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix: permanent @swc/helpers MODULE_NOT_FOUND fix (#crash)
prepublish.mjs: explicitly copy @swc/helpers into standalone app/node_modules
before packaging. npm tarball will always include it.

postinstall.mjs: fallback copy of @swc/helpers from root node_modules into
app/node_modules/@swc/ when missing after npm install -g.

Fixes server crash after npm install -g omniroute.
2026-03-12 10:42:59 -03:00

141 lines
4.8 KiB
JavaScript

#!/usr/bin/env node
/**
* OmniRoute — Postinstall Native Module Fix
*
* The npm package ships with a Next.js standalone build that includes
* better-sqlite3 compiled for the build platform (Linux x64) inside
* app/node_modules/. However, npm also installs better-sqlite3 as a
* top-level dependency (in the root node_modules/), correctly compiled
* for the user's platform.
*
* This script copies the correctly-built native binary from the root
* into the standalone app directory — no rebuild or build tools needed.
*
* Fixes: https://github.com/diegosouzapw/OmniRoute/issues/129
* Fixes: https://github.com/diegosouzapw/OmniRoute/issues/321
*/
import { existsSync, copyFileSync, mkdirSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { PUBLISHED_BUILD_PLATFORM, PUBLISHED_BUILD_ARCH } from "./native-binary-compat.mjs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const ROOT = join(__dirname, "..");
const appBinary = join(
ROOT,
"app",
"node_modules",
"better-sqlite3",
"build",
"Release",
"better_sqlite3.node"
);
const rootBinary = join(
ROOT,
"node_modules",
"better-sqlite3",
"build",
"Release",
"better_sqlite3.node"
);
if (!existsSync(join(ROOT, "app", "node_modules", "better-sqlite3"))) {
process.exit(0);
}
const platformMatch =
process.platform === PUBLISHED_BUILD_PLATFORM && process.arch === PUBLISHED_BUILD_ARCH;
if (platformMatch) {
try {
process.dlopen({ exports: {} }, appBinary);
process.exit(0);
} catch (err) {
console.warn(` ⚠️ Bundled binary incompatible despite platform match: ${err.message}`);
}
}
console.log(`\n 🔧 Fixing better-sqlite3 binary for ${process.platform}-${process.arch}...`);
// Strategy 1: Copy the correctly-built binary from root node_modules
if (existsSync(rootBinary)) {
try {
mkdirSync(dirname(appBinary), { recursive: true });
copyFileSync(rootBinary, appBinary);
} catch (err) {
console.warn(` ⚠️ Failed to copy binary: ${err.message}`);
}
try {
process.dlopen({ exports: {} }, appBinary);
console.log(" ✅ Native module fixed successfully!\n");
process.exit(0);
} catch (err) {
console.warn(` ⚠️ Copied binary failed to load: ${err.message}`);
}
}
// Strategy 2: Fall back to npm rebuild (may work if build tools are available)
console.log(" ⚠️ Root binary not available or incompatible, attempting npm rebuild...");
try {
const { execSync } = await import("node:child_process");
execSync("npm rebuild better-sqlite3", {
cwd: join(ROOT, "app"),
stdio: "inherit",
timeout: 120_000,
});
process.dlopen({ exports: {} }, appBinary);
console.log(" ✅ Native module rebuilt successfully!\n");
process.exit(0);
} catch (err) {
const isTimeout = err.killed || err.signal === "SIGTERM";
if (isTimeout) {
console.warn(" ⚠️ npm rebuild timed out after 120s.");
} else {
console.warn(` ⚠️ npm rebuild failed: ${err.message}`);
}
}
// If nothing worked, warn but don't fail the install — let the package stay
// installed so users can fix manually or use the pre-flight check in the CLI
console.warn(" ⚠️ Could not fix better-sqlite3 native module automatically.");
console.warn(" The server may not start correctly.");
console.warn(" Try manually:");
console.warn(` cd ${join(ROOT, "app")} && npm rebuild better-sqlite3`);
if (process.platform === "darwin") {
console.warn(" If build tools are missing: xcode-select --install");
}
console.warn("");
// ── @swc/helpers fix ────────────────────────────────────────────────────────
// Next.js standalone tracer doesn't always include @swc/helpers in app/node_modules/,
// causing a MODULE_NOT_FOUND crash at runtime. Copy it from root node_modules if needed.
const swcHelpersApp = join(ROOT, "app", "node_modules", "@swc", "helpers");
const swcHelpersRoot = join(ROOT, "node_modules", "@swc", "helpers");
if (!existsSync(swcHelpersApp)) {
if (existsSync(swcHelpersRoot)) {
try {
const { cpSync } = await import("node:fs");
mkdirSync(join(ROOT, "app", "node_modules", "@swc"), { recursive: true });
cpSync(swcHelpersRoot, swcHelpersApp, { recursive: true });
console.log(" ✅ @swc/helpers copied to standalone app/node_modules.\n");
} catch (err) {
console.warn(` ⚠️ Could not copy @swc/helpers: ${err.message}`);
console.warn(
" Try manually: cp -r node_modules/@swc/helpers app/node_modules/@swc/helpers\n"
);
}
} else {
console.warn(" ⚠️ @swc/helpers not found in root node_modules either.");
console.warn(" Try: npm install --save-exact @swc/helpers@0.5.19\n");
}
}