import { UnknownError } from '@livestore/common'; import type { LiveStoreSchema } from '@livestore/common/schema'; import { Effect, type OtelTracer, Runtime, type Schema, type Scope } from '@livestore/utils/effect'; import { type CreateStoreOptions } from './create-store.ts'; import type { Store } from './store.ts'; import type { OtelOptions } from './store-types.ts'; /** * Default time to keep unused stores in cache. * * - Browser: 60 seconds (60,000 ms) * - SSR: Infinity (disables disposal to avoid disposing stores before server render completes) * * @internal Exported primarily for testing purposes. */ export declare const DEFAULT_UNUSED_CACHE_TIME: number; /** * Configuration options for stores managed by a {@link StoreRegistry}. * * Extends {@link CreateStoreOptions} with registry-specific settings for caching and observability. * Use with {@link storeOptions} helper to get full type inference when defining reusable store configurations. * * @typeParam TSchema - The LiveStore schema type * @typeParam TContext - User-defined context attached to the store * @typeParam TSyncPayloadSchema - Schema for the sync payload sent to the backend * * @see {@link storeOptions} for defining reusable store configurations * @see {@link StoreRegistry} for managing store lifecycles */ export interface RegistryStoreOptions = typeof Schema.JsonValue> extends CreateStoreOptions { /** * OpenTelemetry configuration for tracing store operations. * * When provided, store operations (boot, queries, commits) will be traced * under the given root span context using the specified tracer. */ otelOptions?: Partial; /** * The time in milliseconds that this store should remain * in memory after becoming unused. When this store becomes * unused (no active retentions), it will be disposed after this duration. * * Stores transition to the unused state as soon as they have no * active retentions, so when all components which use that store * have unmounted. * * @remarks * - Per-store values override the registry-level default (set via `StoreRegistry` constructor's * `defaultOptions.unusedCacheTime`) * - The value is fixed when the store is first loaded into the registry. If the same `storeId` is * requested again with a different `unusedCacheTime`, the original value is kept. * - If set to `Infinity`, will disable automatic disposal * - The maximum allowed time is about {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout#maximum_delay_value | 24 days} * * @defaultValue `60_000` (60 seconds) or `Infinity` during SSR to avoid * disposing stores before server render completes. */ unusedCacheTime?: number; } type StoreRegistryConfig = { /** * Default options that are applied to all stores when they are loaded. * * @remarks * These are options that typically don't depend on the specific store being loaded: * - Framework integration (`batchUpdates`) * - Environment settings (`disableDevtools`, `debug`, `otelOptions`) * - Behavior defaults (`confirmUnsavedChanges`, `unusedCacheTime`) * * Store-specific fields like `schema`, `adapter`, `storeId`, and `boot` are intentionally * excluded since they vary per store definition. */ defaultOptions?: Partial>; /** * Custom Effect runtime for all registry operations (loading, caching, etc.). * When the runtime's scope closes, all managed stores are automatically shut down. */ runtime?: Runtime.Runtime; }; /** * Store Registry coordinating store loading, caching, and retention * * @public */ export declare class StoreRegistry { #private; /** * Creates a new StoreRegistry instance. * * @example * ```ts * const registry = new StoreRegistry({ * defaultOptions: { * batchUpdates, * unusedCacheTime: 30_000, * } * }) * ``` */ constructor(config?: StoreRegistryConfig); /** * Gets a cached store or loads a new one, with the store lifetime scoped to the caller. * * @typeParam TSchema - The schema type for the store * @typeParam TContext - The context type for the store * @typeParam TSyncPayloadSchema - The sync payload schema type * @returns An Effect that yields the store, scoped to the provided Scope * * @remarks * - Stores are kept in cache and reused while any scope holds them * - When the scope closes, the reference is released; the store is disposed after `unusedCacheTime` * if no other scopes retain it * - Concurrent calls with the same storeId share the same store instance */ getOrLoad: = typeof Schema.JsonValue>(options: RegistryStoreOptions) => Effect.Effect, UnknownError, Scope.Scope>; /** * Get or load a store, returning it directly if already loaded or a promise if loading. * * @typeParam TSchema - The schema type for the store * @typeParam TContext - The context type for the store * @typeParam TSyncPayloadSchema - The sync payload schema type * @returns The loaded store if available, or a Promise that resolves to the loaded store * @throws unknown - store loading error * * @remarks * - Returns the store instance directly (synchronous) when already loaded * - Returns a stable Promise reference when loading is in progress or needs to be initiated * - Throws with the same error instance on subsequent calls after failure * - Applies default options from registry config, with call-site options taking precedence * - Concurrent calls with the same storeId share the same store instance */ getOrLoadPromise: = typeof Schema.JsonValue>(options: RegistryStoreOptions) => Store | Promise>; /** * Retains the store in cache. * * @typeParam TSchema - The schema type for the store * @typeParam TContext - The context type for the store * @typeParam TSyncPayloadSchema - The sync payload schema type * @returns A release function that, when called, removes this retention hold * * @remarks * - Multiple retains on the same store are independent; each must be released separately * - If the store isn't cached yet, it will be loaded and then retained * - The store will remain in cache until all retains are released and after `unusedCacheTime` expires */ retain: = typeof Schema.JsonValue>(options: RegistryStoreOptions) => (() => void); /** * Loads a store (without suspending) to warm up the cache. * * @typeParam TSchema - The schema of the store to preload * @typeParam TContext - The context type for the store * @typeParam TSyncPayloadSchema - The sync payload schema type * @returns A promise that resolves when the loading is complete (success or failure) * * @remarks * - We don't return the store or throw as this is a fire-and-forget operation. * - If the entry remains unused after preload resolves/rejects, it is scheduled for disposal. * - Does not affect the retention of the store in cache. */ preload: = typeof Schema.JsonValue>(options: RegistryStoreOptions) => Promise; /** * Disposes the registry and all its managed stores, immediately releasing resources * (database connections, WebSocket connections, web workers, etc.). * * Most applications should use a single `StoreRegistry` and don't need to call * this method. It's only necessary when creating multiple short-lived registries to * immediately release resources and avoid conflicts with subsequent registries. * * @returns A promise that resolves when disposal is complete * * @remarks * - No-op if a custom `runtime` was provided to the constructor (caller owns cleanup) * - Idempotent: safe to call multiple times * - After disposal, the registry should not be used */ dispose: () => Promise; } /** * Helper for defining reusable store options with full type inference. Returns * options that can be passed to `useStore()` or `storeRegistry.preload()`. * * @remarks * At runtime this is an identity function that returns the input unchanged. * Its value lies in enabling TypeScript's excess property checking to catch * typos and configuration errors, while allowing options to be shared across * `useStore()`, `storeRegistry.preload()`, `storeRegistry.getOrLoad()`, etc. * * @typeParam TSchema - The LiveStore schema type * @typeParam TContext - User-defined context attached to the store * @typeParam TSyncPayloadSchema - Schema for the sync payload sent to the backend * @param options - The store configuration options * @returns The same options object, unchanged * * @example * ```ts * export const issueStoreOptions = (issueId: string) => * storeOptions({ * storeId: `issue-${issueId}`, * schema, * adapter, * unusedCacheTime: 30_000, * }) * * // In a component * const issueStore = useStore(issueStoreOptions(issueId)) * * // In a route loader or event handler * storeRegistry.preload({ * ...issueStoreOptions(issueId), * unusedCacheTime: 10_000, * }); * ``` */ export declare const storeOptions: = typeof Schema.JsonValue>(options: RegistryStoreOptions) => RegistryStoreOptions; export {}; //# sourceMappingURL=StoreRegistry.d.ts.map