@tanstack/db
Version:
A reactive client store for building super fast apps on sync
200 lines (199 loc) • 8.27 kB
text/typescript
import { SortedMap } from '../SortedMap.cjs';
import { VirtualOrigin, WithVirtualProps } from '../virtual-props.js';
import { Transaction } from '../transactions.cjs';
import { StandardSchemaV1 } from '@standard-schema/spec';
import { ChangeMessage, CollectionConfig, OptimisticChangeMessage } from '../types.cjs';
import { CollectionImpl } from './index.js';
import { CollectionLifecycleManager } from './lifecycle.cjs';
import { CollectionChangesManager } from './changes.cjs';
import { CollectionIndexesManager } from './indexes.cjs';
import { CollectionEventsManager } from './events.cjs';
interface PendingSyncedTransaction<T extends object = Record<string, unknown>, TKey extends string | number = string | number> {
committed: boolean;
operations: Array<OptimisticChangeMessage<T>>;
truncate?: boolean;
deletedKeys: Set<string | number>;
rowMetadataWrites: Map<TKey, PendingMetadataWrite>;
collectionMetadataWrites: Map<string, PendingMetadataWrite>;
optimisticSnapshot?: {
upserts: Map<TKey, T>;
deletes: Set<TKey>;
};
/**
* When true, this transaction should be processed immediately even if there
* are persisting user transactions. Used by manual write operations (writeInsert,
* writeUpdate, writeDelete, writeUpsert) which need synchronous updates to syncedData.
*/
immediate?: boolean;
}
type PendingMetadataWrite = {
type: `set`;
value: unknown;
} | {
type: `delete`;
};
export declare class CollectionStateManager<TOutput extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInput extends object = TOutput> {
config: CollectionConfig<TOutput, TKey, TSchema>;
collection: CollectionImpl<TOutput, TKey, any, TSchema, TInput>;
lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>;
changes: CollectionChangesManager<TOutput, TKey, TSchema, TInput>;
indexes: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>;
private _events;
transactions: SortedMap<string, Transaction<any>>;
pendingSyncedTransactions: Array<PendingSyncedTransaction<TOutput, TKey>>;
syncedData: SortedMap<TKey, TOutput>;
syncedMetadata: Map<TKey, unknown>;
syncedCollectionMetadata: Map<string, unknown>;
optimisticUpserts: Map<TKey, TOutput>;
optimisticDeletes: Set<TKey>;
pendingOptimisticUpserts: Map<TKey, TOutput>;
pendingOptimisticDeletes: Set<TKey>;
pendingOptimisticDirectUpserts: Set<TKey>;
pendingOptimisticDirectDeletes: Set<TKey>;
/**
* Tracks the origin of confirmed changes for each row.
* 'local' = change originated from this client
* 'remote' = change was received via sync
*
* This is used for the $origin virtual property.
* Note: This only tracks *confirmed* changes, not optimistic ones.
* Optimistic changes are always considered 'local' for $origin.
*/
rowOrigins: Map<TKey, VirtualOrigin>;
/**
* Tracks keys that have pending local changes.
* Used to determine whether sync-confirmed data should have 'local' or 'remote' origin.
* When sync confirms data for a key with pending local changes, it keeps 'local' origin.
*/
pendingLocalChanges: Set<TKey>;
pendingLocalOrigins: Set<TKey>;
private virtualPropsCache;
size: number;
syncedKeys: Set<TKey>;
preSyncVisibleState: Map<TKey, TOutput>;
recentlySyncedKeys: Set<TKey>;
hasReceivedFirstCommit: boolean;
isCommittingSyncTransactions: boolean;
isLocalOnly: boolean;
/**
* Creates a new CollectionState manager
*/
constructor(config: CollectionConfig<TOutput, TKey, TSchema>);
setDeps(deps: {
collection: CollectionImpl<TOutput, TKey, any, TSchema, TInput>;
lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>;
changes: CollectionChangesManager<TOutput, TKey, TSchema, TInput>;
indexes: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>;
events: CollectionEventsManager;
}): void;
/**
* Checks if a row has pending optimistic mutations (not yet confirmed by sync).
* Used to compute the $synced virtual property.
*/
isRowSynced(key: TKey): boolean;
/**
* Gets the origin of the last confirmed change to a row.
* Returns 'local' if the row has optimistic mutations (optimistic changes are local).
* Used to compute the $origin virtual property.
*/
getRowOrigin(key: TKey): VirtualOrigin;
private createVirtualPropsSnapshot;
private getVirtualPropsSnapshotForState;
private enrichWithVirtualPropsSnapshot;
private clearOriginTrackingState;
/**
* Enriches a row with virtual properties using the "add-if-missing" pattern.
* If the row already has virtual properties (from an upstream collection),
* they are preserved. Otherwise, new values are computed.
*/
enrichWithVirtualProps(row: TOutput, key: TKey): WithVirtualProps<TOutput, TKey>;
/**
* Creates a change message with virtual properties.
* Uses the "add-if-missing" pattern so that pass-through from upstream
* collections works correctly.
*/
enrichChangeMessage(change: ChangeMessage<TOutput, TKey>): ChangeMessage<WithVirtualProps<TOutput, TKey>, TKey>;
/**
* Get the current value for a key enriched with virtual properties.
*/
getWithVirtualProps(key: TKey): WithVirtualProps<TOutput, TKey> | undefined;
/**
* Get the current value for a key (virtual derived state)
*/
get(key: TKey): TOutput | undefined;
/**
* Check if a key exists in the collection (virtual derived state)
*/
has(key: TKey): boolean;
/**
* Get all keys (virtual derived state)
*/
keys(): IterableIterator<TKey>;
/**
* Get all values (virtual derived state)
*/
values(): IterableIterator<TOutput>;
/**
* Get all entries (virtual derived state)
*/
entries(): IterableIterator<[TKey, TOutput]>;
/**
* Get all entries (virtual derived state)
*/
[Symbol.iterator](): IterableIterator<[TKey, TOutput]>;
/**
* Execute a callback for each entry in the collection
*/
forEach(callbackfn: (value: TOutput, key: TKey, index: number) => void): void;
/**
* Create a new array with the results of calling a function for each entry in the collection
*/
map<U>(callbackfn: (value: TOutput, key: TKey, index: number) => U): Array<U>;
/**
* Check if the given collection is this collection
* @param collection The collection to check
* @returns True if the given collection is this collection, false otherwise
*/
private isThisCollection;
/**
* Recompute optimistic state from active transactions
*/
recomputeOptimisticState(triggeredByUserAction?: boolean): void;
/**
* Calculate the current size based on synced data and optimistic changes
*/
private calculateSize;
/**
* Collect events for optimistic changes
*/
private collectOptimisticChanges;
/**
* Get the previous value for a key given previous optimistic state
*/
private getPreviousValue;
/**
* Attempts to commit pending synced transactions if there are no active transactions
* This method processes operations from pending transactions and applies them to the synced data
*/
commitPendingTransactions: () => void;
/**
* Schedule cleanup of a transaction when it completes
*/
scheduleTransactionCleanup(transaction: Transaction<any>): void;
/**
* Capture visible state for keys that will be affected by pending sync operations
* This must be called BEFORE onTransactionStateChange clears optimistic state
*/
capturePreSyncVisibleState(): void;
/**
* Trigger a recomputation when transactions change
* This method should be called by the Transaction class when state changes
*/
onTransactionStateChange(): void;
/**
* Clean up the collection by stopping sync and clearing data
* This can be called manually or automatically by garbage collection
*/
cleanup(): void;
}
export {};