UNPKG

triplit-tanstackdb

Version:

TanStack DB collection adapter for the Triplit real-time, offline-first sync engine. Enables powerful optimistic updates and reactive, cross-source queries.

147 lines (137 loc) 5.17 kB
import { createCollection, Collection, StandardSchema, CollectionConfig, } from '@tanstack/db'; import { TriplitClient, SchemaQuery, Models, TriplitError, } from '@triplit/client'; import { createTriplitCollectionOptions } from './options'; /** * A utility type to allow passthrough of any standard `CollectionConfig` properties * that are not handled by our adapter. This provides maximum flexibility. * @internal */ type PassthroughCollectionConfig<TItem extends object> = Omit< CollectionConfig<TItem>, 'getKey' | 'sync' | 'onInsert' | 'onUpdate' | 'onDelete' >; /** * Configuration options for the `createTriplitCollection` factory function. * This combines the essential Triplit configuration with all standard, passthrough * options from TanStack DB's `CollectionConfig`. */ export interface TriplitCollectionFactoryOptions< M extends Models<M>, TQuery extends SchemaQuery<M>, TItem extends object = TQuery extends { _output: infer O extends object } ? O : never > extends PassthroughCollectionConfig<TItem> { /** * An instance of the configured TriplitClient. This client should be * initialized and managed at a higher level in your application. */ client: TriplitClient<M>; /** * The Triplit query that defines the set of data to be synced into this collection. * This acts as the "source of truth" for the collection's contents. * * @example client.query('todos').where('completed', '=', false) */ query: TQuery; /** * A function that returns a unique, stable key (ID) for a given item. This is * mandatory for TanStack DB to track individual entities for updates and deletes. */ getKey: (item: TItem) => string | number; /** * An optional, but highly recommended, unique identifier for this collection. * This ID is used in developer tools and for debugging, making it an essential * part of a scalable application. */ id?: string; /** * An optional schema (e.g., from Zod or TypeBox). This is a powerhouse feature. * Providing a schema enables full, end-to-end type safety for all mutations. * For example, `collection.update(id, data)` will type-check the `data` payload * against your schema, preventing runtime errors. */ schema?: StandardSchema<TItem>; /** * An optional callback to handle errors that occur during the real-time subscription * or during mutation operations. Useful for global error logging or displaying toasts. * @param error - The error received from the Triplit client. */ onError?: (error: TriplitError | Error) => void; } /** * Creates a new TanStack DB Collection that is kept in sync with a Triplit real-time query. * * This factory function is the primary, high-level API for integrating Triplit with TanStack DB. * It provides a streamlined, one-step process for creating fully reactive, offline-first, * and optimistically updated collections powered by a Triplit backend. * * @param options - The configuration options for the Triplit-powered collection. * @returns An instance of a TanStack DB `Collection`, ready to be used with `useLiveQuery`. * * @example * // In your collections file: * import { createTriplitCollection } from '@tanstack/triplit-collection'; * import { client } from './my-triplit-client'; * import { zodTodoSchema } from './schemas'; * * export const activeTodosCollection = createTriplitCollection({ * // --- Triplit-specific options --- * client, * query: client.query('todos').where('completed', '=', false), * * // --- Mandatory TanStack DB option --- * getKey: (todo) => todo.id, * * // --- Recommended TanStack DB options for a great DX --- * id: 'activeTodos', * schema: zodTodoSchema, * * // --- Adapter-specific options --- * onError: (err) => showToast(`Sync Error: ${err.message}`), * * // --- Passthrough standard CollectionConfig options --- * rowUpdateMode: 'full', * }); */ export function createTriplitCollection< M extends Models<M>, TQuery extends SchemaQuery<M>, TItem extends object = TQuery extends { _output: infer O extends object } ? O : never >( options: TriplitCollectionFactoryOptions<M, TQuery, TItem> ): Collection<TItem> { const { client, query, getKey, onError, // Capture all other standard options into a 'rest' object. ...restConfig } = options; // 1. Generate the core sync and mutation handlers using our lower-level adapter. const triplitAdapterOptions = createTriplitCollectionOptions<M, TQuery, TItem>( { client, query, getKey, onError, } ); // 2. Create and return the final TanStack DB Collection, combining the adapter's // logic with all the standard configuration properties passed in by the user. // Note: Type assertion needed due to TanStack DB's complex ResolveType system // At runtime, the types are compatible since TItem extends object return createCollection({ ...restConfig, // Spread passthrough options first (id, schema, rowUpdateMode, etc.) ...triplitAdapterOptions, // Then spread our adapter's core logic. } as any) as unknown as Collection<TItem>; }