mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix(build): Turbopack/Docker build — externalize sqlite-vec .so + sync mitm manager stub
The Docker image build (`docker compose --profile cli build`) runs `next build` with OMNIROUTE_USE_TURBOPACK=1 and failed with two Turbopack errors that the webpack-based VM build never hits — which is why the VM deploy validated but the Docker build errored (#3066). The reporter's log was truncated before the real errors; reproducing `OMNIROUTE_USE_TURBOPACK=1 npm run build` locally surfaced them: 1. node_modules/sqlite-vec-linux-x64/vec0.so — "Unknown module type". sqlite-vec ships a native vec0.so loaded at runtime via createRequire(); Turbopack tried to bundle the .so. Fixed by adding "sqlite-vec" to serverExternalPackages, exactly like better-sqlite3. 2. /api/tools/agent-bridge/state statically imports getAllAgentsStatus from @/mitm/manager, which next.config aliases to manager.stub.ts for the Turbopack build. The stub did not export getAllAgentsStatus → "Export getAllAgentsStatus doesn't exist in target module". Added the export (throws like the other heavy ops — MITM/agent-bridge is non-functional in the bundled build anyway). Tests (tests/unit/next-config.test.ts): - assert sqlite-vec is in serverExternalPackages. - new guard: manager.stub.ts must export every name statically imported from @/mitm/manager across src/app (catches stub/manager drift — would have caught this). Verified: OMNIROUTE_USE_TURBOPACK=1 npm run build → EXIT 0 (was: Build error occurred); webpack build → EXIT 0; typecheck:core / check:cycles / lint clean. Fixes #3066
This commit is contained in:
@@ -74,6 +74,13 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- **build:** Docker image build (`docker compose --profile cli build`, which runs
|
||||
`next build` with Turbopack) no longer errors. Two Turbopack-only failures were
|
||||
fixed: `sqlite-vec` is now externalized so Turbopack stops trying to bundle its
|
||||
native `vec0.so` ("Unknown module type"), and `manager.stub.ts` now exports
|
||||
`getAllAgentsStatus` (statically imported by `/api/tools/agent-bridge/state` — the
|
||||
missing export aborted the build). The webpack-based VM build was unaffected, which
|
||||
is why the deploy validated while the Docker build errored. (#3066 — thanks @freefrank)
|
||||
- **codex/providers:** `POST /api/providers/[id]/refresh` (the manual/auto "refresh
|
||||
token" endpoint) no longer rotates rotating-refresh providers (Codex/OpenAI share
|
||||
one Auth0 `client_id`). This was the last unguarded proactive-refresh entry point:
|
||||
|
||||
@@ -141,6 +141,11 @@ const nextConfig = {
|
||||
"thread-stream",
|
||||
"pino-abstract-transport",
|
||||
"better-sqlite3",
|
||||
// sqlite-vec ships a native vec0.so loaded at runtime via createRequire().
|
||||
// Turbopack otherwise tries to bundle the .so and fails with "Unknown module
|
||||
// type"; externalizing it keeps the require at runtime (like better-sqlite3).
|
||||
// See issue #3066.
|
||||
"sqlite-vec",
|
||||
"node-machine-id",
|
||||
"keytar",
|
||||
"wreq-js",
|
||||
|
||||
@@ -13,6 +13,13 @@ export const clearCachedPassword = () => {};
|
||||
export const getMitmStatus = async () => {
|
||||
throw new Error(STUB_ERROR);
|
||||
};
|
||||
// Statically imported by /api/tools/agent-bridge/state — the stub must export it or
|
||||
// the Turbopack build fails ("Export getAllAgentsStatus doesn't exist"). MITM/agent
|
||||
// bridge needs host-level access and is non-functional in the bundled build anyway,
|
||||
// so this throws like the other heavy ops. See issue #3066.
|
||||
export const getAllAgentsStatus = (): never => {
|
||||
throw new Error(STUB_ERROR);
|
||||
};
|
||||
export const startMitm = async (
|
||||
_apiKey: string,
|
||||
_sudoPassword: string,
|
||||
|
||||
@@ -83,6 +83,9 @@ test("next config declares Turbopack aliases, runtime assets and server external
|
||||
for (const packageName of [
|
||||
"thread-stream",
|
||||
"better-sqlite3",
|
||||
// sqlite-vec ships a native vec0.so loaded at runtime; without externalizing it
|
||||
// the Turbopack build fails with "Unknown module type" on the .so (issue #3066).
|
||||
"sqlite-vec",
|
||||
"wreq-js",
|
||||
"fs",
|
||||
"path",
|
||||
@@ -95,6 +98,66 @@ test("next config declares Turbopack aliases, runtime assets and server external
|
||||
}
|
||||
});
|
||||
|
||||
// ── manager.stub.ts must cover every static @/mitm/manager import (issue #3066) ──
|
||||
//
|
||||
// next.config aliases `@/mitm/manager` → `manager.stub.ts` for the Turbopack build
|
||||
// (Docker uses Turbopack; the VM/webpack build uses the real module, which is why the
|
||||
// VM validated while Docker's `npm run build` errored). Any route that statically
|
||||
// imports a name the stub doesn't export breaks the Turbopack build with
|
||||
// "Export X doesn't exist in target module". This guard fails on that drift — it is
|
||||
// what would have caught the missing getAllAgentsStatus export in #3066.
|
||||
|
||||
test("manager.stub.ts exports every name statically imported from @/mitm/manager", async () => {
|
||||
const fs = await import("node:fs");
|
||||
const appDir = path.join(process.cwd(), "src", "app");
|
||||
|
||||
// Collect named imports from `... from "@/mitm/manager"` (NOT manager.runtime, which
|
||||
// is loaded via dynamic import() and resolves to the real module at runtime).
|
||||
const collectImports = (dir: string, acc: Set<string>): void => {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
collectImports(full, acc);
|
||||
continue;
|
||||
}
|
||||
if (!/\.(ts|tsx)$/.test(entry.name)) continue;
|
||||
const src = fs.readFileSync(full, "utf-8");
|
||||
const re = /import\s*\{([^}]*)\}\s*from\s*["']@\/mitm\/manager["']/g;
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = re.exec(src)) !== null) {
|
||||
for (const raw of m[1].split(",")) {
|
||||
const name = raw.trim().split(/\s+as\s+/)[0].trim();
|
||||
if (name) acc.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const imported = new Set<string>();
|
||||
collectImports(appDir, imported);
|
||||
|
||||
// Sanity: the suite is meaningless if it finds nothing to check.
|
||||
assert.ok(imported.size > 0, "expected at least one static @/mitm/manager import in src/app");
|
||||
assert.ok(imported.has("getAllAgentsStatus"), "fixture: agent-bridge/state imports getAllAgentsStatus");
|
||||
|
||||
const stubSrc = fs.readFileSync(
|
||||
path.join(process.cwd(), "src", "mitm", "manager.stub.ts"),
|
||||
"utf-8"
|
||||
);
|
||||
const stubExports = new Set(
|
||||
[...stubSrc.matchAll(/export\s+(?:const|function|async\s+function)\s+([A-Za-z0-9_]+)/g)].map(
|
||||
(m) => m[1]
|
||||
)
|
||||
);
|
||||
|
||||
const missing = [...imported].filter((name) => !stubExports.has(name));
|
||||
assert.deepEqual(
|
||||
missing,
|
||||
[],
|
||||
`manager.stub.ts is missing exports statically imported by routes: ${missing.join(", ")}`
|
||||
);
|
||||
});
|
||||
|
||||
test("next-intl webpack hook preserves caller config and filters known extractor warnings", async () => {
|
||||
const { default: nextConfig } = await loadNextConfig("webpack-pass-through");
|
||||
const config: any = {
|
||||
|
||||
Reference in New Issue
Block a user