@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 86.2 kB
Source Map (JSON)
{"version":3,"file":"state.cjs","sources":["../../../src/collection/state.ts"],"sourcesContent":["import { deepEquals } from '../utils'\nimport { SortedMap } from '../SortedMap'\nimport { enrichRowWithVirtualProps } from '../virtual-props.js'\nimport {\n DuplicateTransactionIdError,\n SyncQueueInvariantError,\n SyncTransactionAbortedError,\n} from '../errors.js'\nimport type { DuplicateKeySyncError } from '../errors.js'\nimport type {\n VirtualOrigin,\n VirtualRowProps,\n WithVirtualProps,\n} from '../virtual-props.js'\nimport type { Transaction } from '../transactions'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n ChangeMessage,\n CollectionConfig,\n OperationType,\n OptimisticChangeMessage,\n PendingMutation,\n} from '../types'\nimport type { CollectionImpl } from './index.js'\nimport type { CollectionLifecycleManager } from './lifecycle'\nimport type { CollectionChangesManager } from './changes'\nimport type { CollectionIndexesManager } from './indexes'\nimport type { CollectionEventsManager } from './events'\nimport type { Deferred } from '../deferred'\n\ntype PendingSyncOperation<\n T extends object,\n TKey extends string | number,\n> = OptimisticChangeMessage<T, TKey> & {\n /** Preserve adapter intent when queue changes require reclassification. */\n originalSyncType?: `insert`\n /** A partial update admitted against a row must not become an upsert. */\n}\n\ntype PendingSyncedKeyState<T extends object> = {\n exists: boolean\n value: T | undefined\n}\n\ntype PendingSyncedProjection<T extends object, TKey extends string | number> = {\n states: Map<TKey, PendingSyncedKeyState<T>>\n truncated: boolean\n /** Keys a queued source operation writes; seeds do not count. */\n sourceKeys: Set<TKey>\n}\n\ntype PendingInsertDisposition = `insert` | `update` | `duplicate`\n\ninterface PendingSyncedTransaction<\n T extends object = Record<string, unknown>,\n TKey extends string | number = string | number,\n> {\n committed: boolean\n applicationStarted: boolean\n layoutChanged: boolean\n operations: Array<PendingSyncOperation<T, TKey>>\n // The transaction replaces every row: the adapter began it as a snapshot\n // or called truncate() in it.\n truncate?: boolean\n truncateMarkReady?: boolean\n rowMetadataWrites: Map<TKey, PendingMetadataWrite>\n /** The last explicit write per key, after `position` operations. */\n explicitRowMetadataWrites: Map<\n TKey,\n { position: number; write: PendingMetadataWrite }\n >\n collectionMetadataWrites: Map<string, PendingMetadataWrite>\n /** Resolves after application and rejects if canceled before application. */\n applied: Deferred<void>\n /**\n * Keys whose writes keep their hydration-seed status and fix no adapter\n * authority: a DbClient seed chunk's keys, or a wrapping sync's storage\n * read's seed rows.\n */\n preserveHydrationSeedKeys?: ReadonlySet<TKey>\n /**\n * Set on a truncate that keeps `preserveHydrationSeedKeys`: a schema reset\n * on demand truncates the source's state of every other key (decision 20).\n */\n sourceTruncate?: boolean\n /** Builds the error for an open transaction whose insert a replay invalidates. */\n duplicateKeyError?: (key: TKey) => DuplicateKeySyncError\n /**\n * Set when a replay invalidates an open transaction, which happens when a\n * later transaction begun inside it commits first. Its commit rejects.\n */\n invalidationError?: Error\n}\n\n/** The parts of a wrapping sync's staged transaction that seed authority reads. */\nexport type StagedSyncTransaction<TKey extends string | number> = {\n truncate?: boolean\n operations: ReadonlyArray<{ key: unknown }>\n rowMetadataWrites: ReadonlyMap<TKey, unknown>\n preserveHydrationSeedKeys?: ReadonlySet<TKey>\n sourceTruncate?: boolean\n}\n\n/** Whether a sync transaction truncates the source's state of this key. */\nexport function truncatesSourceKey<TKey extends string | number>(\n transaction: StagedSyncTransaction<TKey>,\n key: TKey,\n): boolean {\n const kept = transaction.preserveHydrationSeedKeys\n return (\n transaction.truncate === true &&\n (!kept || (transaction.sourceTruncate === true && !kept.has(key)))\n )\n}\n\nexport type PendingMetadataWrite =\n { type: `set`; value: unknown } | { type: `delete` }\n\n/** The row metadata a sync operation writes unless the adapter set it explicitly. */\nexport function automaticRowMetadataWrite(\n operation: Pick<OptimisticChangeMessage<object>, `type` | `metadata`>,\n): PendingMetadataWrite | undefined {\n if (operation.metadata !== undefined && operation.type !== `delete`) {\n return { type: `set`, value: operation.metadata }\n }\n return operation.type === `update` ? undefined : { type: `delete` }\n}\n\ntype InternalChangeMessage<\n T extends object = Record<string, unknown>,\n TKey extends string | number = string | number,\n> = ChangeMessage<T, TKey> & {\n __virtualProps?: {\n value?: VirtualRowProps<TKey>\n previousValue?: VirtualRowProps<TKey>\n }\n}\nexport class CollectionStateManager<\n TOutput extends object = Record<string, unknown>,\n TKey extends string | number = string | number,\n TSchema extends StandardSchemaV1 = StandardSchemaV1,\n TInput extends object = TOutput,\n> {\n public config!: CollectionConfig<TOutput, TKey, TSchema, any>\n public collection!: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n public lifecycle!: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n public changes!: CollectionChangesManager<TOutput, TKey, TSchema, TInput>\n public indexes!: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>\n private _events!: CollectionEventsManager\n\n // Core state - make public for testing\n public transactions: SortedMap<string, Transaction<any>>\n public pendingSyncedTransactions: Array<\n PendingSyncedTransaction<TOutput, TKey>\n > = []\n private pendingSyncedProjection: PendingSyncedProjection<TOutput, TKey> = {\n states: new Map(),\n truncated: false,\n sourceKeys: new Set(),\n }\n public syncedData: SortedMap<TKey, TOutput>\n public syncedMetadata = new Map<TKey, unknown>()\n public syncedCollectionMetadata = new Map<string, unknown>()\n public hydrationSeedKeys = new Set<TKey>()\n public hydratedKeys = new Set<TKey>()\n // DbClient may receive a stale hydration chunk after adapter work. Each key\n // whose row metadata an applied adapter write fixed maps to whether that\n // write deleted the row: row metadata is a separate object, closed to later\n // seeds even when the adapter never wrote the row, and a delete also closes\n // the row. Only DbClient collections retain these until cleanup because\n // hydration has no completion boundary.\n public appliedAdapterKeys?: Map<TKey, boolean>\n public hasAppliedAdapterTruncate = false\n /** Held seeds that the applied adapter truncate kept (decision 20). */\n public adapterTruncateKeptKeys = new Set<TKey>()\n\n // Optimistic state tracking - make public for testing\n public optimisticUpserts = new Map<TKey, TOutput>()\n public optimisticDeletes = new Set<TKey>()\n\n // A completed transaction's optimistic row is held only while a queued sync\n // transaction touches its key, so the drop and that sync transaction\n // publish together.\n // The newest completed transaction owns a held key; no row means a delete.\n // Whether a wrapping sync, such as persistence, holds a committed sync\n // transaction for the key that it has not handed to this Collection yet.\n // Such a transaction holds settled optimistic rows like a queued one.\n private isDeferredSyncKey: (key: TKey) => boolean = () => false\n // Those committed transactions themselves, for hydration seed authority.\n public getStagedSyncTransactions: () => Array<StagedSyncTransaction<TKey>> =\n () => []\n public heldOptimisticRows = new Map<\n TKey,\n { owner: Transaction<any>; row?: TOutput }\n >()\n\n /**\n * Tracks Collection attribution for applied source rows. A same-key local\n * mutation can make an independent source write appear 'local'; this map\n * does not identify the source client. Optimistic rows are separately 'local'.\n * Used for the $origin virtual property.\n */\n public rowOrigins = new Map<TKey, VirtualOrigin>()\n\n /**\n * Tracks keys of pending or persisting local mutations for source-write attribution.\n * A same-key source write can receive 'local' even when a peer supplied it.\n */\n public pendingLocalChanges = new Set<TKey>()\n // A successful mutation attributes only the sync writes committed before its\n // optimistic state dropped: those held at its completion boundary. Active or\n // failed mutations must not add to, or erase a sibling's entry in, this set.\n public pendingLocalOrigins = new Set<TKey>()\n\n // Keyed by row key, not row object: adding a WeakMap entry for each\n // published row cost more than the copy it saves. Sync writes, deletes,\n // and cleanup drop a key's entry.\n private virtualPropsCache = new Map<\n TKey,\n {\n row: TOutput\n hasPendingWrites: boolean\n origin: VirtualOrigin\n collectionId: string\n enriched: WithVirtualProps<TOutput, TKey>\n }\n >()\n\n // Cached size for performance\n public size = 0\n\n // State used for computing the change events\n // Hidden keys are captured as undefined so a later recompute cannot become\n // the baseline for a sync commit that must publish that key's change.\n public preSyncVisibleState = new Map<TKey, TOutput | undefined>()\n public preSyncVirtualState = new Map<TKey, VirtualRowProps<TKey>>()\n public recentlySyncedKeys = new Set<TKey>()\n public hasReceivedFirstCommit = false\n public isCommittingSyncTransactions = false\n private isDrainingSyncTransactions = false\n private syncRunGeneration = 0\n public isLocalOnly = false\n /**\n * Set by a local-only Collection for operation types without a user handler.\n * Their direct mutations can be written as synced rows at once.\n */\n public localOnlyDirectWrite:\n | {\n types: ReadonlySet<OperationType>\n write: (mutations: Array<PendingMutation<TOutput>>) => void\n }\n | undefined\n\n /**\n * Creates a new CollectionState manager\n */\n constructor(config: CollectionConfig<TOutput, TKey, TSchema, any>) {\n this.config = config\n this.transactions = new SortedMap<string, Transaction<any>>((a, b) =>\n a.compareCreatedAt(b),\n )\n\n // Set up data storage - always use SortedMap for deterministic iteration.\n // If a custom compare function is provided, use it; otherwise entries are sorted by key only.\n this.syncedData = new SortedMap<TKey, TOutput>(config.compare)\n }\n\n setDeps(deps: {\n collection: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n changes: CollectionChangesManager<TOutput, TKey, TSchema, TInput>\n indexes: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>\n events: CollectionEventsManager\n }) {\n this.collection = deps.collection\n this.lifecycle = deps.lifecycle\n this.changes = deps.changes\n this.indexes = deps.indexes\n this._events = deps.events\n }\n\n /**\n * Snapshot virtual properties from the current or supplied prior state.\n * A row with an optimistic write is local and pending; otherwise it keeps\n * the source row's attribution. Local-only rows are always local without pending writes.\n *\n * This is local mutation status, not backend confirmation: `$hasPendingWrites: false` means the\n * row is not currently affected by an optimistic transaction in this\n * collection's visible state.\n */\n private getVirtualPropsSnapshotForState(\n key: TKey,\n state: {\n rowOrigins: ReadonlyMap<TKey, VirtualOrigin>\n optimisticUpserts: Pick<Map<TKey, unknown>, 'has'>\n optimisticDeletes: Pick<Set<TKey>, 'has'>\n } = this,\n ): VirtualRowProps<TKey> {\n const hasOptimisticChange =\n !this.isLocalOnly &&\n (state.optimisticUpserts.has(key) || state.optimisticDeletes.has(key))\n\n return {\n $hasPendingWrites: hasOptimisticChange,\n $origin:\n this.isLocalOnly || hasOptimisticChange\n ? 'local'\n : (state.rowOrigins.get(key) ?? 'remote'),\n $key: key,\n $collectionId: this.collection.id,\n }\n }\n\n private snapshotRowOriginsForKeys(\n keys: Iterable<TKey>,\n ): Map<TKey, VirtualOrigin> {\n const rowOrigins = new Map<TKey, VirtualOrigin>()\n\n for (const key of keys) {\n const origin = this.rowOrigins.get(key)\n if (origin !== undefined) {\n rowOrigins.set(key, origin)\n }\n }\n\n return rowOrigins\n }\n\n private enrichWithVirtualPropsSnapshot(\n row: TOutput,\n virtualProps: VirtualRowProps<TKey>,\n ): WithVirtualProps<TOutput, TKey> {\n const existingRow = row as Partial<WithVirtualProps<TOutput, TKey>>\n const hasPendingWrites =\n existingRow.$hasPendingWrites ?? virtualProps.$hasPendingWrites\n const origin = existingRow.$origin ?? virtualProps.$origin\n const resolvedKey = existingRow.$key ?? virtualProps.$key\n const collectionId = existingRow.$collectionId ?? virtualProps.$collectionId\n\n const cached = this.virtualPropsCache.get(resolvedKey)\n if (\n cached &&\n cached.row === row &&\n cached.hasPendingWrites === hasPendingWrites &&\n cached.origin === origin &&\n cached.collectionId === collectionId\n ) {\n return cached.enriched\n }\n\n const enriched = {\n ...row,\n $hasPendingWrites: hasPendingWrites,\n $origin: origin,\n $key: resolvedKey,\n $collectionId: collectionId,\n } as WithVirtualProps<TOutput, TKey>\n\n this.virtualPropsCache.set(resolvedKey, {\n row,\n hasPendingWrites,\n origin,\n collectionId,\n enriched,\n })\n\n return enriched\n }\n\n private clearOriginTrackingState(): void {\n this.virtualPropsCache.clear()\n this.rowOrigins.clear()\n this.pendingLocalChanges.clear()\n this.pendingLocalOrigins.clear()\n }\n\n /**\n * Enriches a row with virtual properties using the \"add-if-missing\" pattern.\n * If the row already has virtual properties (from an upstream collection),\n * they are preserved. Otherwise, new values are computed.\n */\n public enrichWithVirtualProps(\n row: TOutput,\n key: TKey,\n ): WithVirtualProps<TOutput, TKey> {\n return this.enrichWithVirtualPropsSnapshot(\n row,\n this.getVirtualPropsSnapshotForState(key),\n )\n }\n\n /**\n * Visible entries whose stored row passes `prefilter`, enriched with virtual\n * properties. Rows that fail are never enriched.\n */\n public *entriesPassing(\n prefilter: (row: object) => boolean,\n ): IterableIterator<[TKey, WithVirtualProps<TOutput, TKey>]> {\n // Without optimistic state, the visible rows are the synced rows in order.\n const rows =\n this.optimisticUpserts.size === 0 && this.optimisticDeletes.size === 0\n ? this.syncedData\n : this.entries()\n for (const [key, row] of rows) {\n if (prefilter(row)) yield [key, this.enrichWithVirtualProps(row, key)]\n }\n }\n\n /**\n * Creates a change message with virtual properties.\n * Uses the \"add-if-missing\" pattern so that pass-through from upstream\n * collections works correctly.\n */\n public enrichChangeMessage(\n change: ChangeMessage<TOutput, TKey>,\n ): ChangeMessage<WithVirtualProps<TOutput, TKey>, TKey> {\n const { __virtualProps } = change as InternalChangeMessage<TOutput, TKey>\n // The cache holds one row per key, so the previous row goes first and\n // the published value stays the row that later reads return.\n const enrichedPreviousValue = change.previousValue\n ? this.enrichWithVirtualPropsSnapshot(\n change.previousValue,\n __virtualProps?.previousValue ??\n this.getVirtualPropsSnapshotForState(change.key),\n )\n : undefined\n const enrichedValue = this.enrichWithVirtualPropsSnapshot(\n change.value,\n __virtualProps?.value ?? this.getVirtualPropsSnapshotForState(change.key),\n )\n // A deleted key, such as a rolled-back insert, has no row to read again.\n if (change.type === `delete`) this.virtualPropsCache.delete(change.key)\n\n return {\n key: change.key,\n type: change.type,\n value: enrichedValue,\n previousValue: enrichedPreviousValue,\n metadata: change.metadata,\n } as ChangeMessage<WithVirtualProps<TOutput, TKey>, TKey>\n }\n\n /**\n * Get the current value for a key enriched with virtual properties.\n */\n public getWithVirtualProps(\n key: TKey,\n ): WithVirtualProps<TOutput, TKey> | undefined {\n const value = this.get(key)\n if (value === undefined) {\n return undefined\n }\n return this.enrichWithVirtualProps(value, key)\n }\n\n /**\n * Read a key from the current optimistic layer, or a supplied prior layer.\n * Both layers fall back to the current synced rows.\n */\n public get(\n key: TKey,\n optimisticUpserts = this.optimisticUpserts,\n optimisticDeletes = this.optimisticDeletes,\n ): TOutput | undefined {\n // Check if optimistically deleted\n if (optimisticDeletes.has(key)) {\n return undefined\n }\n\n // Rows are objects, so undefined from get means there is no upsert.\n return optimisticUpserts.get(key) ?? this.syncedData.get(key)\n }\n\n /**\n * Check if a key exists in the collection (virtual derived state)\n */\n public has(key: TKey): boolean {\n const { optimisticDeletes, optimisticUpserts, syncedData } = this\n // Check if optimistically deleted\n if (optimisticDeletes.has(key)) {\n return false\n }\n\n return optimisticUpserts.has(key) || syncedData.has(key)\n }\n\n /**\n * Get all keys (virtual derived state)\n */\n public *keys(): IterableIterator<TKey> {\n const { syncedData, optimisticDeletes, optimisticUpserts } = this\n // Yield keys from synced data, skipping any that are deleted.\n for (const key of syncedData.keys()) {\n if (!optimisticDeletes.has(key)) {\n yield key\n }\n }\n // Yield keys from upserts that were not already in synced data.\n for (const key of optimisticUpserts.keys()) {\n if (!syncedData.has(key) && !optimisticDeletes.has(key)) {\n // The optimisticDeletes check is technically redundant if inserts/updates always remove from deletes,\n // but it's safer to keep it.\n yield key\n }\n }\n }\n\n /**\n * Get all values (virtual derived state)\n */\n public *values(): IterableIterator<TOutput> {\n for (const key of this.keys()) {\n const value = this.get(key)\n if (value !== undefined) {\n yield value\n }\n }\n }\n\n /**\n * Get all entries (virtual derived state)\n */\n public *entries(): IterableIterator<[TKey, TOutput]> {\n for (const key of this.keys()) {\n const value = this.get(key)\n if (value !== undefined) {\n yield [key, value]\n }\n }\n }\n\n /**\n * Get all entries (virtual derived state)\n */\n public [Symbol.iterator](): IterableIterator<[TKey, TOutput]> {\n return this.entries()\n }\n\n /**\n * Execute a callback for each entry in the collection\n */\n public forEach(\n callbackfn: (value: TOutput, key: TKey, index: number) => void,\n ): void {\n let index = 0\n for (const [key, value] of this.entries()) {\n callbackfn(value, key, index++)\n }\n }\n\n /**\n * Create a new array with the results of calling a function for each entry in the collection\n */\n public map<U>(\n callbackfn: (value: TOutput, key: TKey, index: number) => U,\n ): Array<U> {\n const result: Array<U> = []\n let index = 0\n for (const [key, value] of this.entries()) {\n result.push(callbackfn(value, key, index++))\n }\n return result\n }\n\n /**\n * Lets a wrapping sync report which keys have committed sync transactions\n * it has not handed to this Collection yet.\n */\n public setDeferredSyncKeys(\n isDeferred: (key: TKey) => boolean,\n getStaged: () => Array<StagedSyncTransaction<TKey>> = () => [],\n ): void {\n this.isDeferredSyncKey = isDeferred\n this.getStagedSyncTransactions = getStaged\n }\n\n /**\n * Recompute optimistic state from active transactions\n */\n public recomputeOptimisticState(\n triggeredByUserAction: boolean = false,\n ): void {\n // Skip redundant recalculations when we're in the middle of committing sync transactions\n // While the sync pipeline is replaying a large batch we still want to honour\n // fresh optimistic mutations from the UI. Only skip recompute for the\n // internal sync-driven redraws; user-triggered work (triggeredByUserAction)\n // must run so live queries stay responsive during long commits.\n if (this.isCommittingSyncTransactions && !triggeredByUserAction) {\n return\n }\n\n const previousState = new Map(this.optimisticUpserts)\n const previousDeletes = new Set(this.optimisticDeletes)\n const previousRowOrigins = this.rowOrigins\n\n // Hold completed optimistic rows, and their local attribution, only while\n // an accepted, queued sync transaction touches them; an open one is not\n // accepted yet. That sync was committed before\n // the optimistic state dropped; a later one is remote.\n const pendingSyncKeys = new Set<TKey>()\n for (const transaction of this.pendingSyncedTransactions) {\n if (!transaction.committed) continue\n for (const operation of transaction.operations) {\n pendingSyncKeys.add(operation.key as TKey)\n }\n }\n const isPendingSync = (key: TKey) =>\n pendingSyncKeys.has(key) || this.isDeferredSyncKey(key)\n for (const transaction of this.transactions.values()) {\n if (transaction.state !== `completed`) continue\n for (const mutation of transaction.mutations) {\n if (\n mutation.collection !== this.collection ||\n !isPendingSync(mutation.key)\n )\n continue\n this.pendingLocalOrigins.add(mutation.key)\n if (!mutation.optimistic) continue\n // A completed transaction leaves `transactions` before a newer one\n // settles, so keep the newest owner's row.\n const held = this.heldOptimisticRows.get(mutation.key)\n if (held && held.owner.compareCreatedAt(transaction) > 0) continue\n this.heldOptimisticRows.set(mutation.key, {\n owner: transaction,\n row: mutation.type === `delete` ? undefined : mutation.modified,\n })\n }\n }\n\n // Clear current optimistic state\n this.optimisticUpserts.clear()\n this.optimisticDeletes.clear()\n this.pendingLocalChanges.clear()\n\n this.overlayHeldAndActive(isPendingSync)\n\n // Update cached size\n this.size = this.calculateSize()\n\n // Collect events for changes\n const events: Array<InternalChangeMessage<TOutput, TKey>> = []\n this.collectOptimisticChanges(\n previousState,\n previousDeletes,\n previousRowOrigins,\n events,\n )\n\n // A user action publishes all its events. Otherwise the sync drain\n // already published the recently synced keys.\n const filteredEvents = triggeredByUserAction\n ? events\n : events.filter((event) => !this.recentlySyncedKeys.has(event.key))\n if (filteredEvents.length > 0) this.indexes.updateIndexes(filteredEvents)\n this.changes.emitEvents(filteredEvents, triggeredByUserAction)\n }\n\n /**\n * Tracks `transaction`. Returns `false` when this Collection already tracks\n * it. A different unsettled transaction with the same id is a contract\n * violation: ids are unique.\n */\n public trackTransaction(transaction: Transaction<any>): boolean {\n const tracked = this.transactions.get(transaction.id)\n if (tracked === transaction) return false\n if (tracked && tracked.state !== `completed` && tracked.state !== `failed`)\n throw new DuplicateTransactionIdError(transaction.id)\n this.transactions.set(transaction.id, transaction)\n transaction.collections.add(this.collection)\n return true\n }\n\n /**\n * Overlay held settled rows, then still-active transactions. Given which\n * keys have a committed sync transaction that has not applied, first end\n * every other hold and attribution; a deferred one can be dropped without\n * applying.\n */\n private overlayHeldAndActive(isPendingSync?: (key: TKey) => boolean): void {\n if (isPendingSync) {\n for (const key of this.heldOptimisticRows.keys()) {\n if (!isPendingSync(key)) this.heldOptimisticRows.delete(key)\n }\n for (const key of this.pendingLocalOrigins) {\n if (!isPendingSync(key)) this.pendingLocalOrigins.delete(key)\n }\n }\n for (const [key, { row }] of this.heldOptimisticRows) {\n if (row === undefined) this.optimisticDeletes.add(key)\n else this.optimisticUpserts.set(key, row)\n }\n this.overlayActiveTransactions()\n }\n\n /**\n * Overlay still-active optimistic mutations on the current layers and\n * record their keys as pending local changes for $origin tracking.\n *\n * A settled transaction leaves `transactions` here, by its own entry. A\n * recompute calls this after it records held rows, and a sync commit calls\n * it after it skips those recomputes.\n */\n private overlayActiveTransactions(): void {\n for (const [id, transaction] of this.transactions) {\n if (transaction.state === `completed` || transaction.state === `failed`) {\n // Defer key-array changes until the next ordered read, so pruning the\n // current entry cannot skip the next transaction in this iteration.\n this.transactions.delete(id, true)\n continue\n }\n // Settlement can outlive cleanup. Keep pruning settled transactions,\n // but do not republish a sibling from the discarded sync run.\n if (this.lifecycle.hasStartedCleanup()) continue\n for (const mutation of transaction.mutations) {\n if (mutation.collection !== this.collection) continue\n this.pendingLocalChanges.add(mutation.key)\n if (!mutation.optimistic) continue\n if (mutation.type === `delete`) {\n this.optimisticUpserts.delete(mutation.key)\n this.optimisticDeletes.add(mutation.key)\n } else {\n this.optimisticUpserts.set(mutation.key, mutation.modified)\n this.optimisticDeletes.delete(mutation.key)\n }\n }\n }\n }\n\n /**\n * Calculate the current size based on synced data and optimistic changes\n */\n private calculateSize(): number {\n let size = this.syncedData.size\n for (const key of this.optimisticDeletes) {\n if (this.syncedData.has(key) && !this.optimisticUpserts.has(key)) size--\n }\n for (const key of this.optimisticUpserts.keys()) {\n if (!this.syncedData.has(key)) size++\n }\n return size\n }\n\n /**\n * Collect events for optimistic changes\n */\n private collectOptimisticChanges(\n previousUpserts: Map<TKey, TOutput>,\n previousDeletes: Set<TKey>,\n previousRowOrigins: ReadonlyMap<TKey, VirtualOrigin>,\n events: Array<InternalChangeMessage<TOutput, TKey>>,\n ): void {\n const allKeys = new Set([\n ...previousUpserts.keys(),\n ...this.optimisticUpserts.keys(),\n ...previousDeletes,\n ...this.optimisticDeletes,\n ])\n\n for (const key of allKeys) {\n const currentValue = this.get(key)\n const previousValue = this.get(key, previousUpserts, previousDeletes)\n const previousVirtualProps = this.getVirtualPropsSnapshotForState(key, {\n rowOrigins: previousRowOrigins,\n optimisticUpserts: previousUpserts,\n optimisticDeletes: previousDeletes,\n })\n const nextVirtualProps = this.getVirtualPropsSnapshotForState(key)\n\n if (previousValue !== undefined && currentValue === undefined) {\n events.push({\n type: `delete`,\n key,\n value: previousValue,\n __virtualProps: {\n value: previousVirtualProps,\n },\n })\n } else if (previousValue === undefined && currentValue !== undefined) {\n events.push({\n type: `insert`,\n key,\n value: currentValue,\n __virtualProps: {\n value: nextVirtualProps,\n },\n })\n } else if (\n previousValue !== undefined &&\n currentValue !== undefined &&\n (!deepEquals(previousValue, currentValue) ||\n previousVirtualProps.$origin !== nextVirtualProps.$origin ||\n previousVirtualProps.$hasPendingWrites !==\n nextVirtualProps.$hasPendingWrites)\n ) {\n events.push({\n type: `update`,\n key,\n value: currentValue,\n previousValue,\n __virtualProps: {\n value: nextVirtualProps,\n previousValue: previousVirtualProps,\n },\n })\n }\n }\n }\n\n /** Build once per output flush; queued membership excludes optimistic edits. */\n createSyncedKeyLookup(): (key: TKey) => boolean {\n if (this.pendingSyncedTransactions.length === 0)\n return (key) => this.syncedData.has(key)\n const queued = new Map<TKey, boolean>()\n let truncated = false\n for (const transaction of this.pendingSyncedTransactions) {\n if (!transaction.committed) continue\n if (transaction.truncate) {\n queued.clear()\n truncated = true\n }\n for (const operation of transaction.operations) {\n queued.set(operation.key as TKey, operation.type !== `delete`)\n }\n }\n return (key) => queued.get(key) ?? (!truncated && this.syncedData.has(key))\n }\n\n enableHydrationAuthorityTracking(): void {\n this.appliedAdapterKeys ??= new Map<TKey, boolean>()\n }\n\n private getProjectedSyncedKeyState(\n projection: PendingSyncedProjection<TOutput, TKey>,\n key: TKey,\n ): PendingSyncedKeyState<TOutput> {\n const state = projection.states.get(key)\n if (state !== undefined) return state\n if (projection.truncated) return { exists: false, value: undefined }\n return {\n exists: this.syncedData.has(key),\n value: this.syncedData.get(key),\n }\n }\n\n /**\n * The synced row once every accepted sync transaction applies. A queued\n * transaction is accepted before it is visible, so a direct write must\n * read this rather than `syncedData`.\n */\n getAcceptedSyncedRow(key: TKey): TOutput | undefined {\n return this.getProjectedSyncedKeyState(this.pendingSyncedProjection, key)\n .value\n }\n\n /**\n * Accept a committed transaction in commit order: after every accepted\n * transaction and ahead of every open one. A transaction begun inside an\n * open one is independent, so when it commits first it also applies, and\n * the source reads it, beneath that open transaction. A seed, such as a\n * DbClient hydration chunk, is accepted the same way, so an open source\n * transaction's `commit()` still targets its own writes.\n */\n acceptSyncTransaction(\n transaction: PendingSyncedTransaction<TOutput, TKey>,\n ): void {\n const queue = this.pendingSyncedTransactions\n const index = queue.indexOf(transaction)\n if (index !== -1) queue.splice(index, 1)\n const open = queue.findIndex((pending) => !pending.committed)\n const position = open === -1 ? queue.length : open\n queue.splice(position, 0, transaction)\n if (position !== index) this.refreshPendingSyncedProjection()\n this.commitPendingTransactions()\n }\n\n /** A retired sync run's open transaction can never commit. */\n discardOpenSyncTransactions(): void {\n const committed = this.pendingSyncedTransactions.filter(\n (transaction) => transaction.committed,\n )\n if (committed.length === this.pendingSyncedTransactions.length) return\n this.pendingSyncedTransactions = committed\n this.refreshPendingSyncedProjection()\n }\n\n /** Whether the newest sync transaction is still open for writes. */\n hasOpenSyncTransaction(): boolean {\n return this.pendingSyncedTransactions.at(-1)?.committed === false\n }\n\n /** Whether an accepted sync transaction is not yet visible. */\n hasHeldSyncTransaction(): boolean {\n return this.pendingSyncedTransactions.some(\n (transaction) => transaction.committed,\n )\n }\n\n /**\n * Every synced row once every accepted sync transaction applies: the\n * baseline a diffing adapter writes against, also during a reload. Inside\n * an open snapshot or truncate, only that transaction's writes.\n */\n *acceptedSyncedEntries(): IterableIterator<[TKey, TOutput]> {\n const { states, truncated } = this.pendingSyncedProjection\n if (!truncated) {\n for (const entry of this.syncedData.entries()) {\n if (!states.has(entry[0])) yield entry\n }\n }\n for (const [key, state] of states) {\n if (state.exists) yield [key, state.value!]\n }\n }\n\n private classifyProjectedInsert(\n projection: PendingSyncedProjection<TOutput, TKey>,\n key: TKey,\n value: TOutput,\n ): PendingInsertDisposition {\n const current = this.getProjectedSyncedKeyState(projection, key)\n if (!current.exists) return `insert`\n // A seed is older than every source write, so an insert replaces a row\n // that only a seed supplied. Over a row the source wrote, it is judged\n // like any insert, holds and seeds notwithstanding.\n if (this.hydrationSeedKeys.has(key) && !projection.sourceKeys.has(key))\n return `insert`\n if (current.value !== undefined && deepEquals(current.value, value)) {\n return `update`\n }\n return `duplicate`\n }\n\n /**\n * A partial update merges over the row before it. An insert names the\n * whole row, even as an equal re-insert, and replaces it.\n */\n private mergesOverRow(operation: PendingSyncOperation<TOutput, TKey>) {\n return (\n operation.type === `update` &&\n operation.originalSyncType !== `insert` &&\n (this.config.sync.rowUpdateMode || `partial`) === `partial`\n )\n }\n\n /** Classify an adapter insert against retained and queued source state. */\n classifyPendingSyncedInsert(\n key: TKey,\n value: TOutput,\n ): PendingInsertDisposition {\n return this.classifyProjectedInsert(\n this.pendingSyncedProjection,\n key,\n value,\n )\n }\n\n private applyPendingSyncOperation(\n projection: PendingSyncedProjection<TOutput, TKey>,\n operation: PendingSyncOperation<TOutput, TKey>,\n ): void {\n const key = operation.key as TKey\n if (operation.type === `delete`) {\n projection.states.set(key, { exists: false, value: undefined })\n } else if (this.mergesOverRow(operation)) {\n const current = this.getProjectedSyncedKeyState(projection, key)\n projection.states.set(key, {\n exists: true,\n // Spread defines own fields; assignment would run a `__proto__` setter.\n value: { ...current.value, ...operation.value },\n })\n } else {\n projection.states.set(key, { exists: true, value: operation.value })\n }\n }\n\n /**\n * Extend the queued projection after admitting one sync operation. A key\n * its transaction keeps as a seed's is no source write, as in the rebuild.\n */\n stagePendingSyncOperation(\n operation: PendingSyncOperation<TOutput, TKey>,\n preserved?: boolean,\n ): void {\n this.applyPendingSyncOperation(this.pendingSyncedProjection, operation)\n if (!preserved)\n this.pendingSyncedProjection.sourceKeys.add(operation.key as TKey)\n }\n\n private rebuildAutomaticRowMetadataWrites(\n transaction: PendingSyncedTransaction<TOutput, TKey>,\n ): void {\n // A rebuild can reclassify an operation. Last write wins: each key's\n // last explicit write holds unless a later operation writes the key.\n const explicit = transaction.explicitRowMetadataWrites\n const writes = transaction.rowMetadataWrites\n for (const operation of transaction.operations)\n writes.delete(operation.key as TKey)\n for (const [key, last] of explicit) writes.set(key, last.write)\n transaction.operations.forEach((operation, position) => {\n const key = operation.key as TKey\n if (position < (explicit.get(key)?.position ?? 0)) return\n const metadataWrite = automaticRowMetadataWrite(operation)\n if (metadataWrite) writes.set(key, metadataWrite)\n })\n }\n\n /**\n * Rebuild the queued projection after truncate, application, or an\n * accepted transaction changes queue history. An accepted transaction keeps\n * the operation kinds it was accepted with, even when it commits ahead of\n * an open transaction it began inside: its insert names the whole row. An\n * open transaction's inserts follow the rows before it, so it can become\n * invalid when a later transaction begun inside it commits first; it then\n * holds an invalidation error that its commit returns.\n */\n private rebuildPendingSyncedProjection(): void {\n const projection: PendingSyncedProjection<TOutput, TKey> = {\n states: new Map(),\n truncated: false,\n sourceKeys: new Set(),\n }\n // The source keys that an accepted transaction writes.\n const acceptedSourceKeys = new Set<TKey>()\n\n for (const transaction of this.pendingSyncedTransactions) {\n if (transaction.invalidationError !== undefined) continue\n // Only an open transaction can become invalid and need this rollback.\n const before = transaction.committed\n ? undefined\n : {\n states: new Map(projection.states),\n truncated: projection.truncated,\n sourceKeys: new Set(projection.sourceKeys),\n }\n if (transaction.truncate) {\n projection.states = new Map()\n projection.truncated = true\n }\n\n let invalidKey: TKey | undefined\n for (const operation of transaction.operations) {\n const key = operation.key as TKey\n // A seed beneath an open insert of a row the source also wrote can\n // change that row, but not the insert's kind: it stays what the\n // source wrote. An accepted source write makes the row the source's,\n // as its application does.\n if (\n !transaction.committed &&\n operation.originalSyncType === `insert` &&\n operation.type !== `delete` &&\n !(\n this.hydrationSeedKeys.has(key) &&\n projection.sourceKeys.has(key) &&\n !acceptedSourceKeys.has(key)\n )\n ) {\n const disposition = this.classifyProjectedInsert(\n projection,\n key,\n operation.value,\n )\n if (disposition === `duplicate`) {\n invalidKey = key\n break\n }\n operation.type = disposition\n }\n this.applyPendingSyncOperation(projection, operation)\n if (!transaction.preserveHydrationSeedKeys?.has(key)) {\n projection.sourceKeys.add(key)\n if (transaction.committed) acceptedSourceKeys.add(key)\n }\n }\n if (invalidKey !== undefined) {\n Object.assign(projection, before)\n transaction.invalidationError =\n transaction.duplicateKeyError?.(invalidKey) ??\n new SyncTransactionAbortedError()\n continue\n }\n if (!transaction.committed)\n this.rebuildAutomaticRowMetadataWrites(transaction)\n }\n\n this.pendingSyncedProjection = projection\n }\n\n /** Rebuild after truncate, application, or an accepted seed. */\n refreshPendingSyncedProjection(): void {\n this.rebuildPendingSyncedProjection()\n }\n\n /**\n * Attempts to commit pending synced transactions if there are no active transactions\n * This method processes operations from pending transactions and applies them to the synced data\n */\n commitPendingTransactions = () => {\n if (this.isDrainingSyncTransactions) return\n this.isDrainingSyncTransactions = true\n let failed = false\n let firstError: unknown\n try {\n let result: { processed: boolean; failure?: { error: unknown } }\n do {\n result = this.commitNextPendingTransactionBatch()\n if (result.failure && !failed) {\n failed = true\n firstError = result.failure.error\n }\n } while (result.processed)\n } finally {\n this.isDrainingSyncTransactions = false\n }\n if (failed) throw firstError\n }\n\n hasPersistingTransaction(): boolean {\n for (const transaction of this.transactions.values()) {\n if (transaction.state === `persisting`) return true\n }\n return false\n }\n\n private commitNextPendingTransactionBatch(): {\n processed: boolean\n failure?: { error: unknown }\n } {\n const syncRunGeneration = this.syncRunGeneration\n const hasPersistingTransaction = this.hasPersistingTransaction()\n\n // pending synced transactions could be either `committed` or still open.\n // we only want to process `committed` transactions here\n const committedSyncedTransactions: Array<\n PendingSyncedTransaction<TOutput, TKey>\n > = []\n const uncommittedSyncedTransactions: Array<\n PendingSyncedTransaction<TOutput, TKey>\n > = []\n let hasTruncateSync = false\n let truncateMarksReady = false\n let layoutChanged = false\n for (const t of this.pendingSyncedTransactions) {\n if (t.committed) {\n committedSyncedTransactions.push(t)\n layoutChanged ||= t.layoutChanged\n if (t.truncate) {\n hasTruncateSync = true\n truncateMarksReady = t.truncateMarkReady !== false\n }\n } else {\n uncommittedSyncedTransactions.push(t)\n }\n }\n\n if (committedSyncedTransactions.length === 0) {\n return { processed: false }\n }\n\n // A persisting transaction holds sync transactions until it settles. A\n // truncate applies at once, with every committed transaction before it,\n // so later application cannot overwrite newer state.\n if (!hasPersistingTransaction || hasTruncateSync) {\n const previousLayout = layoutChanged ? [...this.keys()] : undefined\n this.pendingSyncedTransactions = uncommittedSyncedTransactions\n\n // Application is now the point of no return. Event listeners run before\n // the receipts resolve, so a signal aborted from one of those listeners\n // must not cancel writes that are already becoming visible.\n const deferOrder =\n committedSyncedTransactions.reduce(\n (count, transaction) => count + transaction.operations.length,\n 0,\n ) >= 512\n for (const transaction of committedSyncedTransactions) {\n transaction.applicationStarted = true\n }\n\n // Set flag to prevent redundant optimistic state recalculations\n this.isCommittingSyncTransactions = true\n\n // First collect all keys that will be affected by sync operations\n const changedKeys = new Set<TKey>()\n const firstSyncOperations = new Map<\n TKey,\n OptimisticChangeMessage<TOutput>\n >()\n for (const transaction of committedSyncedTransactions) {\n for (const operation of transaction.operations) {\n const key = operation.key as TKey\n changedKeys.add(key)\n if (!firstSyncOperations.has(key))\n firstSyncOperations.set(key, operation)\n }\n for (const [key] of transaction.rowMetadataWrites) {\n changedKeys.add(key)\n }\n }\n\n const previousRowOrigins = this.snapshotRowOriginsForKeys(changedKeys)\n const previousOptimisticUpserts = new Map(this.optimisticUpserts)\n const previousOptimisticDeletes = new Set(this.optimisticDeletes)\n\n // Use pre-captured state if available (from optimistic scenarios),\n // otherwise capture current state (for pure sync scenarios)\n let currentVisibleState = this.preSyncVisibleState\n if (currentVisibleState.size === 0) {\n // No pre-captured state, capture it now for pure sync operations\n currentVisibleState = new Map<TKey, TOutput | undefined>()\n for (const key of changedKeys) {\n const currentValue = this.get(key)\n if (currentValue !== undefined) {\n currentVisibleState.set(key, currentValue)\n }\n }\n }\n\n const events: Array<ChangeMessage<TOutput, TKey>> = []\n let reappliedKeys: ReadonlySet<TKey> | undefined\n if (hasTruncateSync) {\n // All queued transactions publish as one batch. Its clear prefix must\n // describe the prior visible rows, not intermediate queued writes.\n // Freeze metadata before replacement writes change row attribution.\n for (const [key, value] of this.entries()) {\n events.push({\n type: `delete`,\n key,\n value: this.enrichWithVirtualPropsSnapshot(\n value,\n this.getVirtualPropsSnapshotForState(key),\n ),\n })\n }\n }\n for (const transaction of committedSyncedTransactions) {\n // Handle truncate operations first\n if (transaction.truncate) {\n // TRUNCATE PHASE\n // Clear the authoritative synced base. Subsequent server ops in this\n // same commit will rebuild the base atomically.\n // Keep active local mutations for later source transactions on keys\n // this truncate does not write. Completed attribution is one-use.\n this.syncedData.clear()\n // A wrapping sync's storage read that keeps seed keys replaces\n // rows without truncating the source's authority over them or\n // their metadata. A schema reset on demand truncates all but its\n // kept seeds (decision 20).\n const kept = transaction.sourceTruncate\n ? transaction.preserveHydrationSeedKeys\n : undefined\n if (!transaction.preserveHydrationSeedKeys || kept) {\n // A kept seed keeps the authority a source write fixed over\n // one of its objects too.\n for (const keys of [\n this.syncedMetadata,\n this.hydrationSeedKeys,\n this.hydratedKeys,\n this.appliedAdapterKeys ?? new Set<TKey>(),\n ])\n for (const key of keys.keys())\n if (!kept?.has(key)) keys.delete(key)\n if (this.appliedAdapterKeys) {\n this.hasAppliedAdapterTruncate = true\n this.adapterTruncateKeptKeys = new Set(kept)\n }\n }\n this.virtualPropsCache.clear()\n this.rowOrigins.clear()\n this.pendingLocalOrigins.clear()\n\n // Clear currentVisibleState for truncated keys to ensure subsequent operations\n // are compared against the post-truncate state (undefined) rather than pre-truncate state\n // This ensures that re-inserted keys are emitted as INSERT events, not UPDATE events\n for (const key of changedKeys) {\n currentVisibleState.delete(key)\n }\n\n // Emit truncate event so subscriptions reset their tracking state\n // and replay their on-demand demand.\n this._events.emit(`truncate`, {\n type: `truncate`,\n collection: this.collection,\n })\n }\n\n // Attribution belongs to the whole atomic batch. A repeated write must\n // not forget the local acknowledgement consumed by its first operation.\n const localKeys = new Set<TKey>()\n for (const operation of transaction.operations) {\n const key = operation.key as TKey\n\n // Attribute this source write from active or held same-key mutations.\n const origin: VirtualOrigin =\n this.isLocalOnly ||\n this.pendingLocalChanges.has(key) ||\n this.pendingLocalOrigins.has(key) ||\n localKeys.has(key)\n ? 'local'\n : 'remote'\n if (origin === `local`) localKeys.add(key)\n\n // A sync source may reuse a live-reading row object, making an\n // enriched snapshot cached for an earlier publication stale.\n this.virtualPropsCache.delete(key)\n\n if (operation.type === `delete`) {\n this.syncedData.delete(key, deferOrder)\n this.syncedMetadata.delete(key)\n this.rowOrigins.delete(key)\n } else {\n this.syncedData.set(\n key,\n this.mergesOverRow(operation)\n ? { ...this.syncedData.get(key), ...operation.value }\n : operation.value,\n deferOrder,\n )\n this.rowOrigins.set(key, origin)\n }\n // Sync has confirmed the key, so local tracking for it ends. A\n // deferred transaction on the key still holds its settled row.\n this.pendingLocalChanges.delete(key)\n this.pendingLocalOrigins.delete(key)\n if (!this.isDeferredSyncKey(key)) this.heldOptimisticRows.delete(key)\n if (!transaction.preserveHydrationSeedKeys?.has(key)) {\n this.hydrationSeedKeys.delete(key)\n this.hydratedKeys.delete(key)\n // A write that brings a deleted row back keeps the metadata the\n // delete cleared.\n if (operation.type === `delete`)\n this.appliedAdapterKeys?.set(key, true)\n else if (this.appliedAdapterKeys?.get(key))\n this.appliedAdapterKeys.set(key, false)\n }\n }\n\n for (const [key, metadataWrite] of transaction.rowMetadataWrites) {\n if (\n !transaction.preserveHydrationSeedKeys?.has(key) &&\n !this.appliedAdapterKeys?.has(key)\n )\n this.appliedAdapterKeys?.set(key, false)\n if (metadataWrite.type === `delete`) {\n this.syncedMetadata.delete(key)\n continue\n }\n this.syncedMetadata.set(key, metadataWrite.value)\n }\n\n for (const [\n key,\n metadataWrite,\n ] of transaction.collectionMetadataWrites) {\n if (metadataWrite.type === `delete`) {\n this.syncedCollectionMetadata.delete(key)\n continue\n }\n this.syncedCollectionMetadata.set(key, metadataWrite.value)\n }\n }\n this.syncedData.restoreOrder()\n\n // The retained base now includes every removed committed transaction.\n // Rebuild only the projection for still-open transactions.\n this.refreshPendingSyncedProjection()\n\n // Maintain optimistic state appropriately\n // Clear optimistic state since sync operations will now provide the authoritative data.\n // Any still-active user transactions will be re-applied below in recompute.\n this.optimisticUpserts.clear()\n this.optimisticDeletes.clear()\n\n // Reset flag and recompute optimistic state for any remaining active transactions\n this.isCommittingSyncTransactions = false\n\n // A settled row that a deferred transaction still holds stays over the\n // new base. Truncate clears attribution with the old base, not the\n // still-live local requests, so active transactions overlay it too.\n this.overlayHeldAndActive()\n\n // After applying synced operations, if this commit included a truncate,\n // re-apply optimistic mutations on top of the fresh synced base. This ensures\n // the UI preserves local intent while respecting server rebuild semantics.\n // Ordering: deletes (above) -> server ops (just applied) -> optimistic upserts.\n if (hasTruncateSync) {\n // Events use the same rebuilt overlay as synchronous reads. Until\n // this point the batch holds only the truncate delete prefix, so each\n // re-applied upsert publishes as an insert after it. A key is never\n // both an optimistic upsert and an optimistic delete.\n for (const [key, value] of this.optimisticUpserts) {\n events.push({ type: `insert`, key, value })\n }\n\n // The changed-key loop below must not publish these keys again.\n reappliedKeys = new Set(this.optimisticUpserts.keys())\n }\n\n // Now check what actually changed in the final visible state\n for (const key of changedKeys) {\n // Truncate already published each re-applied upsert as an insert.\n if (reappliedKeys?.has(key)) continue\n const firstSyncOperation = firstSyncOperations.get(key)\n // A live-reading source can change a reused row before this commit\n // captures it. Later writes must not substitute an intermediate value.\n const syncPreviousValue =\n firstSyncOperation?.type === `update` &&\n currentVisibleState.get(key) === firstSyncOperation.value\n ? firstSyncOperation.previousValue\n : undefined\n const previousVisibleValue =\n !hasTruncateSync &&\n !previousOptimisticUpserts.has(key) &&\n !previousOptimisticDeletes.has(key) &&\n syncPreviousValue !== undefined\n ? syncPreviousValue\n : currentVisibleState.get(key)\n const newVisibleValue = this.get(key) // This returns the new derived state\n\n if (previousVisibleValue === undefined) {\n if (newVisibleValue === undefined) continue\n // Subscribers last saw this key absent, whatever a completed\n // optimistic request held. Batching composes a buffered delete with\n // this insert into an update.\n events.push({ type: `insert`, key, value: newVisibleValue })\n continue\n }\n // Only deletes and updates describe the previous row.\n const previousVirtualProps =\n this.preSyncVirtualState.get(key) ??\n this.getVirtualPropsSnapshotForState(key, {\n rowOrigins: previousRowOrigins,\n optimisticUpserts: previousOptimisticUpserts,\n optimisticDeletes: previousOptimisticDeletes,\n })\n const withPreviousVirtualProps = (value: TOutput) =>\n enrichRowWithVirtualProps(\n value,\n key,\n this.collection.id,\n () => previousVirtualProps.$hasPendingWrites,\n () => previousVirtualProps.$origin,\n )\n\n if (newVisibleValue === undefined) {\n events.push({\n type: `delete`,\n key,\n value: withPreviousVirtualProps(previousVisibleValue),\n })\n continue\n }\n const nextVirtualProps = this.getVirtualPropsSnapshotForState(key)\n if (\n previousVirtualProps.$hasPendingWrites !==\n nextVirtualProps.$hasPendingWrites ||\n previousVirtualProps.$origin !== nextVirtualProps.$origin ||\n !deepEquals(previousVisibleValue, newVisibleValue)\n ) {\n events.push({\n type: `update`,\n key,\n value: newVisibleValue,\n previousValue: withPreviousVirtualProps(previousVisibleValue),\n })\n }\n }\n\n // Update cached size after synced data changes\n this.size = this.calculateSize()\n\n // Update indexes for all events before emitting\n if (events.length > 0) {\n this.indexes.updateIndexes(events)\n }\n\n // End batching and emit all events (combines any batched events with sync events)\n // Subscribers and ready callbacks can throw. Keep the first error so\n // the applied receipts below still settle.\n let failure: { error: unknown } | undefined\n const capture = (step: () => void) => {\n try {\n step()\n } catch (error) {\n failure ??= { error }\n }\n }\n const visibleLayoutChanged =\n previousLayout !== undefined &&\n (previousLayout.length !== this.size ||\n [...this.keys()].some((key, index) => key !== previousLayout[index]))\n // markReady may skip its transition, and then the batch still emits.\n let emitted = false as boolean\n const emit = () => {\n emitted = true\n capture(() =>\n this.changes.emitEvents(events, true, visibleLayoutChanged),\n )\n }\n // A truncate that makes the Collection ready publishes its batch after\n // the status reads ready and before status listeners and ready\n // callbacks run, so their writes follow the batch they describe.\n // During a reload, that is the reload's completion.\n if (truncateMarksReady && this.lifecycle.status !== `ready`)\n capture(() => this.lifecycle.markReady(emit))\n if (!emitted) emit()\n // A replacement that applies completes a reload of a ready Collection.\n if (hasTruncateSync && this.lifecycle.status === `ready`)\n capture(() => this.lifecycle.completeReload())\n\n if (this.syncRunGeneration === syncRunGeneration) {\n this.preSyncVisibleState.clear()\n this.preSyncVirtualState.clear()\n Promise.resolve().then(() => {\n if (this.syncRunGeneration === syncRunGeneration) {\n this.recentlySyncedKeys.clear()\n }\n })\n this.hasReceivedFirstCommit = true\n }\n\n for (const transaction of committedSyncedTransactions) {\n transaction.applied.resolve()\n }\n return { processed: true, failure }\n }\n\n return { processed: false }\n }\n\n /**\n * Abandons the open last sync transaction before acceptance. Only\n * `commit(signal)` with an aborted signal reaches this, so no other\n * transaction can depend on the one canceled.\n */\n public cancelPendingSyncedTransaction(\n transaction: PendingSyncedTransaction<TOutput, TKey>,\n reason: Error = new SyncTransactionAbortedError(),\n ): void {\n if (\n transaction.committed ||\n this.pendingSyncedTransactions.at(-1) !== transaction\n )\n throw new SyncQueueInvariantError(\n `only the open last sync transaction can be canceled`,\n )\n this.pendingSyncedTransactions.pop()\n const canceledKeys = new Set<TKey>()\n for (const operation of transaction.operations) {\n canceledKeys.add(operation.key as TKey)\n }\n transaction.applied.reject(reason)\n this.rebuildPendingSyncedProjection()\n\n const remainingPendingKeys = new Set<TKey>()\n for (const pending of this.pendingSyncedTransactions) {\n if (pending.invalidationError !== undefined) continue\n for (const operation of pending.operations) {\n remainingPendingKeys.add(operation.key as TKey)\n }\n }\n for (const key of canceledKeys) {\n if (!remainingPendingKeys.has(key)) {\n this.recentlySyncedKeys.delete(key)\n this.preSyncVisibleState.delete(key)\n this.preSyncVirtualState.delete(key)\n }\n }\n\n if (this.pendingSyncedTransactions.length === 0) {\n this.preSyncVisibleState.clear()\n this.preSyncVirtualState.clear()\n this.recentlySyncedKeys.clear()\n this.changes.emitEvents([], true)\n } else {\n // Recompute after removing the canceled keys so optimistic cleanup is\n // no longer suppressed by a sync transaction that will never publish.\n this.recomputeOptimisticState(false)\n }\n }\n\n /**\n * Capture visible state for keys that will be affected by pending sync operations\n * This must be called BEFORE onTransactionStateChange clears optimistic state\n */\n public capturePreSyncVisibleState(): void {\n if (this.pendingSyncedTransactions.length === 0) return\n\n // Get all keys that will be affected by sync operations, including\n // metadata-only writes, which the drain also compares.\n const syncedKeys = new Set<TKey>()\n for (const transaction of this.pendingSyncedTransactions) {\n // An open transaction does not publish in this drain.\n if (!transaction.committed) continue\n for (const operation of transaction.operations) {\n syncedKeys.add(operation.key as TKey)\n }\n for (const key of transaction.rowMetadataWrites.keys()) {\n syncedKeys.add(key)\n }\n }\n\n // Mark keys as about to be synced to suppress intermediate events from recomputeOptimisticState\n for (const key of syncedKeys) {\n this.recentlySyncedKeys.add(key)\n }\n\n // Only capture current visible state for keys that will be affected by sync operations\n // This is much more efficient than capturing the entire collection state\n // Only capture keys that haven't been captured yet to preserve earlier captures\n for (const key of syncedKeys) {\n if (!this.preSyncVisibleState.has(key)) {\n const currentValue = this.get(key)\n this.preSyncVisibleState.set(key, currentValue)\n if (currentValue !== undefined) {\n this.preSyncVirtualState.set(\n key,\n this.getVirtualPropsSnapshotForState(key),\n )\n }\n }\n }\n }\n\n /**\n * Trigger a recomputation when transactions change\n * This method should be called by the Transaction class when state changes\n */\n public onTransactionStateChange(): void {\n // Batch only when the next sync drain can actually publish. A persisting\n // sibling can keep normal sync queued; it must not hide this rollback.\n const hasPersistingTransaction = this.hasPersistingTransaction()\n this.changes.shouldBatchEvents = this.pendingSyncedTransactions.some(\n (transaction) =>\n transaction.committed &&\n (!hasPersistingTransaction || transaction.truncate),\n )\n\n // CRITICAL: Capture visible state BEFORE clearing optimistic state\n if (this.changes.shouldBatchEvents) this.capturePreSyncVisibleState()\n\n this.recomputeOptimisticState(false)\n }\n\n /**\n * Clean up the collection by stopping sync and clearing data\n * This can be called manually or automatically by garbage collection\n */\n public cleanup(): void {\n this.syncRunGeneration++\n for (const transaction of this.pendingSyncedTransactions) {\n transaction.applied.reject(new SyncTransactionAbortedError())\n }\n this.syncedData.clear()\n this.syncedMetadata.clear()\n this.syncedCollectionMetadata.clear()\n this.optimisticUpserts.clear()\n this.optimisticDeletes.clear()\n this.heldOptimisticRows.clear()\n this.hydrationSeedKeys.clear()\n this.hydratedKeys.clear()\n this.appliedAdapterKeys?.clear()\n this.hasAppliedAdapterTruncate = false\n this.adapterTruncateKeptKeys.clear()\n this.clearOriginTrackingState()\n this.isLocalOnly = false\n this.localOnlyDirectWrite = undefined\n this.size = 0\n this.pendingSyncedTransactions = []\n this.refreshPendingSyncedProjection()\n this.preSyncVisibleState.clear()\n this.preSyncVirtualState.clear()\n this.recentlySyncedKeys.clear()\n this.hasReceivedFirstCommit = false\n }\n}\n"],"names":["pendingSyncedProjection","isDeferredSyncKey","virtualPropsCache","isDrainingSyncTransactions","commitNextPendingTransactionBatch","SortedMap","_events","getVirtualPropsSnapshotForState","snapshotRowOriginsForKeys","enrichWithVirtualPropsSnapshot","virtualProps","clearOriginTrackingState","overlayHeldAndActive","calculateSize","collectOptimisticChanges","DuplicateTransactionIdError","overlayActiveTransactions","deepEquals","getProjectedSyncedKeyState","classifyProjectedInsert","mergesOverRow","applyPendingSyncOperation","rebuildAutomaticRowMetadataWrites","rebuildPendingSyncedProjection","SyncTransactionAbortedError","enrichRowWithVirtualProps","SyncQueueInvariantError"],"mappings":"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"}