UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

192 lines (191 loc) • 6.94 kB
import { BaseCollectionConfig, CollectionConfig, PendingMutation, UtilsRecord } from './types.js'; import { StandardSchemaV1 } from '@standard-schema/spec'; export declare class DatabaseRequiredError extends Error { constructor(); } /** * Thrown when the specified object store doesn't exist in the database */ export declare class ObjectStoreNotFoundError extends Error { constructor(storeName: string, databaseName: string, availableStores: ReadonlyArray<string>); } /** * Thrown when the name (object store) configuration is missing */ export declare class NameRequiredError extends Error { constructor(); } /** * Thrown when the getKey function is missing */ export declare class GetKeyRequiredError extends Error { constructor(); } export interface CreateIndexedDBOptions { /** Database name */ name: string; /** Schema version (increment when adding stores) */ version: number; /** Object store names to create */ stores: ReadonlyArray<string>; /** Custom IDBFactory for testing/mocking */ idbFactory?: IDBFactory; /** Reports a native blocker without settling the open request. */ onBlocked?: (event: IDBVersionChangeEvent) => void; } /** * A shared IndexedDB database instance. * Create with createIndexedDB() and pass to collections. */ export interface IndexedDBInstance { /** The underlying IDBDatabase connection */ readonly db: IDBDatabase; /** Database name */ readonly name: string; /** Database version */ readonly version: number; /** Requested object store names (frozen); omissions do not remove stores */ readonly stores: ReadonlyArray<string>; /** IDBFactory used to create this database (for testing) */ readonly idbFactory?: IDBFactory; /** Close the connection and mark its managed Collections as errored. */ close: () => void; } type InferSchemaOutput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<T> extends object ? StandardSchemaV1.InferOutput<T> : Record<string, unknown> : Record<string, unknown>; /** * Schema input type inference helper */ type InferSchemaInput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferInput<T> extends object ? StandardSchemaV1.InferInput<T> : Record<string, unknown> : Record<string, unknown>; /** * Configuration options for creating an IndexedDB Collection */ export interface IndexedDBCollectionConfig<T extends object = object, TSchema extends StandardSchemaV1 = never, TKey extends string | number = string | number> extends BaseCollectionConfig<T, TKey, TSchema> { /** * IndexedDB instance from createIndexedDB() * REQUIRED - must create database before collections */ db: IndexedDBInstance; /** * Name of the object store within the database * Must exist in the underlying database */ name: string; } /** * Database information returned by getDatabaseInfo() */ export interface DatabaseInfo { name: string; version: number; objectStores: Array<string>; /** Origin-wide storage usage in bytes, including other databases and caches. */ estimatedSize?: number; } /** * Utility functions exposed on collection.utils */ export interface IndexedDBCollectionUtils<TItem extends object = Record<string, unknown>, TInsertInput extends object = TItem> extends UtilsRecord { /** * Removes all data from the object store * Does NOT delete the database itself */ clearObjectStore: () => Promise<void>; /** * Returns database information for debugging */ getDatabaseInfo: () => Promise<DatabaseInfo>; /** * Accepts mutations from a manual transaction and persists to IndexedDB */ acceptMutations: (transaction: { mutations: Array<PendingMutation>; }) => Promise<void>; /** * Exports all data from the object store as an array * Useful for backup/debugging */ exportData: () => Promise<Array<TItem>>; /** * Validates input rows and atomically replaces the object store. * Failure preserves the previous rows and versions. */ importData: (items: Array<TInsertInput>) => Promise<void>; } /** * Creates or opens an IndexedDB database with the specified stores. * Call this once at app startup, then pass the instance to collections. * The connection closes on versionchange so another context can upgrade or * delete the database. Affected Collections enter error and retain their rows. * Recreate affected Collections with a new instance before * further persistence. * * All stores are created in a single upgrade transaction, avoiding * version race conditions when multiple collections share a database. * * @example * ```typescript * const db = await createIndexedDB({ * name: 'myApp', * version: 1, * stores: ['todos', 'users', 'settings'], * }) * * const todosCollection = createCollection( * indexedDBCollectionOptions({ * db, * name: 'todos', * getKey: (item: { id: string }) => item.id, * }) * ) * ``` */ export declare function createIndexedDB(options: CreateIndexedDBOptions): Promise<IndexedDBInstance>; /** * Creates IndexedDB collection options for use with a standard Collection. * This provides persistent local storage with cross-tab synchronization. * * IMPORTANT: You must first create the database with createIndexedDB() and * pass the instance to this function. This ensures all stores are created * upfront in a single upgrade transaction. * * @example * // Step 1: Create database with all stores * const db = await createIndexedDB({ * name: 'myApp', * version: 1, * stores: ['todos', 'users'], * }) * * // Step 2: Create collections using the shared database * const todosCollection = createCollection( * indexedDBCollectionOptions({ * db, * name: 'todos', * schema: todoSchema, * getKey: (item: { id: string }) => item.id, * }) * ) * * @example * // Without schema (explicit type) * const todosCollection = createCollection( * indexedDBCollectionOptions<Todo>({ * db, * name: 'todos', * getKey: (item: { id: string }) => item.id, * }) * ) */ export declare function indexedDBCollectionOptions<T extends StandardSchemaV1, TKey extends string | number = string | number>(config: IndexedDBCollectionConfig<InferSchemaOutput<T>, T, TKey> & { schema: T; }): CollectionConfig<InferSchemaOutput<T>, TKey, T, IndexedDBCollectionUtils<InferSchemaOutput<T>, InferSchemaInput<T>>> & { schema: T; utils: IndexedDBCollectionUtils<InferSchemaOutput<T>, InferSchemaInput<T>>; }; export declare function indexedDBCollectionOptions<T extends object, TKey extends string | number = string | number>(config: IndexedDBCollectionConfig<T, never, TKey> & { schema?: never; }): CollectionConfig<T, TKey, never, IndexedDBCollectionUtils<T>> & { schema?: never; utils: IndexedDBCollectionUtils<T>; }; export {};