{"version":3,"file":"live-query-adapter.cjs","sources":["../../src/live-query-adapter.ts"],"sourcesContent":["import { SourceCollectionIdReuseError } from './errors.js'\nimport { isCollection } from './live-query-primitives.js'\nimport {\n  getPreparedLiveQueryIdentity,\n  getPreparedLiveQuerySources,\n} from './live-query-options.js'\nimport type { DbClient } from './client.js'\nimport type { LiveQueryKey } from './live-query-options.js'\n\n/**\n * The adapter layer: what the first-party framework adapters\n * (`@tanstack/react-db`, `@tanstack/preact-db`, `@tanstack/vue-db`,\n * `@tanstack/svelte-db`, `@tanstack/solid-db`, `@tanstack/angular-db`) build\n * their bindings from. It centralizes logic every adapter used to duplicate,\n * so they stay consistent across frameworks.\n *\n * Application code should use an adapter instead. Everything exported here is\n * unstable for external use and changes with the adapters that share it.\n */\n\nexport * from './live-query-primitives.js'\nexport * from './live-query-observer.js'\nexport * from './live-query-window-binding.js'\nexport {\n  configPool,\n  getLiveQueryHash,\n  getPreparedLiveQueryIdentity,\n  getPreparedLiveQuerySources,\n  prepareLiveQueryValue,\n  rejectLiveQueryInput,\n  releaseDeferredOnReclaim,\n  resolveLiveQueryValue,\n  resumeDeferredLiveQueryCollections,\n} from './live-query-options.js'\nexport type { DeferredLiveQueryCollections } from './live-query-options.js'\nexport {\n  createLiveQueryWindowController,\n  fetchNextLiveQueryWindowPage,\n} from './live-query-window-controller.js'\nexport type {\n  CreateLiveQueryWindowControllerOptions,\n  LiveQueryWindowController,\n  LiveQueryWindowSnapshot,\n} from './live-query-window-controller.js'\n\n/**\n * The `queryKey` of a config-object query input, if it supplies one. An empty\n * key is absent, as it is for `getLiveQueryHash`, so a hook and a `DbClient`\n * preload agree on the query's identity.\n */\nexport function getLiveQueryKey(input: unknown): LiveQueryKey | undefined {\n  const queryKey =\n    input && typeof input === `object` && !isCollection(input)\n      ? (input as { queryKey?: unknown }).queryKey\n      : undefined\n  return Array.isArray(queryKey) && queryKey.length > 0 ? queryKey : undefined\n}\n\n/*\n * Query identity and source Collection ID claims.\n *\n * A binding that compares derived query identity decides from it whether to\n * compile again: React and Preact compare it on every render, and a `DbClient`\n * matches preloaded and hydrated queries by its hash. That identity names each\n * source by its Collection ID. While such a binding is mounted, an ID must\n * keep naming one source object in each client scope, or the binding could\n * reuse a live query that reads the old source. A binding that compiles again\n * whenever its reactive reads change compares no identity, so neither check\n * applies to it.\n */\n\nconst sourceObjectTokens = new WeakMap<object, number>()\nlet nextSourceObjectToken = 0\n\n/** A process-unique number for a source object, without retaining it. */\nexport function getSourceObjectToken(source: object): number {\n  let token = sourceObjectTokens.get(source)\n  if (token === undefined) {\n    token = ++nextSourceObjectToken\n    sourceObjectTokens.set(source, token)\n  }\n  return token\n}\n\n// The client scope of a binding that reads no DbClient.\nconst unscopedClaims = {}\n\n/**\n * The source object each Collection ID named while one binding is mounted,\n * per client scope.\n */\nexport type LiveQuerySourceIdClaims = WeakMap<object, Map<string, number>>\n\nexport function createLiveQuerySourceIdClaims(): LiveQuerySourceIdClaims {\n  return new WeakMap()\n}\n\n/** Record a query's sources, or throw before recording any. */\nexport function claimLiveQuerySourceIds(\n  claims: LiveQuerySourceIdClaims,\n  sources: ReadonlyArray<{ id: string }>,\n  client: DbClient | undefined,\n  bindingName: string,\n): void {\n  const scope = client ?? unscopedClaims\n  const prior = claims.get(scope)\n  const seen = new Map<string, number>()\n  for (const source of sources) {\n    const token = getSourceObjectToken(source)\n    const previous = seen.get(source.id) ?? prior?.get(source.id)\n    if (previous !== undefined && previous !== token) {\n      throw new SourceCollectionIdReuseError(bindingName, source.id)\n    }\n    seen.set(source.id, token)\n  }\n  const claimed = prior ?? new Map<string, number>()\n  for (const [id, token] of seen) claimed.set(id, token)\n  claims.set(scope, claimed)\n}\n\n/** Where a binding that compares query identity checks a prepared query. */\nexport interface LiveQueryIdentityScope {\n  /** This binding's source Collection ID claims. */\n  claims: LiveQuerySourceIdClaims\n  client: DbClient | undefined\n  bindingName: string\n  /** Report a descriptor source that no client bound. */\n  onUnboundDescriptor?: (alias: string) => never\n}\n\n/**\n * Identify a prepared query for a binding that compares query identity. The\n * identity throws `UnhashableQueryIRError` for IR without a stable identity,\n * then the query's sources claim their Collection IDs. The binding's render\n * boundary releases the sync starts a rejected render deferred; see\n * `rejectLiveQueryInput`.\n */\nexport function identifyLiveQuery<TIdentity = unknown>(\n  preparedValue: unknown,\n  scope: LiveQueryIdentityScope,\n  identify: (\n    preparedValue: unknown,\n  ) => TIdentity = getPreparedLiveQueryIdentity as (\n    preparedValue: unknown,\n  ) => TIdentity,\n): TIdentity {\n  const identity = identify(preparedValue)\n  claimLiveQuerySourceIds(\n    scope.claims,\n    getPreparedLiveQuerySources(preparedValue, scope.onUnboundDescriptor),\n    scope.client,\n    scope.bindingName,\n  )\n  return identity\n}\n"],"names":["isCollection","SourceCollectionIdReuseError","getPreparedLiveQueryIdentity","getPreparedLiveQuerySources"],"mappings":";;;;;AAkDO,SAAS,gBAAgB,OAA0C;AACxE,QAAM,WACJ,SAAS,OAAO,UAAU,YAAY,CAACA,oBAAAA,aAAa,KAAK,IACpD,MAAiC,WAClC;AACN,SAAO,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,IAAI,WAAW;AACrE;AAeA,MAAM,yCAAyB,QAAA;AAC/B,IAAI,wBAAwB;AAGrB,SAAS,qBAAqB,QAAwB;AAC3D,MAAI,QAAQ,mBAAmB,IAAI,MAAM;AACzC,MAAI,UAAU,QAAW;AACvB,YAAQ,EAAE;AACV,uBAAmB,IAAI,QAAQ,KAAK;AAAA,EACtC;AACA,SAAO;AACT;AAGA,MAAM,iBAAiB,CAAA;AAQhB,SAAS,gCAAyD;AACvE,6BAAW,QAAA;AACb;AAGO,SAAS,wBACd,QACA,SACA,QACA,aACM;AACN,QAAM,QAAQ,UAAU;AACxB,QAAM,QAAQ,OAAO,IAAI,KAAK;AAC9B,QAAM,2BAAW,IAAA;AACjB,aAAW,UAAU,SAAS;AAC5B,UAAM,QAAQ,qBAAqB,MAAM;AACzC,UAAM,WAAW,KAAK,IAAI,OAAO,EAAE,KAAK,OAAO,IAAI,OAAO,EAAE;AAC5D,QAAI,aAAa,UAAa,aAAa,OAAO;AAChD,YAAM,IAAIC,OAAAA,6BAA6B,aAAa,OAAO,EAAE;AAAA,IAC/D;AACA,SAAK,IAAI,OAAO,IAAI,KAAK;AAAA,EAC3B;AACA,QAAM,UAAU,SAAS,oBAAI,IAAA;AAC7B,aAAW,CAAC,IAAI,KAAK,KAAK,KAAM,SAAQ,IAAI,IAAI,KAAK;AACrD,SAAO,IAAI,OAAO,OAAO;AAC3B;AAmBO,SAAS,kBACd,eACA,OACA,WAEiBC,iBAAAA,8BAGN;AACX,QAAM,WAAW,SAAS,aAAa;AACvC;AAAA,IACE,MAAM;AAAA,IACNC,6CAA4B,eAAe,MAAM,mBAAmB;AAAA,IACpE,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAER,SAAO;AACT;;;;;;;;;;;;;;;;;;;;"}