import type { TCacheEntryAddedContext, TQueryStartedContext } from "./cache.js"; import type { ICommand, TCommandOptions } from "./command.js"; import type { CombinePluginCommandAugments, CombinePluginProjectionResourceAugments, CombinePluginResourceAugments, PluginHKT } from "./plugin-hkt.js"; import type { TProjectionResourceOptions } from "./projection-resource.js"; import type { IResource, TResourceOptions } from "./resource.js"; import type { ISyncDriver, TApiSnapshot } from "./snapshot.js"; /** * Provenance passed to {@link TMapError} alongside the raw error. Lets a single * api-level mapper branch on where the failure originated without wrapping the * error itself. */ export interface TErrorContext { /** Which operation surfaced the error. */ source: "query" | "command"; /** The arguments the failing operation ran with (typed `unknown` — one api-level mapper serves resources/commands with differing arg types). */ args: unknown; /** Serialized cache-entry key of the failing operation. */ entryKey: string; /** Resource/command key, when one is configured. */ key?: string; } /** * Normalizes every raw error surfaced by a query/command into the api's error * type. Runs exactly once per failure, at the boundary where the rejection is * first observed, so everything downstream — agent state, imperative-fetch * rejections, the Suspense throw, the command result envelope — sees the mapped * value. The mapper also receives internal lifecycle errors that feed the typed * mutation envelope: a `CacheEntryRemovedError` when a command entry is evicted * mid-flight (re-execute with the same key, `reset()`), so handle unknown * shapes with a fallback branch. Deliberately kept raw: aborted runs (flow * control, never mapped) and lifecycle-hook contexts (`$queryFulfilled` rejects * with the raw error). The inferred return type becomes the api's `TError`. */ export type TMapError = (error: unknown, ctx: TErrorContext) => TError; export interface IPluginContext { keyPrefix: string; } export interface IPlugin { readonly name: string; install(context: IPluginContext): void; augmentResource?(resource: IResource, options: TResourceOptions): Record; augmentCommand?(command: ICommand, options: TCommandOptions): Record; /** * Additional augmentation applied only to projection resources, on top of the * regular {@link augmentResource} pass (which projection resources go through * as ordinary resources). Runs after the projection runtime is attached. */ augmentProjectionResource?(resource: IResource, options: TProjectionResourceOptions): Record; /** * Phantom type member. Plugins that provide typed augmentations should * `declare readonly _hkt: MyPluginHKT` where `MyPluginHKT extends PluginHKT`. * Never set at runtime — purely a compile-time protocol. */ readonly _hkt?: PluginHKT; } export interface TCreateApiOptions { keyPrefix?: string | null; plugins?: TPlugins; serializeArgs?: (args: unknown) => string; resourceRetentionTime?: number | false; commandRetentionTime?: number | false; initialSnapshot?: TApiSnapshot | null; snapshotValidTime?: number | false; defaultSync?: "none" | "resources" | "all"; syncDriver?: ISyncDriver; /** * Normalizes raw query/command errors into a typed error. When provided, the * `error` on every resource/command state (and the mutation result envelope) * is typed as its return value instead of `unknown`. See {@link TMapError}. */ mapError?: TMapError; onCacheEntryAdded?: (args: unknown, ctx: TCacheEntryAddedContext) => void; onQueryStarted?: (args: unknown, ctx: TQueryStartedContext) => void | Promise; } export interface IApi { createResource(options: TResourceOptions): IResource & CombinePluginResourceAugments; unstable_createProjectionResource(options: TProjectionResourceOptions): IResource & CombinePluginResourceAugments & CombinePluginProjectionResourceAugments; createCommand(options: TCommandOptions): ICommand & CombinePluginCommandAugments; getSnapshot(): TApiSnapshot; resetAll(): void; }