{"version":3,"file":"index.cjs","sources":["../../../src/collection/index.ts"],"sourcesContent":["import {\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 { AllCollectionEvents, CollectionEventHandler } from './events.js'\nimport type { BaseIndex, IndexResolver } 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 { BTreeIndex } from '../indexes/btree-index.js'\nimport type { IndexProxy } from '../indexes/lazy-index.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  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 ?? `eager`,\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    })\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    })\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): TOutput | undefined {\n    return this._state.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    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<TOutput> {\n    yield* this._state.values()\n  }\n\n  /**\n   * Get all entries (virtual derived state)\n   */\n  public *entries(): IterableIterator<[TKey, TOutput]> {\n    yield* this._state.entries()\n  }\n\n  /**\n   * Get all entries (virtual derived state)\n   */\n  public *[Symbol.iterator](): IterableIterator<[TKey, TOutput]> {\n    yield* this._state[Symbol.iterator]()\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    return this._state.forEach(callbackfn)\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    return this._state.map(callbackfn)\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   * @template TResolver - The type of the index resolver (constructor or async loader)\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 An index proxy that provides access to the index when ready\n   *\n   * @example\n   * // Create a default B+ tree index\n   * const ageIndex = collection.createIndex((row) => row.age)\n   *\n   * // Create a ordered index with custom options\n   * const ageIndex = collection.createIndex((row) => row.age, {\n   *   indexType: BTreeIndex,\n   *   options: {\n   *     compareFn: customComparator,\n   *     compareOptions: { direction: 'asc', nulls: 'first', stringSort: 'lexical' }\n   *   },\n   *   name: 'age_btree'\n   * })\n   *\n   * // Create an async-loaded index\n   * const textIndex = collection.createIndex((row) => row.content, {\n   *   indexType: async () => {\n   *     const { FullTextIndex } = await import('./indexes/fulltext.js')\n   *     return FullTextIndex\n   *   },\n   *   options: { language: 'en' }\n   * })\n   */\n  public createIndex<TResolver extends IndexResolver<TKey> = typeof BTreeIndex>(\n    indexCallback: (row: SingleRowRefProxy<TOutput>) => any,\n    config: IndexOptions<TResolver> = {},\n  ): IndexProxy<TKey> {\n    return this._indexes.createIndex(indexCallback, config)\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, TOutput>()\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, TOutput>> {\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<TOutput>> {\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<TOutput>> | 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: (changes: Array<ChangeMessage<TOutput>>) => void,\n    options: SubscribeChangesOptions<TOutput> = {},\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","CollectionChangesManager","CollectionEventsManager","CollectionIndexesManager","CollectionLifecycleManager","CollectionMutationsManager","CollectionStateManager","CollectionSyncManager","currentStateAsChanges"],"mappings":"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"}