| #!/usr/bin/env node
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| import { copyFileSync, cpSync, existsSync, mkdirSync, readdirSync } from "node:fs";
|
| import { dirname, join } from "node:path";
|
| import { fileURLToPath } from "node:url";
|
|
|
| import { PUBLISHED_BUILD_ARCH, PUBLISHED_BUILD_PLATFORM } from "./native-binary-compat.mjs";
|
| import { hasStandaloneAppBundle, isTermux } from "./postinstallSupport.mjs";
|
|
|
| const __filename = fileURLToPath(import.meta.url);
|
| const __dirname = dirname(__filename);
|
| const ROOT = join(__dirname, "..", "..");
|
|
|
| const appBinary = join(
|
| ROOT,
|
| "dist",
|
| "node_modules",
|
| "better-sqlite3",
|
| "build",
|
| "Release",
|
| "better_sqlite3.node"
|
| );
|
| const rootBinary = join(
|
| ROOT,
|
| "node_modules",
|
| "better-sqlite3",
|
| "build",
|
| "Release",
|
| "better_sqlite3.node"
|
| );
|
|
|
| async function fixBetterSqliteBinary() {
|
| if (!existsSync(join(ROOT, "dist", "node_modules", "better-sqlite3"))) {
|
| return;
|
| }
|
|
|
| const platformMatch =
|
| process.platform === PUBLISHED_BUILD_PLATFORM && process.arch === PUBLISHED_BUILD_ARCH;
|
|
|
| if (platformMatch) {
|
| try {
|
| process.dlopen({ exports: {} }, appBinary);
|
| return;
|
| } catch (err) {
|
| console.warn(` ⚠️ Bundled binary incompatible despite platform match: ${err.message}`);
|
| }
|
| }
|
|
|
| console.log(`\n 🔧 Fixing better-sqlite3 binary for ${process.platform}-${process.arch}...`);
|
|
|
| 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");
|
| return;
|
| } catch (err) {
|
| console.warn(` ⚠️ Copied binary failed to load: ${err.message}`);
|
| }
|
| }
|
|
|
| console.log(" 📥 Attempting to download prebuilt binary via node-pre-gyp...");
|
| try {
|
| const { execSync } = await import("node:child_process");
|
| const preGypBin = join(
|
| ROOT,
|
| "dist",
|
| "node_modules",
|
| ".bin",
|
| process.platform === "win32" ? "node-pre-gyp.cmd" : "node-pre-gyp"
|
| );
|
| const preGypFallback = join(
|
| ROOT,
|
| "dist",
|
| "node_modules",
|
| "@mapbox",
|
| "node-pre-gyp",
|
| "bin",
|
| "node-pre-gyp"
|
| );
|
| const preGypCmd = existsSync(preGypBin) ? preGypBin : preGypFallback;
|
|
|
| if (existsSync(preGypCmd)) {
|
| execSync(`"${process.execPath}" "${preGypCmd}" install --fallback-to-build=false`, {
|
| cwd: join(ROOT, "dist", "node_modules", "better-sqlite3"),
|
| stdio: "inherit",
|
| timeout: 60_000,
|
| });
|
| mkdirSync(dirname(appBinary), { recursive: true });
|
|
|
| try {
|
| process.dlopen({ exports: {} }, appBinary);
|
| console.log(" ✅ Prebuilt binary downloaded and loaded successfully!\n");
|
| return;
|
| } catch (loadErr) {
|
| console.warn(` ⚠️ Downloaded binary failed to load: ${loadErr.message}`);
|
| }
|
| } else {
|
| console.warn(" ⚠️ node-pre-gyp not found, skipping prebuilt download.");
|
| }
|
| } catch (err) {
|
| console.warn(` ⚠️ node-pre-gyp download failed: ${err.message.split("\n")[0]}`);
|
| }
|
|
|
| console.log(" ⚠️ Attempting npm rebuild (requires build tools)...");
|
|
|
| try {
|
| const { execSync } = await import("node:child_process");
|
|
|
|
|
| const isAndroid = process.platform === "android" || isTermux();
|
| const rebuildCmd = isAndroid
|
| ? "npm install better-sqlite3 --build-from-source --force"
|
| : "npm rebuild better-sqlite3";
|
|
|
| const env = { ...process.env };
|
| if (isAndroid) {
|
| env.GYP_DEFINES = "android_ndk_path=''";
|
| }
|
|
|
| execSync(rebuildCmd, {
|
| cwd: join(ROOT, "dist"),
|
| stdio: "inherit",
|
| timeout: isAndroid ? 600_000 : 300_000,
|
| env,
|
| });
|
|
|
| process.dlopen({ exports: {} }, appBinary);
|
| console.log(" ✅ Native module rebuilt successfully!\n");
|
| return;
|
| } catch (err) {
|
| const isTimeout = err.killed || err.signal === "SIGTERM";
|
| if (isTimeout) {
|
| const secs = isAndroid ? 600 : 300;
|
| console.warn(` ⚠️ npm rebuild timed out after ${secs}s.`);
|
| } else {
|
| console.warn(` ⚠️ npm rebuild failed: ${err.message}`);
|
| }
|
| }
|
|
|
| console.warn("\n ⚠️ Could not fix better-sqlite3 native module automatically.");
|
| console.warn(" The server may not start correctly.");
|
| console.warn(" Manual fix options:");
|
| if (process.platform === "win32") {
|
| console.warn(" Option A (easiest — no build tools needed):");
|
| console.warn(` cd "${join(ROOT, "dist", "node_modules", "better-sqlite3")}"`);
|
| console.warn(" npx @mapbox/node-pre-gyp install --fallback-to-build=false");
|
| console.warn(" Option B (requires Build Tools for Visual Studio):");
|
| console.warn(` cd "${join(ROOT, "dist")}" && npm rebuild better-sqlite3`);
|
| console.warn(" Install from: https://visualstudio.microsoft.com/visual-cpp-build-tools/");
|
| console.warn(" Also ensure Python is installed: https://python.org");
|
| } else if (process.platform === "darwin") {
|
| console.warn(` cd ${join(ROOT, "dist")} && npm rebuild better-sqlite3`);
|
| console.warn(" If build tools are missing: xcode-select --install");
|
| } else {
|
| console.warn(` cd ${join(ROOT, "dist")} && npm rebuild better-sqlite3`);
|
| }
|
| console.warn("");
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| async function fixWreqJsBinary() {
|
|
|
|
|
| if (process.platform === "android" || isTermux()) {
|
| console.log(
|
| " [postinstall] wreq-js: skipped on Termux/Android " +
|
| "(libgcc not available — OAuth TLS fingerprinting will use the fallback path)"
|
| );
|
| return;
|
| }
|
|
|
| const appWreqDir = join(ROOT, "dist", "node_modules", "wreq-js", "rust");
|
| const rootWreqDir = join(ROOT, "node_modules", "wreq-js", "rust");
|
|
|
| if (!existsSync(join(ROOT, "dist", "node_modules", "wreq-js"))) {
|
| return;
|
| }
|
|
|
| const binaryName = `wreq-js.${process.platform}-${process.arch}.node`;
|
| const appBinaryPath = join(appWreqDir, binaryName);
|
| const rootBinaryPath = join(rootWreqDir, binaryName);
|
|
|
|
|
| if (existsSync(appBinaryPath)) {
|
| try {
|
| process.dlopen({ exports: {} }, appBinaryPath);
|
| return;
|
| } catch (err) {
|
| console.warn(` ⚠️ wreq-js binary exists but failed to load: ${err.message}`);
|
| }
|
| }
|
|
|
| console.log(`\n 🔧 Fixing wreq-js binary for ${process.platform}-${process.arch}...`);
|
|
|
|
|
| if (existsSync(rootBinaryPath)) {
|
| try {
|
| mkdirSync(appWreqDir, { recursive: true });
|
| copyFileSync(rootBinaryPath, appBinaryPath);
|
| process.dlopen({ exports: {} }, appBinaryPath);
|
| console.log(" ✅ wreq-js native module fixed successfully!\n");
|
| return;
|
| } catch (err) {
|
| console.warn(` ⚠️ Copied wreq-js binary failed to load: ${err.message}`);
|
| }
|
| }
|
|
|
|
|
| if (existsSync(rootWreqDir)) {
|
| try {
|
| mkdirSync(appWreqDir, { recursive: true });
|
| const files = readdirSync(rootWreqDir);
|
| for (const file of files) {
|
| if (file.endsWith(".node")) {
|
| copyFileSync(join(rootWreqDir, file), join(appWreqDir, file));
|
| }
|
| }
|
| if (existsSync(appBinaryPath)) {
|
| process.dlopen({ exports: {} }, appBinaryPath);
|
| console.log(" ✅ wreq-js native module fixed (full copy) successfully!\n");
|
| return;
|
| }
|
| } catch (err) {
|
| console.warn(` ⚠️ wreq-js full copy failed: ${err.message}`);
|
| }
|
| }
|
|
|
|
|
| console.log(" 📥 Attempting npm rebuild wreq-js...");
|
| try {
|
| const { execSync } = await import("node:child_process");
|
| execSync("npm rebuild wreq-js", {
|
| cwd: join(ROOT, "dist"),
|
| stdio: "inherit",
|
| timeout: 120_000,
|
| });
|
| if (existsSync(appBinaryPath)) {
|
| process.dlopen({ exports: {} }, appBinaryPath);
|
| console.log(" ✅ wreq-js native module rebuilt successfully!\n");
|
| return;
|
| }
|
| } catch (err) {
|
| console.warn(` ⚠️ wreq-js rebuild failed: ${err.message}`);
|
| }
|
|
|
| console.warn(
|
| `\n ⚠️ Could not fix wreq-js native module for ${process.platform}-${process.arch}.`
|
| );
|
| console.warn(" OAuth-based providers (Codex, Cursor, etc.) may not work.");
|
| console.warn(` Manual fix: cd ${join(ROOT, "dist")} && npm install wreq-js --no-save\n`);
|
| }
|
|
|
| async function ensureSwcHelpers() {
|
| if (!hasStandaloneAppBundle(ROOT)) {
|
| return;
|
| }
|
|
|
| const swcHelpersApp = join(ROOT, "dist", "node_modules", "@swc", "helpers");
|
| const swcHelpersRoot = join(ROOT, "node_modules", "@swc", "helpers");
|
|
|
| if (existsSync(swcHelpersApp)) {
|
| return;
|
| }
|
|
|
| if (existsSync(swcHelpersRoot)) {
|
| try {
|
| const { cpSync } = await import("node:fs");
|
| mkdirSync(join(ROOT, "dist", "node_modules", "@swc"), { recursive: true });
|
| cpSync(swcHelpersRoot, swcHelpersApp, { recursive: true });
|
| console.log(" ✅ @swc/helpers copied to standalone dist/node_modules.\n");
|
| } catch (err) {
|
| console.warn(` ⚠️ Could not copy @swc/helpers: ${err.message}`);
|
| console.warn(
|
| " Try manually: cp -r node_modules/@swc/helpers dist/node_modules/@swc/helpers\n"
|
| );
|
| }
|
| return;
|
| }
|
|
|
| console.warn(" ⚠️ @swc/helpers not found in root node_modules either.");
|
| console.warn(" Try: npm install --save-exact @swc/helpers@0.5.19\n");
|
| }
|
|
|
| async function syncProjectEnv() {
|
| try {
|
| const { syncEnv } = await import("./sync-env.mjs");
|
| syncEnv({ rootDir: ROOT });
|
| } catch (err) {
|
| console.warn(` ⚠️ .env sync skipped: ${err.message}`);
|
| }
|
| }
|
|
|
| await fixBetterSqliteBinary();
|
| await fixWreqJsBinary();
|
| await ensureSwcHelpers();
|
| await syncProjectEnv();
|
|
|
|
|
|
|
| try {
|
| await import("../postinstall.mjs");
|
| } catch {
|
|
|
| }
|
|
|