UNPKG

lynkr

Version:

Self-hosted LLM gateway and tier-routing proxy for Claude Code, Cursor, and Codex. Routes across Ollama, AWS Bedrock, OpenRouter, Databricks, Azure OpenAI, llama.cpp, and LM Studio with prompt caching, MCP tools, and 60-80% cost savings.

98 lines (88 loc) 2.92 kB
#!/usr/bin/env node /** * Native module ABI guard (postinstall). * * better-sqlite3 (and the other native optionalDependencies) are compiled * against a specific Node ABI. When Node is upgraded, the prebuilt/compiled * binary stops loading with: * * "was compiled against a different Node.js version using * NODE_MODULE_VERSION 115. This version of Node.js requires * NODE_MODULE_VERSION 141." * * The failure is silent at runtime — telemetry, request logs, and the memory * store all sit behind try/catch and simply go empty. This probe detects the * mismatch and rebuilds the native modules so it self-heals on `npm install`. * * It is intentionally best-effort: it NEVER exits non-zero, so it can't break * `npm install` on machines without a build toolchain (the modules are * optional and the app degrades gracefully without them). */ const { execSync } = require("child_process"); // Native optionalDependencies that are ABI-sensitive. If Node changed, all of // them are stale, so we rebuild the set in one pass. const NATIVE_DEPS = [ "better-sqlite3", "hnswlib-node", "tree-sitter", "tree-sitter-javascript", "tree-sitter-python", "tree-sitter-typescript", ]; function log(msg) { console.log(`[check-native] ${msg}`); } /** * Probe better-sqlite3 — the canary. `require()` alone is not enough: the * native addon only loads when a Database is instantiated. * @returns {"ok"|"absent"|"mismatch"} */ function probe() { let Database; try { Database = require("better-sqlite3"); } catch (err) { if (err && err.code === "MODULE_NOT_FOUND") return "absent"; return "mismatch"; } try { const db = new Database(":memory:"); db.close(); return "ok"; } catch (err) { if (/NODE_MODULE_VERSION|different Node\.js version|invalid ELF|dlopen|\.node/i.test(err.message || "")) { return "mismatch"; } // Some other instantiation error — not an ABI issue we can fix by rebuild. return "ok"; } } function main() { const status = probe(); if (status === "absent") { // Optional dependency not installed (e.g. build skipped). Nothing to do. return; } if (status === "ok") { return; } log("native module ABI mismatch detected (Node was likely upgraded). Rebuilding native modules…"); try { execSync(`npm rebuild ${NATIVE_DEPS.join(" ")}`, { stdio: "inherit" }); } catch { log("rebuild did not complete (a build toolchain may be missing). Continuing — native features will be disabled until you run: npm rebuild better-sqlite3"); return; } // Re-probe to report the outcome. if (probe() === "ok") { log("native modules rebuilt successfully."); } else { log("native modules still not loadable after rebuild. Run `npm rebuild better-sqlite3` manually."); } } try { main(); } catch (err) { // Never fail the install. log(`skipped (${err.message})`); }