import type { Leaf, NamespaceBodyInput, Translations } from '../types'; import type { IInvalidatingStore, IMutableStore, InvalidateListener, StoreGetContext, StoreSetContext } from './types'; /** * User-supplied loader. Resolves a `(locale, namespace)` pair to a * `TranslationsNode` (`defineTranslations({ ... })`) — the namespace body whose * `(locale, namespace)` is fixed by the call arguments. * * Return `undefined` to signal "no data for this pair" — the store caches * the absence so the loader isn't called again for the same pair. */ export type LoaderFn = (locale: string, namespace: string) => Promise | NamespaceBodyInput | undefined; export type LoaderStoreOptions = { /** * Function that loads a `Translations` on demand for a given * `(locale, namespace)` pair. Typically wraps a dynamic `import()`: * * ```typescript * new LoaderStore({ * // each module's default export is a translations node — a `.json` file * // shaped `{ "type": "translations", "data": { ... } }`, or a `.ts` file * // `export default defineTranslations({ ... })`. * loader: (locale, namespace) => * import(`./locales/${locale}/${namespace}.json`).then((m) => m.default), * }); * ``` */ loader: LoaderFn; /** * Optional list of locales the loader knows about. Returned verbatim * from `getLocales()` so `Ilingo.getLocales()` can answer without * touching the loader (which would otherwise mean probing every * (locale, namespace) combination). If omitted, `getLocales()` returns * whatever has been cached so far. */ locales?: string[]; id?: string | symbol; }; type CacheEntry = { /** `undefined` when the loader explicitly returned no data — cached as a miss. */ record: Translations | undefined; }; /** * Lazy-loaded store backed by a user-supplied `loader(locale, namespace)`. * Caches the loaded `Translations` per `(locale, namespace)` so the loader is * called at most once per pair until `invalidate()` is called. * * Designed for SPA / browser code-splitting: * * ```typescript * const store = new LoaderStore({ * loader: (locale, namespace) => import(`./locales/${locale}/${namespace}.json`) * .then((m) => m.default), * locales: ['en', 'de'], * }); * ``` * * Implements `IInvalidatingStore` — calling `invalidate(locale?, namespace?)` * drops the matching cached entries and fires the `invalidate` event so * subscribers (e.g. a Vue composable in dev mode) can re-fetch. */ export declare class LoaderStore implements IInvalidatingStore, IMutableStore { readonly id: string | symbol; protected loaderFn: LoaderFn; protected locales: string[]; /** Map of `${locale}\0${namespace} (NUL-joined)` → cache entry (including miss markers). */ protected cache: Map; /** In-flight loads, keyed identically, so concurrent get()s share a promise. */ protected inflight: Map>; protected listeners: Set; /** * Monotonically increasing generation counter. Bumped by `invalidate()`. * `loadNamespace` captures the generation at the start of a load and only * writes the resolved value into the cache if the generation hasn't * changed in the meantime — protects against an in-flight load * clobbering a fresh cache state after an invalidation race. */ protected generation: number; constructor(options: LoaderStoreOptions); get(context: StoreGetContext): Promise; set(context: StoreSetContext): Promise; getLocales(): Promise; invalidate(locale?: string, namespace?: string): void; on(event: 'invalidate', listener: InvalidateListener): () => void; protected cacheKey(locale: string, namespace: string): string; protected emit(locale: string | undefined, namespace: string | undefined): void; protected loadNamespace(locale: string, namespace: string): Promise; } export {};