mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-19 05:32:19 +03:00
* fix(sse): import localDb through its real .ts extension (#10674) `open-sse/services/combo.ts` imported "../../src/lib/localDb.js" — a .js suffix on a module that only exists as .ts. Turbopack resolved it by accident until the dependency-tree change in #10647; after that the instrumentation hook died at boot with MODULE_NOT_FOUND, breaking `npm run dev` and the production build (60 consecutive red `Build App` runs on release/v3.8.50). Fixes the same latent pattern in src/lib/usage/usageLedger.ts, which survived only because it is an `import type` and is erased before resolution. Adds a guard rejecting relative .js specifiers across open-sse/ and src/. Package specifiers are untouched: publishing ESM as .js is legitimate there (e.g. @modelcontextprotocol/sdk), and only first-party relative imports are first-party TypeScript. Closes #10674 * fix(config): keep the SQLite driver out of the client bundle (#10692) The `aihorde` entry in IMAGE_PROVIDERS imported its live-catalog service directly. IMAGE_PROVIDERS is reachable from "use client" dashboard pages — they read its KEYS to derive which providers support which media kind — so that import dragged aihordeImageCatalog → safeOutboundFetch → proxyFetch → featureFlags → db/core → sqljsAdapter into the browser graph. The build then tried to bundle fs/net/tls for the browser and failed with 28 Module not found errors, leaving `Build App` red for 60 consecutive runs and no artifact buildable from the branch. A dynamic import() does not fix this: the bundler still has to make the module browser-loadable. The dependency is inverted instead — the registry entry knows only a pure registration module, and the server-only service registers itself on import, which every server path needing live models already does. With nothing registered the getter yields [], exactly what the live catalog returned before its first poll. Validated by a full `npm run build:release`: 0 Module not found, artifact produced. Closes #10692 --------- Co-authored-by: Xiangzhe <bakryun0718@proton.me>
50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
/**
|
|
* Registry indirection for image providers whose model list is discovered at runtime (#10692).
|
|
*
|
|
* `IMAGE_PROVIDERS` is reachable from `"use client"` dashboard pages — they read its KEYS to
|
|
* decide which providers support which media kind (see `mediaServiceKinds.ts`). A provider entry
|
|
* that imports its live-catalog service directly therefore drags that service, and everything it
|
|
* imports, into the browser graph. For AI Horde that meant
|
|
* `aihordeImageCatalog → safeOutboundFetch → proxyFetch → featureFlags → db/core → sqljsAdapter`,
|
|
* so the build tried to bundle `fs`/`net`/`tls` for the browser and failed.
|
|
*
|
|
* A dynamic `import()` does not help: the bundler still has to make the module browser-loadable.
|
|
* The dependency has to be inverted instead — the registry entry knows only this pure module, and
|
|
* the server-only service registers itself when it is imported (which every server path that needs
|
|
* live models already does).
|
|
*
|
|
* With no source registered the getter yields `[]`, which is exactly what the live catalog
|
|
* returned before it had polled — so the client keeps seeing the provider without its models,
|
|
* unchanged.
|
|
*/
|
|
|
|
export interface DynamicImageModelEntry {
|
|
id: string;
|
|
name: string;
|
|
inputModalities: string[];
|
|
}
|
|
|
|
type DynamicImageModelSource = () => DynamicImageModelEntry[];
|
|
|
|
const sources = new Map<string, DynamicImageModelSource>();
|
|
|
|
/** Called by a server-only catalog service at import time. Last registration wins. */
|
|
export function registerDynamicImageModelSource(
|
|
providerId: string,
|
|
source: DynamicImageModelSource
|
|
): void {
|
|
sources.set(providerId, source);
|
|
}
|
|
|
|
/** Models discovered for `providerId`, or `[]` when no server-side source is loaded. */
|
|
export function getDynamicImageModels(providerId: string): DynamicImageModelEntry[] {
|
|
const source = sources.get(providerId);
|
|
if (!source) return [];
|
|
return source();
|
|
}
|
|
|
|
/** Test seam — drops every registration. */
|
|
export function resetDynamicImageModelSources(): void {
|
|
sources.clear();
|
|
}
|