- Replace `OPENREADER_COMPUTE_MODE` and related variables with `COMPUTE_MODE` - Replace `OPENREADER_*` PDF/Whisper model URLs with `PDF_LAYOUT_MODEL_BASE_URL` and `WHISPER_MODEL_BASE_URL` - Remove legacy `NEXT_PUBLIC_*` runtime config seeds in favor of `RUNTIME_SEED_*` - Update documentation, code, and environment references to match new variable names - Remove deprecated `scripts/fetch-models.mjs` and related npm script - Update runtime config SSR injection from `window.__OPENREADER_RUNTIME_CONFIG__` to `window.__RUNTIME_CONFIG__` - Adjust Next.js config to use new compute mode env var and optimize output file tracing for ONNX dependencies BREAKING CHANGE: Environment variable names for compute mode, model URLs, and runtime config seeding have changed. Update `.env` files and deployment configs to use `COMPUTE_MODE`, `PDF_LAYOUT_MODEL_BASE_URL`, `WHISPER_MODEL_BASE_URL`, and `RUNTIME_SEED_*` as appropriate. Legacy `OPENREADER_*` and `NEXT_PUBLIC_*` variables are no longer supported.
86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
'use client';
|
|
|
|
import { createContext, useContext, useMemo, type ReactNode } from 'react';
|
|
|
|
/**
|
|
* Site-wide runtime config resolved at SSR time and injected via
|
|
* `window.__RUNTIME_CONFIG__`. Replaces module-scope reads of
|
|
* build-time public env flags so admin edits take effect on the next page
|
|
* load without a redeploy. Read-only from the client; admin writes go
|
|
* through `/api/admin/settings` and trigger a reload.
|
|
*
|
|
* Keep this in sync with `RUNTIME_CONFIG_SCHEMA` on the server.
|
|
*/
|
|
export interface RuntimeConfig {
|
|
defaultTtsProvider: string;
|
|
changelogFeedUrl: string;
|
|
appVersion: string;
|
|
enableUserSignups: boolean;
|
|
restrictUserApiKeys: boolean;
|
|
enableTtsProvidersTab: boolean;
|
|
enableAudiobookExport: boolean;
|
|
enableDocxConversion: boolean;
|
|
enableDestructiveDeleteActions: boolean;
|
|
showAllProviderModels: boolean;
|
|
computeAvailable: boolean;
|
|
}
|
|
|
|
const RUNTIME_DEFAULTS: RuntimeConfig = {
|
|
defaultTtsProvider: 'custom-openai',
|
|
changelogFeedUrl: 'https://docs.openreader.richardr.dev/changelog/manifest.json',
|
|
appVersion: '0.0.0',
|
|
enableUserSignups: true,
|
|
restrictUserApiKeys: true,
|
|
enableTtsProvidersTab: true,
|
|
enableAudiobookExport: true,
|
|
enableDocxConversion: true,
|
|
enableDestructiveDeleteActions: true,
|
|
showAllProviderModels: true,
|
|
computeAvailable: true,
|
|
};
|
|
|
|
declare global {
|
|
// Injected via SSR in `src/app/layout.tsx`. Always defined in the browser.
|
|
interface Window {
|
|
__RUNTIME_CONFIG__?: Partial<RuntimeConfig>;
|
|
}
|
|
}
|
|
|
|
function readInjectedConfig(): RuntimeConfig {
|
|
if (typeof window === 'undefined') return { ...RUNTIME_DEFAULTS };
|
|
const injected = window.__RUNTIME_CONFIG__;
|
|
if (!injected || typeof injected !== 'object') return { ...RUNTIME_DEFAULTS };
|
|
return { ...RUNTIME_DEFAULTS, ...injected };
|
|
}
|
|
|
|
const RuntimeConfigContext = createContext<RuntimeConfig>({ ...RUNTIME_DEFAULTS });
|
|
|
|
export function RuntimeConfigProvider({
|
|
children,
|
|
value,
|
|
}: {
|
|
children: ReactNode;
|
|
/** Optional override (for tests). When omitted, reads from window. */
|
|
value?: RuntimeConfig;
|
|
}) {
|
|
const resolved = useMemo<RuntimeConfig>(() => value ?? readInjectedConfig(), [value]);
|
|
return <RuntimeConfigContext.Provider value={resolved}>{children}</RuntimeConfigContext.Provider>;
|
|
}
|
|
|
|
export function useRuntimeConfig(): RuntimeConfig {
|
|
return useContext(RuntimeConfigContext);
|
|
}
|
|
|
|
export function useFeatureFlag<K extends keyof RuntimeConfig>(key: K): RuntimeConfig[K] {
|
|
const cfg = useRuntimeConfig();
|
|
return cfg[key];
|
|
}
|
|
|
|
/**
|
|
* Synchronous accessor for modules that are loaded before the React tree
|
|
* mounts (e.g. Dexie initialization, config defaults). Falls back to the
|
|
* built-in defaults during SSR.
|
|
*/
|
|
export function readRuntimeConfigSync(): RuntimeConfig {
|
|
return readInjectedConfig();
|
|
}
|