{"version":3,"file":"index.cjs","sources":["../../../src/collection/index.ts"],"sourcesContent":["import {\n  CollectionConfigurationError,\n  CollectionRequiresConfigError,\n  CollectionRequiresSyncConfigError,\n} from '../errors'\nimport { currentStateAsChanges } from './change-events'\n\nimport { CollectionStateManager } from './state'\nimport { CollectionChangesManager } from './changes'\nimport { CollectionLifecycleManager } from './lifecycle.js'\nimport { CollectionSyncManager } from './sync'\nimport { CollectionIndexesManager } from './indexes'\nimport { CollectionMutationsManager } from './mutations'\nimport { CollectionEventsManager } from './events.js'\nimport type { CollectionSubscription } from './subscription'\nimport type {\n  AllCollectionEvents,\n  CollectionEventHandler,\n  CollectionIndexMetadata,\n} from './events.js'\nimport type { BaseIndex, IndexConstructor } from '../indexes/base-index.js'\nimport type { IndexOptions } from '../indexes/index-options.js'\nimport type {\n  ChangeMessage,\n  CollectionConfig,\n  CollectionStatus,\n  CurrentStateAsChangesOptions,\n  Fn,\n  InferSchemaInput,\n  InferSchemaOutput,\n  InsertConfig,\n  NonSingleResult,\n  OperationConfig,\n  SingleResult,\n  StringCollationConfig,\n  SubscribeChangesOptions,\n  Transaction as TransactionType,\n  UtilsRecord,\n  WritableDeep,\n} from '../types'\nimport type { SingleRowRefProxy } from '../query/builder/ref-proxy'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { WithVirtualProps } from '../virtual-props.js'\n\nexport type { CollectionIndexMetadata } from './events.js'\n\n/**\n * Enhanced Collection interface that includes both data type T and utilities TUtils\n * @template T - The type of items in the collection\n * @template TKey - The type of the key for the collection\n * @template TUtils - The utilities record type\n * @template TInsertInput - The type for insert operations (can be different from T for schemas with defaults)\n */\nexport interface Collection<\n  T extends object = Record<string, unknown>,\n  TKey extends string | number = string | number,\n  TUtils extends UtilsRecord = UtilsRecord,\n  TSchema extends StandardSchemaV1 = StandardSchemaV1,\n  TInsertInput extends object = T,\n> extends CollectionImpl<T, TKey, TUtils, TSchema, TInsertInput> {\n  readonly utils: TUtils\n  readonly singleResult?: true\n}\n\n/**\n * Creates a new Collection instance with the given configuration\n *\n * @template T - The schema type if a schema is provided, otherwise the type of items in the collection\n * @template TKey - The type of the key for the collection\n * @template TUtils - The utilities record type\n * @param options - Collection options with optional utilities\n * @returns A new Collection with utilities exposed both at top level and under .utils\n *\n * @example\n * // Pattern 1: With operation handlers (direct collection calls)\n * const todos = createCollection({\n *   id: \"todos\",\n *   getKey: (todo) => todo.id,\n *   schema,\n *   onInsert: async ({ transaction, collection }) => {\n *     // Send to API\n *     await api.createTodo(transaction.mutations[0].modified)\n *   },\n *   onUpdate: async ({ transaction, collection }) => {\n *     await api.updateTodo(transaction.mutations[0].modified)\n *   },\n *   onDelete: async ({ transaction, collection }) => {\n *     await api.deleteTodo(transaction.mutations[0].key)\n *   },\n *   sync: { sync: () => {} }\n * })\n *\n * // Direct usage (handlers manage transactions)\n * const tx = todos.insert({ id: \"1\", text: \"Buy milk\", completed: false })\n * await tx.isPersisted.promise\n *\n * @example\n * // Pattern 2: Manual transaction management\n * const todos = createCollection({\n *   getKey: (todo) => todo.id,\n *   schema: todoSchema,\n *   sync: { sync: () => {} }\n * })\n *\n * // Explicit transaction usage\n * const tx = createTransaction({\n *   mutationFn: async ({ transaction }) => {\n *     // Handle all mutations in transaction\n *     await api.saveChanges(transaction.mutations)\n *   }\n * })\n *\n * tx.mutate(() => {\n *   todos.insert({ id: \"1\", text: \"Buy milk\" })\n *   todos.update(\"2\", draft => { draft.completed = true })\n * })\n *\n * await tx.isPersisted.promise\n *\n * @example\n * // Using schema for type inference (preferred as it also gives you client side validation)\n * const todoSchema = z.object({\n *   id: z.string(),\n *   title: z.string(),\n *   completed: z.boolean()\n * })\n *\n * const todos = createCollection({\n *   schema: todoSchema,\n *   getKey: (todo) => todo.id,\n *   sync: { sync: () => {} }\n * })\n *\n */\n\n// Overload for when schema is provided and utils is required (not optional)\n// We can't infer the Utils type from the CollectionConfig because it will always be optional\n// So we omit it from that type and instead infer it from the extension `& { utils: TUtils }`\n// such that we have the real, non-optional Utils type\nexport function createCollection<\n  T extends StandardSchemaV1,\n  TKey extends string | number,\n  TUtils extends UtilsRecord,\n>(\n  options: Omit<\n    CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils>,\n    `utils`\n  > & {\n    schema: T\n    utils: TUtils // Required utils\n  } & NonSingleResult,\n): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> &\n  NonSingleResult\n\n// Overload for when schema is provided and utils is optional\n// In this case we can simply infer the Utils type from the CollectionConfig type\nexport function createCollection<\n  T extends StandardSchemaV1,\n  TKey extends string | number,\n  TUtils extends UtilsRecord,\n>(\n  options: CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils> & {\n    schema: T\n  } & NonSingleResult,\n): Collection<\n  InferSchemaOutput<T>,\n  TKey,\n  Exclude<TUtils, undefined>,\n  T,\n  InferSchemaInput<T>\n> &\n  NonSingleResult\n\n// Overload for when schema is provided, singleResult is true, and utils is required\nexport function createCollection<\n  T extends StandardSchemaV1,\n  TKey extends string | number,\n  TUtils extends UtilsRecord,\n>(\n  options: Omit<\n    CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils>,\n    `utils`\n  > & {\n    schema: T\n    utils: TUtils // Required utils\n  } & SingleResult,\n): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> &\n  SingleResult\n\n// Overload for when schema is provided and singleResult is true\nexport function createCollection<\n  T extends StandardSchemaV1,\n  TKey extends string | number,\n  TUtils extends UtilsRecord,\n>(\n  options: CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils> & {\n    schema: T\n  } & SingleResult,\n): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> &\n  SingleResult\n\n// Overload for when no schema is provided and utils is required\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function createCollection<\n  T extends object,\n  TKey extends string | number,\n  TUtils extends UtilsRecord,\n>(\n  options: Omit<CollectionConfig<T, TKey, never, TUtils>, `utils`> & {\n    schema?: never // prohibit schema if an explicit type is provided\n    utils: TUtils // Required utils\n  } & NonSingleResult,\n): Collection<T, TKey, TUtils, never, T> & NonSingleResult\n\n// Overload for when no schema is provided\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function createCollection<\n  T extends object,\n  TKey extends string | number = string | number,\n  TUtils extends UtilsRecord = UtilsRecord,\n>(\n  options: CollectionConfig<T, TKey, never, TUtils> & {\n    schema?: never // prohibit schema if an explicit type is provided\n  } & NonSingleResult,\n): Collection<T, TKey, TUtils, never, T> & NonSingleResult\n\n// Overload for when no schema is provided, singleResult is true, and utils is required\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function createCollection<\n  T extends object,\n  TKey extends string | number = string | number,\n  TUtils extends UtilsRecord = UtilsRecord,\n>(\n  options: Omit<CollectionConfig<T, TKey, never, TUtils>, `utils`> & {\n    schema?: never // prohibit schema if an explicit type is provided\n    utils: TUtils // Required utils\n  } & SingleResult,\n): Collection<T, TKey, TUtils, never, T> & SingleResult\n\n// Overload for when no schema is provided and singleResult is true\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function createCollection<\n  T extends object,\n  TKey extends string | number = string | number,\n  TUtils extends UtilsRecord = UtilsRecord,\n>(\n  options: CollectionConfig<T, TKey, never, TUtils> & {\n    schema?: never // prohibit schema if an explicit type is provided\n  } & SingleResult,\n): Collection<T, TKey, TUtils, never, T> & SingleResult\n\n// Implementation\nexport function createCollection(\n  options: CollectionConfig<any, string | number, any, UtilsRecord> & {\n    schema?: StandardSchemaV1\n  },\n): Collection<any, string | number, UtilsRecord, any, any> {\n  const collection = new CollectionImpl<any, string | number, any, any, any>(\n    options,\n  )\n\n  // Attach utils to collection\n  if (options.utils) {\n    collection.utils = options.utils\n  } else {\n    collection.utils = {}\n  }\n\n  return collection\n}\n\nexport class CollectionImpl<\n  TOutput extends object = Record<string, unknown>,\n  TKey extends string | number = string | number,\n  TUtils extends UtilsRecord = {},\n  TSchema extends StandardSchemaV1 = StandardSchemaV1,\n  TInput extends object = TOutput,\n> {\n  public id: string\n  public config: CollectionConfig<TOutput, TKey, TSchema>\n\n  // Utilities namespace\n  // This is populated by createCollection\n  public utils: Record<string, Fn> = {}\n\n  // Managers\n  private _events: CollectionEventsManager\n  private _changes: CollectionChangesManager<TOutput, TKey, TSchema, TInput>\n  public _lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n  public _sync: CollectionSyncManager<TOutput, TKey, TSchema, TInput>\n  private _indexes: CollectionIndexesManager<TOutput, TKey, TSchema, TInput>\n  private _mutations: CollectionMutationsManager<\n    TOutput,\n    TKey,\n    TUtils,\n    TSchema,\n    TInput\n  >\n  // The core state of the collection is \"public\" so that is accessible in tests\n  // and for debugging\n  public _state: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n\n  /**\n   * When set, collection consumers should defer processing incoming data\n   * refreshes until this promise resolves. This prevents stale data from\n   * overwriting optimistic state while pending writes are being applied.\n   */\n  public deferDataRefresh: Promise<void> | null = null\n\n  private comparisonOpts: StringCollationConfig\n\n  /**\n   * Creates a new Collection instance\n   *\n   * @param config - Configuration object for the collection\n   * @throws Error if sync config is missing\n   */\n  constructor(config: CollectionConfig<TOutput, TKey, TSchema>) {\n    // eslint-disable-next-line\n    if (!config) {\n      throw new CollectionRequiresConfigError()\n    }\n\n    // eslint-disable-next-line\n    if (!config.sync) {\n      throw new CollectionRequiresSyncConfigError()\n    }\n\n    if (config.id) {\n      this.id = config.id\n    } else {\n      this.id = crypto.randomUUID()\n    }\n\n    // Set default values for optional config properties\n    this.config = {\n      ...config,\n      autoIndex: config.autoIndex ?? `off`,\n    }\n\n    if (this.config.autoIndex === `eager` && !config.defaultIndexType) {\n      throw new CollectionConfigurationError(\n        `autoIndex: 'eager' requires defaultIndexType to be set. ` +\n          `Import an index type and set it:\\n` +\n          `  import { BasicIndex } from '@tanstack/db'\\n` +\n          `  createCollection({ defaultIndexType: BasicIndex, autoIndex: 'eager', ... })`,\n      )\n    }\n\n    this._changes = new CollectionChangesManager()\n    this._events = new CollectionEventsManager()\n    this._indexes = new CollectionIndexesManager()\n    this._lifecycle = new CollectionLifecycleManager(config, this.id)\n    this._mutations = new CollectionMutationsManager(config, this.id)\n    this._state = new CollectionStateManager(config)\n    this._sync = new CollectionSyncManager(config, this.id)\n\n    this.comparisonOpts = buildCompareOptionsFromConfig(config)\n\n    this._changes.setDeps({\n      collection: this, // Required for passing to CollectionSubscription\n      lifecycle: this._lifecycle,\n      sync: this._sync,\n      events: this._events,\n      state: this._state, // Required for enriching changes with virtual properties\n    })\n    this._events.setDeps({\n      collection: this, // Required for adding to emitted events\n    })\n    this._indexes.setDeps({\n      state: this._state,\n      lifecycle: this._lifecycle,\n      defaultIndexType: config.defaultIndexType,\n      events: this._events,\n    })\n    this._lifecycle.setDeps({\n      changes: this._changes,\n      events: this._events,\n      indexes: this._indexes,\n      state: this._state,\n      sync: this._sync,\n    })\n    this._mutations.setDeps({\n      collection: this, // Required for passing to config.onInsert/onUpdate/onDelete and annotating mutations\n      lifecycle: this._lifecycle,\n      state: this._state,\n    })\n    this._state.setDeps({\n      collection: this, // Required for filtering events to only include this collection\n      lifecycle: this._lifecycle,\n      changes: this._changes,\n      indexes: this._indexes,\n      events: this._events,\n    })\n    this._sync.setDeps({\n      collection: this, // Required for passing to config.sync callback\n      state: this._state,\n      lifecycle: this._lifecycle,\n      events: this._events,\n    })\n\n    // Only start sync immediately if explicitly enabled\n    if (config.startSync === true) {\n      this._sync.startSync()\n    }\n  }\n\n  /**\n   * Gets the current status of the collection\n   */\n  public get status(): CollectionStatus {\n    return this._lifecycle.status\n  }\n\n  /**\n   * Get the number of subscribers to the collection\n   */\n  public get subscriberCount(): number {\n    return this._changes.activeSubscribersCount\n  }\n\n  /**\n   * Register a callback to be executed when the collection first becomes ready\n   * Useful for preloading collections\n   * @param callback Function to call when the collection first becomes ready\n   * @example\n   * collection.onFirstReady(() => {\n   *   console.log('Collection is ready for the first time')\n   *   // Safe to access collection.state now\n   * })\n   */\n  public onFirstReady(callback: () => void): void {\n    return this._lifecycle.onFirstReady(callback)\n  }\n\n  /**\n   * Check if the collection is ready for use\n   * Returns true if the collection has been marked as ready by its sync implementation\n   * @returns true if the collection is ready, false otherwise\n   * @example\n   * if (collection.isReady()) {\n   *   console.log('Collection is ready, data is available')\n   *   // Safe to access collection.state\n   * } else {\n   *   console.log('Collection is still loading')\n   * }\n   */\n  public isReady(): boolean {\n    return this._lifecycle.status === `ready`\n  }\n\n  /**\n   * Check if the collection is currently loading more data\n   * @returns true if the collection has pending load more operations, false otherwise\n   */\n  public get isLoadingSubset(): boolean {\n    return this._sync.isLoadingSubset\n  }\n\n  /**\n   * Start sync immediately - internal method for compiled queries\n   * This bypasses lazy loading for special cases like live query results\n   */\n  public startSyncImmediate(): void {\n    this._sync.startSync()\n  }\n\n  /**\n   * Preload the collection data by starting sync if not already started\n   * Multiple concurrent calls will share the same promise\n   */\n  public preload(): Promise<void> {\n    return this._sync.preload()\n  }\n\n  /**\n   * Get the current value for a key (virtual derived state)\n   */\n  public get(key: TKey): WithVirtualProps<TOutput, TKey> | undefined {\n    return this._state.getWithVirtualProps(key)\n  }\n\n  /**\n   * Check if a key exists in the collection (virtual derived state)\n   */\n  public has(key: TKey): boolean {\n    return this._state.has(key)\n  }\n\n  /**\n   * Get the current size of the collection (cached)\n   */\n  public get size(): number {\n    return this._state.size\n  }\n\n  /**\n   * Get all keys (virtual derived state)\n   */\n  public *keys(): IterableIterator<TKey> {\n    yield* this._state.keys()\n  }\n\n  /**\n   * Get all values (virtual derived state)\n   */\n  public *values(): IterableIterator<WithVirtualProps<TOutput, TKey>> {\n    for (const key of this._state.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, WithVirtualProps<TOutput, TKey>]> {\n    for (const key of this._state.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<\n    [TKey, WithVirtualProps<TOutput, TKey>]\n  > {\n    yield* this.entries()\n  }\n\n  /**\n   * Execute a callback for each entry in the collection\n   */\n  public forEach(\n    callbackfn: (\n      value: WithVirtualProps<TOutput, TKey>,\n      key: TKey,\n      index: number,\n    ) => 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: (\n      value: WithVirtualProps<TOutput, TKey>,\n      key: TKey,\n      index: number,\n    ) => 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  public getKeyFromItem(item: TOutput): TKey {\n    return this.config.getKey(item)\n  }\n\n  /**\n   * Creates an index on a collection for faster queries.\n   * Indexes significantly improve query performance by allowing constant time lookups\n   * and logarithmic time range queries instead of full scans.\n   *\n   * @param indexCallback - Function that extracts the indexed value from each item\n   * @param config - Configuration including index type and type-specific options\n   * @returns The created index\n   *\n   * @example\n   * ```ts\n   * import { BasicIndex } from '@tanstack/db'\n   *\n   * // Create an index with explicit type\n   * const ageIndex = collection.createIndex((row) => row.age, {\n   *   indexType: BasicIndex\n   * })\n   *\n   * // Create an index with collection's default type\n   * const nameIndex = collection.createIndex((row) => row.name)\n   * ```\n   */\n  public createIndex<TIndexType extends IndexConstructor<TKey>>(\n    indexCallback: (row: SingleRowRefProxy<TOutput>) => any,\n    config: IndexOptions<TIndexType> = {},\n  ): BaseIndex<TKey> {\n    return this._indexes.createIndex(indexCallback, config)\n  }\n\n  /**\n   * Removes an index created with createIndex.\n   * Returns true when an index existed and was removed.\n   *\n   * Best-effort semantics: removing an index guarantees it is detached from\n   * collection query planning. Existing index proxy references should be treated\n   * as invalid after removal.\n   */\n  public removeIndex(indexOrId: BaseIndex<TKey> | number): boolean {\n    return this._indexes.removeIndex(indexOrId)\n  }\n\n  /**\n   * Returns a snapshot of current index metadata sorted by indexId.\n   * Persistence wrappers can use this to bootstrap index state if indexes were\n   * created before event listeners were attached.\n   */\n  public getIndexMetadata(): Array<CollectionIndexMetadata> {\n    return this._indexes.getIndexMetadataSnapshot()\n  }\n\n  /**\n   * Get resolved indexes for query optimization\n   */\n  get indexes(): Map<number, BaseIndex<TKey>> {\n    return this._indexes.indexes\n  }\n\n  /**\n   * Validates the data against the schema\n   */\n  public validateData(\n    data: unknown,\n    type: `insert` | `update`,\n    key?: TKey,\n  ): TOutput | never {\n    return this._mutations.validateData(data, type, key)\n  }\n\n  get compareOptions(): StringCollationConfig {\n    // return a copy such that no one can mutate the internal comparison object\n    return { ...this.comparisonOpts }\n  }\n\n  /**\n   * Inserts one or more items into the collection\n   * @param items - Single item or array of items to insert\n   * @param config - Optional configuration including metadata\n   * @returns A Transaction object representing the insert operation(s)\n   * @throws {SchemaValidationError} If the data fails schema validation\n   * @example\n   * // Insert a single todo (requires onInsert handler)\n   * const tx = collection.insert({ id: \"1\", text: \"Buy milk\", completed: false })\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Insert multiple todos at once\n   * const tx = collection.insert([\n   *   { id: \"1\", text: \"Buy milk\", completed: false },\n   *   { id: \"2\", text: \"Walk dog\", completed: true }\n   * ])\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Insert with metadata\n   * const tx = collection.insert({ id: \"1\", text: \"Buy groceries\" },\n   *   { metadata: { source: \"mobile-app\" } }\n   * )\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Handle errors\n   * try {\n   *   const tx = collection.insert({ id: \"1\", text: \"New item\" })\n   *   await tx.isPersisted.promise\n   *   console.log('Insert successful')\n   * } catch (error) {\n   *   console.log('Insert failed:', error)\n   * }\n   */\n  insert = (data: TInput | Array<TInput>, config?: InsertConfig) => {\n    return this._mutations.insert(data, config)\n  }\n\n  /**\n   * Updates one or more items in the collection using a callback function\n   * @param keys - Single key or array of keys to update\n   * @param configOrCallback - Either update configuration or update callback\n   * @param maybeCallback - Update callback if config was provided\n   * @returns A Transaction object representing the update operation(s)\n   * @throws {SchemaValidationError} If the updated data fails schema validation\n   * @example\n   * // Update single item by key\n   * const tx = collection.update(\"todo-1\", (draft) => {\n   *   draft.completed = true\n   * })\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Update multiple items\n   * const tx = collection.update([\"todo-1\", \"todo-2\"], (drafts) => {\n   *   drafts.forEach(draft => { draft.completed = true })\n   * })\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Update with metadata\n   * const tx = collection.update(\"todo-1\",\n   *   { metadata: { reason: \"user update\" } },\n   *   (draft) => { draft.text = \"Updated text\" }\n   * )\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Handle errors\n   * try {\n   *   const tx = collection.update(\"item-1\", draft => { draft.value = \"new\" })\n   *   await tx.isPersisted.promise\n   *   console.log('Update successful')\n   * } catch (error) {\n   *   console.log('Update failed:', error)\n   * }\n   */\n\n  // Overload 1: Update multiple items with a callback\n  update(\n    key: Array<TKey | unknown>,\n    callback: (drafts: Array<WritableDeep<TInput>>) => void,\n  ): TransactionType\n\n  // Overload 2: Update multiple items with config and a callback\n  update(\n    keys: Array<TKey | unknown>,\n    config: OperationConfig,\n    callback: (drafts: Array<WritableDeep<TInput>>) => void,\n  ): TransactionType\n\n  // Overload 3: Update a single item with a callback\n  update(\n    id: TKey | unknown,\n    callback: (draft: WritableDeep<TInput>) => void,\n  ): TransactionType\n\n  // Overload 4: Update a single item with config and a callback\n  update(\n    id: TKey | unknown,\n    config: OperationConfig,\n    callback: (draft: WritableDeep<TInput>) => void,\n  ): TransactionType\n\n  update(\n    keys: (TKey | unknown) | Array<TKey | unknown>,\n    configOrCallback:\n      | ((draft: WritableDeep<TInput>) => void)\n      | ((drafts: Array<WritableDeep<TInput>>) => void)\n      | OperationConfig,\n    maybeCallback?:\n      | ((draft: WritableDeep<TInput>) => void)\n      | ((drafts: Array<WritableDeep<TInput>>) => void),\n  ) {\n    return this._mutations.update(keys, configOrCallback, maybeCallback)\n  }\n\n  /**\n   * Deletes one or more items from the collection\n   * @param keys - Single key or array of keys to delete\n   * @param config - Optional configuration including metadata\n   * @returns A Transaction object representing the delete operation(s)\n   * @example\n   * // Delete a single item\n   * const tx = collection.delete(\"todo-1\")\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Delete multiple items\n   * const tx = collection.delete([\"todo-1\", \"todo-2\"])\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Delete with metadata\n   * const tx = collection.delete(\"todo-1\", { metadata: { reason: \"completed\" } })\n   * await tx.isPersisted.promise\n   *\n   * @example\n   * // Handle errors\n   * try {\n   *   const tx = collection.delete(\"item-1\")\n   *   await tx.isPersisted.promise\n   *   console.log('Delete successful')\n   * } catch (error) {\n   *   console.log('Delete failed:', error)\n   * }\n   */\n  delete = (\n    keys: Array<TKey> | TKey,\n    config?: OperationConfig,\n  ): TransactionType<any> => {\n    return this._mutations.delete(keys, config)\n  }\n\n  /**\n   * Gets the current state of the collection as a Map\n   * @returns Map containing all items in the collection, with keys as identifiers\n   * @example\n   * const itemsMap = collection.state\n   * console.log(`Collection has ${itemsMap.size} items`)\n   *\n   * for (const [key, item] of itemsMap) {\n   *   console.log(`${key}: ${item.title}`)\n   * }\n   *\n   * // Check if specific item exists\n   * if (itemsMap.has(\"todo-1\")) {\n   *   console.log(\"Todo 1 exists:\", itemsMap.get(\"todo-1\"))\n   * }\n   */\n  get state() {\n    const result = new Map<TKey, WithVirtualProps<TOutput, TKey>>()\n    for (const [key, value] of this.entries()) {\n      result.set(key, value)\n    }\n    return result\n  }\n\n  /**\n   * Gets the current state of the collection as a Map, but only resolves when data is available\n   * Waits for the first sync commit to complete before resolving\n   *\n   * @returns Promise that resolves to a Map containing all items in the collection\n   */\n  stateWhenReady(): Promise<Map<TKey, WithVirtualProps<TOutput, TKey>>> {\n    // If we already have data or collection is ready, resolve immediately\n    if (this.size > 0 || this.isReady()) {\n      return Promise.resolve(this.state)\n    }\n\n    // Use preload to ensure the collection starts loading, then return the state\n    return this.preload().then(() => this.state)\n  }\n\n  /**\n   * Gets the current state of the collection as an Array\n   *\n   * @returns An Array containing all items in the collection\n   */\n  get toArray() {\n    return Array.from(this.values())\n  }\n\n  /**\n   * Gets the current state of the collection as an Array, but only resolves when data is available\n   * Waits for the first sync commit to complete before resolving\n   *\n   * @returns Promise that resolves to an Array containing all items in the collection\n   */\n  toArrayWhenReady(): Promise<Array<WithVirtualProps<TOutput, TKey>>> {\n    // If we already have data or collection is ready, resolve immediately\n    if (this.size > 0 || this.isReady()) {\n      return Promise.resolve(this.toArray)\n    }\n\n    // Use preload to ensure the collection starts loading, then return the array\n    return this.preload().then(() => this.toArray)\n  }\n\n  /**\n   * Returns the current state of the collection as an array of changes\n   * @param options - Options including optional where filter\n   * @returns An array of changes\n   * @example\n   * // Get all items as changes\n   * const allChanges = collection.currentStateAsChanges()\n   *\n   * // Get only items matching a condition\n   * const activeChanges = collection.currentStateAsChanges({\n   *   where: (row) => row.status === 'active'\n   * })\n   *\n   * // Get only items using a pre-compiled expression\n   * const activeChanges = collection.currentStateAsChanges({\n   *   whereExpression: eq(row.status, 'active')\n   * })\n   */\n  public currentStateAsChanges(\n    options: CurrentStateAsChangesOptions = {},\n  ): Array<ChangeMessage<WithVirtualProps<TOutput, TKey>>> | void {\n    return currentStateAsChanges(this, options)\n  }\n\n  /**\n   * Subscribe to changes in the collection\n   * @param callback - Function called when items change\n   * @param options - Subscription options including includeInitialState and where filter\n   * @returns Unsubscribe function - Call this to stop listening for changes\n   * @example\n   * // Basic subscription\n   * const subscription = collection.subscribeChanges((changes) => {\n   *   changes.forEach(change => {\n   *     console.log(`${change.type}: ${change.key}`, change.value)\n   *   })\n   * })\n   *\n   * // Later: subscription.unsubscribe()\n   *\n   * @example\n   * // Include current state immediately\n   * const subscription = collection.subscribeChanges((changes) => {\n   *   updateUI(changes)\n   * }, { includeInitialState: true })\n   *\n   * @example\n   * // Subscribe only to changes matching a condition using where callback\n   * import { eq } from \"@tanstack/db\"\n   *\n   * const subscription = collection.subscribeChanges((changes) => {\n   *   updateUI(changes)\n   * }, {\n   *   includeInitialState: true,\n   *   where: (row) => eq(row.status, \"active\")\n   * })\n   *\n   * @example\n   * // Using multiple conditions with and()\n   * import { and, eq, gt } from \"@tanstack/db\"\n   *\n   * const subscription = collection.subscribeChanges((changes) => {\n   *   updateUI(changes)\n   * }, {\n   *   where: (row) => and(eq(row.status, \"active\"), gt(row.priority, 5))\n   * })\n   */\n  public subscribeChanges(\n    callback: (\n      changes: Array<ChangeMessage<WithVirtualProps<TOutput, TKey>>>,\n    ) => void,\n    options: SubscribeChangesOptions<TOutput, TKey> = {},\n  ): CollectionSubscription {\n    return this._changes.subscribeChanges(callback, options)\n  }\n\n  /**\n   * Subscribe to a collection event\n   */\n  public on<T extends keyof AllCollectionEvents>(\n    event: T,\n    callback: CollectionEventHandler<T>,\n  ) {\n    return this._events.on(event, callback)\n  }\n\n  /**\n   * Subscribe to a collection event once\n   */\n  public once<T extends keyof AllCollectionEvents>(\n    event: T,\n    callback: CollectionEventHandler<T>,\n  ) {\n    return this._events.once(event, callback)\n  }\n\n  /**\n   * Unsubscribe from a collection event\n   */\n  public off<T extends keyof AllCollectionEvents>(\n    event: T,\n    callback: CollectionEventHandler<T>,\n  ) {\n    this._events.off(event, callback)\n  }\n\n  /**\n   * Wait for a collection event\n   */\n  public waitFor<T extends keyof AllCollectionEvents>(\n    event: T,\n    timeout?: number,\n  ) {\n    return this._events.waitFor(event, timeout)\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 async cleanup(): Promise<void> {\n    this._lifecycle.cleanup()\n    return Promise.resolve()\n  }\n}\n\nfunction buildCompareOptionsFromConfig(\n  config: CollectionConfig<any, any, any>,\n): StringCollationConfig {\n  if (config.defaultStringCollation) {\n    const options = config.defaultStringCollation\n    return {\n      stringSort: options.stringSort ?? `locale`,\n      locale: options.stringSort === `locale` ? options.locale : undefined,\n      localeOptions:\n        options.stringSort === `locale` ? options.localeOptions : undefined,\n    }\n  } else {\n    return {\n      stringSort: `locale`,\n    }\n  }\n}\n"],"names":["config","CollectionRequiresConfigError","CollectionRequiresSyncConfigError","CollectionConfigurationError","CollectionChangesManager","CollectionEventsManager","CollectionIndexesManager","CollectionLifecycleManager","CollectionMutationsManager","CollectionStateManager","CollectionSyncManager","currentStateAsChanges"],"mappings":";;;;;;;;;;;AA4PO,SAAS,iBACd,SAGyD;AACzD,QAAM,aAAa,IAAI;AAAA,IACrB;AAAA,EAAA;AAIF,MAAI,QAAQ,OAAO;AACjB,eAAW,QAAQ,QAAQ;AAAA,EAC7B,OAAO;AACL,eAAW,QAAQ,CAAA;AAAA,EACrB;AAEA,SAAO;AACT;AAEO,MAAM,eAMX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCA,YAAY,QAAkD;AAlC9D,SAAO,QAA4B,CAAA;AAwBnC,SAAO,mBAAyC;AAwXhD,SAAA,SAAS,CAAC,MAA8BA,YAA0B;AAChE,aAAO,KAAK,WAAW,OAAO,MAAMA,OAAM;AAAA,IAC5C;AA+GA,SAAA,SAAS,CACP,MACAA,YACyB;AACzB,aAAO,KAAK,WAAW,OAAO,MAAMA,OAAM;AAAA,IAC5C;AAleE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAIC,OAAAA,8BAAA;AAAA,IACZ;AAGA,QAAI,CAAC,OAAO,MAAM;AAChB,YAAM,IAAIC,OAAAA,kCAAA;AAAA,IACZ;AAEA,QAAI,OAAO,IAAI;AACb,WAAK,KAAK,OAAO;AAAA,IACnB,OAAO;AACL,WAAK,KAAK,OAAO,WAAA;AAAA,IACnB;AAGA,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,WAAW,OAAO,aAAa;AAAA,IAAA;AAGjC,QAAI,KAAK,OAAO,cAAc,WAAW,CAAC,OAAO,kBAAkB;AACjE,YAAM,IAAIC,OAAAA;AAAAA,QACR;AAAA;AAAA;AAAA,MAAA;AAAA,IAKJ;AAEA,SAAK,WAAW,IAAIC,iCAAA;AACpB,SAAK,UAAU,IAAIC,+BAAA;AACnB,SAAK,WAAW,IAAIC,iCAAA;AACpB,SAAK,aAAa,IAAIC,UAAAA,2BAA2B,QAAQ,KAAK,EAAE;AAChE,SAAK,aAAa,IAAIC,UAAAA,2BAA2B,QAAQ,KAAK,EAAE;AAChE,SAAK,SAAS,IAAIC,MAAAA,uBAAuB,MAAM;AAC/C,SAAK,QAAQ,IAAIC,KAAAA,sBAAsB,QAAQ,KAAK,EAAE;AAEtD,SAAK,iBAAiB,8BAA8B,MAAM;AAE1D,SAAK,SAAS,QAAQ;AAAA,MACpB,YAAY;AAAA;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA;AAAA,IAAA,CACb;AACD,SAAK,QAAQ,QAAQ;AAAA,MACnB,YAAY;AAAA;AAAA,IAAA,CACb;AACD,SAAK,SAAS,QAAQ;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,kBAAkB,OAAO;AAAA,MACzB,QAAQ,KAAK;AAAA,IAAA,CACd;AACD,SAAK,WAAW,QAAQ;AAAA,MACtB,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,IAAA,CACZ;AACD,SAAK,WAAW,QAAQ;AAAA,MACtB,YAAY;AAAA;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,IAAA,CACb;AACD,SAAK,OAAO,QAAQ;AAAA,MAClB,YAAY;AAAA;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,IAAA,CACd;AACD,SAAK,MAAM,QAAQ;AAAA,MACjB,YAAY;AAAA;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,IAAA,CACd;AAGD,QAAI,OAAO,cAAc,MAAM;AAC7B,WAAK,MAAM,UAAA;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,SAA2B;AACpC,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,kBAA0B;AACnC,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,aAAa,UAA4B;AAC9C,WAAO,KAAK,WAAW,aAAa,QAAQ;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcO,UAAmB;AACxB,WAAO,KAAK,WAAW,WAAW;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAW,kBAA2B;AACpC,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,qBAA2B;AAChC,SAAK,MAAM,UAAA;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,UAAyB;AAC9B,WAAO,KAAK,MAAM,QAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKO,IAAI,KAAwD;AACjE,WAAO,KAAK,OAAO,oBAAoB,GAAG;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKO,IAAI,KAAoB;AAC7B,WAAO,KAAK,OAAO,IAAI,GAAG;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAe;AACxB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,CAAQ,OAA+B;AACrC,WAAO,KAAK,OAAO,KAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,CAAQ,SAA4D;AAClE,eAAW,OAAO,KAAK,OAAO,KAAA,GAAQ;AACpC,YAAM,QAAQ,KAAK,IAAI,GAAG;AAC1B,UAAI,UAAU,QAAW;AACvB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,CAAQ,UAAqE;AAC3E,eAAW,OAAO,KAAK,OAAO,KAAA,GAAQ;AACpC,YAAM,QAAQ,KAAK,IAAI,GAAG;AAC1B,UAAI,UAAU,QAAW;AACvB,cAAM,CAAC,KAAK,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,EAAS,OAAO,QAAQ,IAEtB;AACA,WAAO,KAAK,QAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,QACL,YAKM;AACN,QAAI,QAAQ;AACZ,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,WAAW;AACzC,iBAAW,OAAO,KAAK,OAAO;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,IACL,YAKU;AACV,UAAM,SAAmB,CAAA;AACzB,QAAI,QAAQ;AACZ,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,WAAW;AACzC,aAAO,KAAK,WAAW,OAAO,KAAK,OAAO,CAAC;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEO,eAAe,MAAqB;AACzC,WAAO,KAAK,OAAO,OAAO,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBO,YACL,eACA,SAAmC,IAClB;AACjB,WAAO,KAAK,SAAS,YAAY,eAAe,MAAM;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUO,YAAY,WAA8C;AAC/D,WAAO,KAAK,SAAS,YAAY,SAAS;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,mBAAmD;AACxD,WAAO,KAAK,SAAS,yBAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAwC;AAC1C,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKO,aACL,MACA,MACA,KACiB;AACjB,WAAO,KAAK,WAAW,aAAa,MAAM,MAAM,GAAG;AAAA,EACrD;AAAA,EAEA,IAAI,iBAAwC;AAE1C,WAAO,EAAE,GAAG,KAAK,eAAA;AAAA,EACnB;AAAA,EA4GA,OACE,MACA,kBAIA,eAGA;AACA,WAAO,KAAK,WAAW,OAAO,MAAM,kBAAkB,aAAa;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuDA,IAAI,QAAQ;AACV,UAAM,6BAAa,IAAA;AACnB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,WAAW;AACzC,aAAO,IAAI,KAAK,KAAK;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAsE;AAEpE,QAAI,KAAK,OAAO,KAAK,KAAK,WAAW;AACnC,aAAO,QAAQ,QAAQ,KAAK,KAAK;AAAA,IACnC;AAGA,WAAO,KAAK,QAAA,EAAU,KAAK,MAAM,KAAK,KAAK;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,UAAU;AACZ,WAAO,MAAM,KAAK,KAAK,OAAA,CAAQ;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAoE;AAElE,QAAI,KAAK,OAAO,KAAK,KAAK,WAAW;AACnC,aAAO,QAAQ,QAAQ,KAAK,OAAO;AAAA,IACrC;AAGA,WAAO,KAAK,QAAA,EAAU,KAAK,MAAM,KAAK,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBO,sBACL,UAAwC,IACsB;AAC9D,WAAOC,aAAAA,sBAAsB,MAAM,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4CO,iBACL,UAGA,UAAkD,IAC1B;AACxB,WAAO,KAAK,SAAS,iBAAiB,UAAU,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKO,GACL,OACA,UACA;AACA,WAAO,KAAK,QAAQ,GAAG,OAAO,QAAQ;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKO,KACL,OACA,UACA;AACA,WAAO,KAAK,QAAQ,KAAK,OAAO,QAAQ;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKO,IACL,OACA,UACA;AACA,SAAK,QAAQ,IAAI,OAAO,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKO,QACL,OACA,SACA;AACA,WAAO,KAAK,QAAQ,QAAQ,OAAO,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,UAAyB;AACpC,SAAK,WAAW,QAAA;AAChB,WAAO,QAAQ,QAAA;AAAA,EACjB;AACF;AAEA,SAAS,8BACP,QACuB;AACvB,MAAI,OAAO,wBAAwB;AACjC,UAAM,UAAU,OAAO;AACvB,WAAO;AAAA,MACL,YAAY,QAAQ,cAAc;AAAA,MAClC,QAAQ,QAAQ,eAAe,WAAW,QAAQ,SAAS;AAAA,MAC3D,eACE,QAAQ,eAAe,WAAW,QAAQ,gBAAgB;AAAA,IAAA;AAAA,EAEhE,OAAO;AACL,WAAO;AAAA,MACL,YAAY;AAAA,IAAA;AAAA,EAEhB;AACF;;;"}