Files
OmniRoute/tests/unit/production-build-module-integrity.test.ts
Diego Rodrigues de Sa e Souza 37d70785c7 fix(build): repair broken production build, red lint gate and SWR crash (#10198)
The Build CI job is advisory, so eight module-level defects from eight
different PRs accumulated on release/v3.8.50 until `npm run build` failed
with 7 Turbopack errors and `npm run lint` with 14.

Build (link-time):
- modelSelectModalHelpers.ts: a lost `}` swallowed PROVIDER_TEST_CHUNK_SIZE
  into isProviderModelHidden's body (#9011).
- videoGeneration.ts: handleFalVideoGeneration imported twice; the standalone
  falHandler.ts is superseded by the provider-neutral mediaGeneration/fal.ts
  and is removed here (#9982 over #9969).
- catalog.ts: re-exported and called the injectable SWR policy that #9199
  deliberately replaced with a fixed 30s bound. Fixed on the consumer side —
  restoring the accessor would resurrect the unbounded window #9199 removed
  after measuring a 41s catalog build in production.
- tinycmsSigner.ts: generated wasm-bindgen glue kept a sidecar
  `new URL('wasm_signer_bg.wasm', import.meta.url)` that no file backs;
  Turbopack resolves it statically. The module ships inlined as WASM_BASE64
  and the only caller always passes it explicitly (#8736/#10087).
- conolDiscovery.ts: imported getProviderOutboundGuard from outboundUrlGuard,
  which does not export it. Fixed on the consumer side: outboundUrlGuard.ts is
  loaded by the packaged CLI without a tsconfig, so it must stay free of
  `@/`-aliased imports (#7682).

Runtime (the build never caught this one):
- catalogCache.ts::scheduleBackgroundRefresh had two dangling statements
  referencing undeclared `inFlight`/`promise`, so EVERY stale-while-revalidate
  read threw a ReferenceError. Surfaced by realigning the #8728 suite, which
  #9199 left asserting a removed contract.

Lint:
- driverFactory.test.ts: a case inserted between the preceding test's `finally`
  and its `});` left the file unparseable, so the SQLite driver-cascade suite
  (26 tests) had not run since 2026-08-11 (#9173).
- providerModelsConfig.ts: imported an executor directly, crossing the G14
  boundary; routed through a new open-sse/services/zaiWebCredentials.ts (#8451).
- image-combo.test.ts: 11 `any` violations, now typed (#9499).

Validation: npm run build exit 0, npm run lint clean, typecheck:core clean,
41/41 tests green across the affected suites.

Refs #9011 #9982 #9199 #8728 #8736 #10087 #8974 #9173 #8451 #9499

Co-authored-by: backryun <bakryun0718@proton.me>
2026-08-12 15:58:40 -03:00

143 lines
7.1 KiB
TypeScript

/**
* Regression guard for the broken Turbopack production build on release/v3.8.50.
*
* Six independent module-level defects, each from a different PR, made `npm run build`
* fail. Most are *link-time* errors, so those cases are expressed as "this module must be
* importable / statically resolvable" rather than as behavioral assertions:
*
* 1. src/shared/components/modelSelectModalHelpers.ts — a lost `}` (#9011) left
* `export const PROVIDER_TEST_CHUNK_SIZE` inside a function body.
* 2. open-sse/handlers/videoGeneration.ts — `handleFalVideoGeneration` imported
* twice from two different modules (#9982 landed on top of #9969).
* 3. src/app/api/v1/models/catalog.ts — re-exported three SWR symbols that #9199
* deliberately removed from ./catalogCache when it replaced #8728's injectable
* policy with a fixed 30 s bound. The consumer was never updated.
* 4. src/app/api/v1/models/catalogCache.ts — the same PR left two dangling statements
* referencing undeclared `inFlight` / `promise`, so every stale-while-revalidate
* read threw a ReferenceError at RUNTIME (this one the build never caught).
* 5. open-sse/executors/tinycmsSigner.ts — generated wasm-bindgen glue kept a
* `new URL('wasm_signer_bg.wasm', import.meta.url)` default that no file backs.
* 6. src/app/api/providers/[id]/models/conolDiscovery.ts — imported
* `getProviderOutboundGuard` from ./outboundUrlGuard, which does not export it (#8974).
*/
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import path from "node:path";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
test("modelSelectModalHelpers exports survive isProviderModelHidden (#9011 missing brace)", async () => {
const helpers = await import("@/shared/components/modelSelectModalHelpers");
// The missing `}` swallowed everything after isProviderModelHidden into its body,
// so this constant stopped being a module-level export.
assert.equal(helpers.PROVIDER_TEST_CHUNK_SIZE, 3);
const hidden = helpers.parseHiddenModelsByProvider({ openai: ["gpt-4o"] });
assert.equal(helpers.isProviderModelHidden(hidden, "openai", "gpt-4o"), true);
assert.equal(helpers.isProviderModelHidden(hidden, "openai", "gpt-4o-mini"), false);
assert.equal(helpers.isProviderModelHidden(hidden, "anthropic", "gpt-4o"), false);
});
test("videoGeneration handler links with a single handleFalVideoGeneration binding (#9982)", async () => {
// A duplicate import binding is an ESM early SyntaxError, so the import itself is
// the assertion. The Fal video path must resolve to the provider-neutral module
// that #9982 added (it also covers the #9969 Grok Imagine routing).
const mod = await import("@omniroute/open-sse/handlers/videoGeneration.ts");
assert.equal(typeof mod.handleVideoGeneration, "function");
const source = readFileSync(path.join(repoRoot, "open-sse/handlers/videoGeneration.ts"), "utf8");
const falImports = source.match(/import \{ handleFalVideoGeneration \}/g) ?? [];
assert.equal(falImports.length, 1, "handleFalVideoGeneration must be imported exactly once");
assert.match(source, /handleFalVideoGeneration \} from "\.\/mediaGeneration\/fal\.ts"/);
});
test("catalog.ts re-exports only what catalogCache actually exports (#9199)", async () => {
// #9199 deliberately replaced #8728's injectable SWR policy with a fixed bound, but
// left catalog.ts re-exporting the three removed symbols. Re-exporting a binding the
// source module does not export is a link-time error, so this import IS the assertion.
const catalog = await import("@/app/api/v1/models/catalog");
const catalogCache = await import("@/app/api/v1/models/catalogCache");
assert.equal(catalogCache.CATALOG_STALE_WHILE_REVALIDATE_MS, 30_000);
assert.equal(catalog.CATALOG_STALE_WHILE_REVALIDATE_MS, 30_000);
// The accessor/policy trio must stay gone — re-adding it would resurrect the
// unbounded window #9199 removed (a failing refresh could pin an old catalog forever).
for (const removed of [
"getCatalogStaleWhileRevalidateMs",
"__setCatalogStaleWhileRevalidateAccessorForTest",
"__setCatalogStaleWhileRevalidateMsForTest",
]) {
assert.equal(
(catalogCache as Record<string, unknown>)[removed],
undefined,
`${removed} was removed by #9199 and must not come back`
);
}
});
test("the stale-while-revalidate path does not throw a ReferenceError (#9199 merge residue)", async () => {
// The mangled merge left `inFlight = { … promise }` referencing two undeclared
// identifiers inside scheduleBackgroundRefresh, so EVERY stale read crashed at runtime.
const catalogCache = await import("@/app/api/v1/models/catalogCache");
catalogCache.__resetCatalogBuilderRunsForTest();
const payload = (body: string) => ({
body,
headers: { "content-type": "application/json" },
status: 200,
cacheTTL: 60_000,
});
const call = (body: string) =>
catalogCache.resolveCachedCatalogResponse(
new Request("http://localhost/v1/models"),
{ corsHeaders: {}, diagnosticHeaders: {} },
async () => payload(body)
);
await call("first");
catalogCache.__expireCatalogCacheForTest();
const stale = await call("second");
assert.equal(await stale.text(), "first", "the stale body must be served, not a crash");
await catalogCache.__flushCatalogBackgroundRefreshForTest();
});
test("conolDiscovery resolves getProviderOutboundGuard from the policy module (#8974)", async () => {
// outboundUrlGuard.ts does NOT export getProviderOutboundGuard — importing it from
// there is a link-time error, so the import below is the assertion.
const mod = await import("@/app/api/providers/[id]/models/conolDiscovery");
assert.equal(typeof mod.maybeHandleConolModelDiscovery, "function");
// The fix must stay on the consumer side. outboundUrlGuard.ts is loaded by the packaged
// CLI, where no tsconfig resolves `@/*`, so re-exporting the policy helpers from it
// (they pull in featureFlags → the DB layer) would break `omniroute setup-opencode`
// (#7682). Guard that nobody "fixes" this by adding the re-export instead.
const guardSource = readFileSync(
path.join(repoRoot, "src/shared/network/outboundUrlGuard.ts"),
"utf8"
);
assert.doesNotMatch(
guardSource,
/^\s*(import|export)[^\n]*from\s+["']@\//m,
"outboundUrlGuard.ts must stay free of @/-aliased imports/re-exports (#7682)"
);
});
test("tinycmsSigner has no build-time-resolvable wasm sidecar URL (#8736/#10087)", () => {
const source = readFileSync(path.join(repoRoot, "open-sse/executors/tinycmsSigner.ts"), "utf8");
// The wasm binary ships inlined as WASM_BASE64; there is no wasm_signer_bg.wasm file.
// Turbopack statically resolves `new URL(<literal>, import.meta.url)`, so leaving the
// generated default in place fails `next build` with "Module not found".
assert.ok(source.includes("const WASM_BASE64 ="), "wasm binary must stay inlined");
assert.doesNotMatch(
source,
/new URL\(\s*['"]wasm_signer_bg\.wasm['"]/,
"generated wasm-bindgen sidecar URL must not survive — Turbopack resolves it at build time"
);
});