{"version":3,"file":"builder.mjs","names":["#pushOrBranch","#sink","#collection","#topK","#near","#selectCalled","#projection","#offset","#consistency","#run","#validateRawFilters"],"sources":["../../../src/batteries/vector/builder.ts"],"sourcesContent":["/**\n * Knex-style chainable query builder for the vector storage battery.\n *\n * @module @nhtio/adk/batteries/vector/builder\n */\n\nimport { isRawFilter, isFilterCondition } from './filters'\nimport {\n  E_VECTOR_STORE_QUERY_CONFLICT,\n  E_VECTOR_STORE_PROJECTION_REQUIRED,\n  E_VECTOR_STORE_RAW_BINDING_MISMATCH,\n  E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR,\n} from './exceptions'\nimport type { VectorRecord, VectorMatch, VectorConsistency } from './types'\nimport type { SearchPlan, UpsertPlan, DeletePlan, Projection } from './plan'\nimport type { VectorFilter, FilterCondition, FilterOperator } from './filters'\n\nconst OP_ALIASES: Record<string, FilterOperator> = {\n  '=': 'eq',\n  '==': 'eq',\n  '===': 'eq',\n  '!=': 'ne',\n  '<>': 'ne',\n  '!==': 'ne',\n  '>': 'gt',\n  '>=': 'gte',\n  '<': 'lt',\n  '<=': 'lte',\n  'eq': 'eq',\n  'ne': 'ne',\n  'gt': 'gt',\n  'gte': 'gte',\n  'lt': 'lt',\n  'lte': 'lte',\n  'in': 'in',\n  'nin': 'nin',\n  'exists': 'exists',\n  'contains': 'contains',\n}\nconst normalizeOp = (op: string): FilterOperator => {\n  const norm = OP_ALIASES[op]\n  if (!norm) throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['builder', op])\n  return norm\n}\n\n/**\n * The execution backend a {@link VectorQueryBuilder} drains its assembled plans into. Implemented\n * by the vector store; the builder produces {@link SearchPlan}/{@link UpsertPlan}/{@link DeletePlan}\n * objects and hands them here rather than touching the adapter directly.\n */\nexport interface PlanSink {\n  /** Executes an assembled search plan and resolves the matching records. */\n  executeSearch(plan: SearchPlan): Promise<VectorMatch[]>\n  /** Executes an assembled upsert plan. */\n  executeUpsert(plan: UpsertPlan): Promise<void>\n  /** Executes an assembled delete plan. */\n  executeDelete(plan: DeletePlan): Promise<void>\n}\n\n/**\n * An argument accepted by {@link VectorQueryBuilder.select} — a field name (or `'*'`), a\n * `[field, config]` tuple, or a `{ field: config }` map selecting and configuring projected fields.\n */\nexport type SelectArg =\n  | string\n  | [string, Record<string, unknown>]\n  | Record<string, Record<string, unknown> | true>\n\n/**\n * A callback that receives a fresh filter-only builder, used to express a parenthesized group of\n * conditions — `A AND (B OR C)`, `NOT (…)`, and arbitrary nesting. The callback mutates the builder\n * in place (knex-style); its accumulated conditions become a single nested `VectorFilter`.\n *\n * @see {@link FilterBuilder.where}\n */\nexport type FilterCallback = (qb: FilterBuilder) => void\n\n/**\n * The where-clause surface of the query builder, factored out so a grouping callback can be handed\n * a builder that only exposes filter methods (not `near*`/`select`/`limit` or the terminals).\n *\n * Chained `.where()` ANDs; the first `.orWhere()` snapshots the accumulated AND-list into the first\n * branch of an OR (knex semantics). Any of the where-methods also accepts a {@link FilterCallback}\n * to open a nested group, letting AND and OR mix to any depth.\n */\nclass FilterBuilder {\n  protected andConditions: VectorFilter[] = []\n  protected orBranches: VectorFilter[][] = []\n\n  /** Build a nested group by running `cb` against a fresh {@link FilterBuilder}. */\n  protected runGroup(cb: FilterCallback): VectorFilter | undefined {\n    const fb = new FilterBuilder()\n    cb(fb)\n    return fb.buildFilter()\n  }\n\n  /** Add a parenthesized condition group via a {@link FilterCallback}; ANDed with prior conditions. */\n  where(cb: FilterCallback): this\n  /** Add a condition `field op value` (or `field = value` when `c` is omitted); ANDed with prior conditions. */\n  where(a: string, b?: unknown, c?: unknown): this\n  /** Add equality conditions for each key of `obj`; ANDed with prior conditions. */\n  where(obj: Record<string, unknown>): this\n  where(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n    if (typeof a === 'function') {\n      const group = this.runGroup(a)\n      if (group !== undefined) {\n        this.andConditions.push(group)\n      }\n      return this\n    }\n    if (typeof a === 'object' && !Array.isArray(a)) {\n      for (const key of Object.keys(a)) {\n        this.andConditions.push({\n          field: key,\n          op: 'eq',\n          value: a[key] as FilterCondition['value'],\n        })\n      }\n      return this\n    }\n    const field = a as string\n    const value = b !== undefined ? (c !== undefined ? c : b) : b\n    const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n    this.andConditions.push({ field, op, value: value as FilterCondition['value'] })\n    return this\n  }\n\n  /** Alias of {@link FilterBuilder.where} (callback group form) for readability in a chain. */\n  andWhere(cb: FilterCallback): this\n  /** Alias of {@link FilterBuilder.where} (`field op value` form) for readability in a chain. */\n  andWhere(a: string, b?: unknown, c?: unknown): this\n  /** Alias of {@link FilterBuilder.where} (object form) for readability in a chain. */\n  andWhere(obj: Record<string, unknown>): this\n  andWhere(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n    return this.where(a as any, b, c)\n  }\n\n  /**\n   * Open a new OR branch holding a single filter. The accumulated AND-list is contributed as the\n   * first OR-group by {@link buildFilter}, so each branch carries only its own condition(s) — that\n   * is what makes `where(A).where(B).orWhere(C)` resolve to `(A AND B) OR C`.\n   */\n  #pushOrBranch(filter: VectorFilter): void {\n    this.orBranches.push([filter])\n  }\n\n  /** Open a new OR branch holding a parenthesized condition group via a {@link FilterCallback}. */\n  orWhere(cb: FilterCallback): this\n  /** Open a new OR branch holding the equality condition `field = value`. */\n  orWhere(field: string, value: unknown): this\n  /** Open a new OR branch holding the condition `field op value`. */\n  orWhere(field: string, op: FilterOperator, value: unknown): this\n  orWhere(field: string | FilterCallback, b?: unknown, c?: unknown): this {\n    if (typeof field === 'function') {\n      const group = this.runGroup(field)\n      if (group !== undefined) {\n        this.#pushOrBranch(group)\n      }\n      return this\n    }\n    const value = c !== undefined ? c : b\n    const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n    this.#pushOrBranch({ field, op, value: value as FilterCondition['value'] })\n    return this\n  }\n\n  /** AND a negated parenthesized condition group via a {@link FilterCallback}. */\n  whereNot(cb: FilterCallback): this\n  /** AND the negated equality condition `field != value`. */\n  whereNot(field: string, value: unknown): this\n  whereNot(field: string | FilterCallback, value?: unknown): this {\n    if (typeof field === 'function') {\n      const group = this.runGroup(field)\n      if (group !== undefined) {\n        this.andConditions.push({ not: group })\n      }\n      return this\n    }\n    return this.where(field, 'ne', value as FilterCondition['value'])\n  }\n\n  /** Open a new OR branch holding a negated parenthesized condition group via a {@link FilterCallback}. */\n  orWhereNot(cb: FilterCallback): this\n  /** Open a new OR branch holding the negated equality condition `field != value`. */\n  orWhereNot(field: string, value: unknown): this\n  orWhereNot(field: string | FilterCallback, value?: unknown): this {\n    if (typeof field === 'function') {\n      const group = this.runGroup(field)\n      if (group !== undefined) {\n        this.#pushOrBranch({ not: group })\n      }\n      return this\n    }\n    return this.orWhere(field, 'ne', value)\n  }\n\n  /** AND the condition that `field`'s value is one of `values`. */\n  whereIn(field: string, values: unknown[]): this {\n    return this.where(field, 'in', values as FilterCondition['value'])\n  }\n\n  /** AND the condition that `field`'s value is none of `values`. */\n  whereNotIn(field: string, values: unknown[]): this {\n    return this.where(field, 'nin', values as FilterCondition['value'])\n  }\n\n  /** AND the condition that `field` is absent (does not exist). */\n  whereNull(field: string): this {\n    return this.where(field, 'exists', false as FilterCondition['value'])\n  }\n\n  /** AND the condition that `field` is present (exists). */\n  whereExists(field: string): this {\n    return this.where(field, 'exists', true as FilterCondition['value'])\n  }\n\n  /** AND a raw, adapter-dialect filter expressed as SQL text plus positional `bindings`. */\n  whereRaw(sql: string, bindings?: unknown[]): this\n  /** AND a raw, adapter-dialect filter expressed as a `{ $dialect, $raw, $bindings }` object. */\n  whereRaw(rawObj: { $dialect: string; $raw: unknown; $bindings?: unknown[] }): this\n  whereRaw(\n    sqlOrObj: string | { $dialect: string; $raw: unknown; $bindings?: unknown[] },\n    bindings?: unknown[]\n  ): this {\n    if (typeof sqlOrObj === 'object') {\n      this.andConditions.push({\n        $dialect: sqlOrObj.$dialect,\n        $raw: sqlOrObj.$raw,\n        $bindings: sqlOrObj.$bindings ?? [],\n      })\n    } else {\n      this.andConditions.push({ $dialect: 'sql', $raw: sqlOrObj, $bindings: bindings ?? [] })\n    }\n    return this\n  }\n\n  protected buildFilter(): VectorFilter | undefined {\n    if (this.andConditions.length === 0 && this.orBranches.length === 0) {\n      return undefined\n    }\n\n    if (this.orBranches.length > 0) {\n      const orGroups: VectorFilter[][] = []\n      if (this.andConditions.length > 0) {\n        orGroups.push(this.andConditions)\n      }\n      for (const branch of this.orBranches) {\n        if (branch.length > 0) {\n          orGroups.push(branch)\n        }\n      }\n      if (orGroups.length === 1) {\n        return { and: orGroups[0] }\n      }\n      return { or: orGroups.map((conds) => ({ and: conds })) }\n    }\n\n    return { and: this.andConditions }\n  }\n\n  protected extractIdsFromFilter(): string[] {\n    const ids: string[] = []\n    const only = this.andConditions.length === 1 ? this.andConditions[0] : undefined\n    if (\n      only &&\n      isFilterCondition(only) &&\n      only.field === 'id' &&\n      only.op === 'in' &&\n      Array.isArray(only.value)\n    ) {\n      ids.push(...(only.value as string[]))\n    }\n    return ids\n  }\n}\n\nclass VectorQueryBuilder extends FilterBuilder implements PromiseLike<VectorMatch[]> {\n  #sink: PlanSink\n  #collection: string\n  #near: { vector: number[] } | { serverText: string } | { id: string } | undefined\n  #projection: Projection = { id: false, vector: false, document: false, metadata: false }\n  #topK: number\n  #offset: number = 0\n  #selectCalled: boolean = false\n  #consistency: VectorConsistency | undefined\n\n  constructor(sink: PlanSink, collection: string, defaultTopK: number) {\n    super()\n    this.#sink = sink\n    this.#collection = collection\n    this.#topK = defaultTopK\n  }\n\n  /**\n   * Search by nearest neighbours to a client-supplied query `vector`. Mutually exclusive with the\n   * other `near*` clauses.\n   *\n   * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n   */\n  nearVector(vector: number[]): this {\n    if (this.#near !== undefined) {\n      throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n    }\n    this.#near = { vector }\n    return this\n  }\n\n  /**\n   * Search by nearest neighbours to `text`, embedded server-side by the backend. Mutually exclusive\n   * with the other `near*` clauses.\n   *\n   * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n   */\n  nearText(text: string): this {\n    if (this.#near !== undefined) {\n      throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n    }\n    this.#near = { serverText: text }\n    return this\n  }\n\n  /**\n   * Search by nearest neighbours to the stored vector of the record with the given `id`. Mutually\n   * exclusive with the other `near*` clauses.\n   *\n   * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n   */\n  nearId(id: string): this {\n    if (this.#near !== undefined) {\n      throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n    }\n    this.#near = { id }\n    return this\n  }\n\n  /**\n   * Declare which fields each match projects (id / vector / document / metadata). Required before a\n   * search terminal runs. Accepts {@link SelectArg}s: `'*'`, field names, `[field, config]` tuples,\n   * or `{ field: config }` maps.\n   */\n  select(...args: SelectArg[]): this {\n    this.#selectCalled = true\n    for (const arg of args) {\n      if (typeof arg === 'string') {\n        if (arg === '*') {\n          this.#projection = { id: true, vector: {}, document: {}, metadata: {} }\n        } else {\n          if (arg === 'id') {\n            this.#projection.id = true\n          } else if (arg === 'vector') {\n            this.#projection.vector = {}\n          } else if (arg === 'document') {\n            this.#projection.document = {}\n          } else if (arg === 'metadata') {\n            this.#projection.metadata = {}\n          }\n        }\n      } else if (Array.isArray(arg)) {\n        const [field, config] = arg\n        if (field === 'vector') {\n          this.#projection.vector = config as { name?: string }\n        } else if (field === 'document') {\n          this.#projection.document = config as { field?: string }\n        } else if (field === 'metadata') {\n          this.#projection.metadata = config as { fields?: string[] }\n        } else if (field === 'id') {\n          this.#projection.id = true\n        }\n      } else if (typeof arg === 'object') {\n        for (const key of Object.keys(arg)) {\n          if (key === 'vector') {\n            this.#projection.vector = arg[key] as { name?: string }\n          } else if (key === 'document') {\n            this.#projection.document = arg[key] as { field?: string }\n          } else if (key === 'metadata') {\n            this.#projection.metadata = arg[key] as { fields?: string[] }\n          } else if (key === 'id') {\n            this.#projection.id = true\n          }\n        }\n      }\n    }\n    return this\n  }\n\n  /** Cap the number of matches returned (the search `topK`). */\n  limit(n: number): this {\n    this.#topK = n\n    return this\n  }\n\n  /** Skip the first `n` matches before returning results. */\n  offset(n: number): this {\n    this.#offset = n\n    return this\n  }\n\n  /**\n   * Per-operation read-after-write override for the terminal `.upsert()` / `.delete()`.\n   * Universal across adapters: strongly-consistent backends ignore it (no-op), so a chain\n   * written for an eventually-consistent backend keeps working verbatim when the adapter is\n   * swapped. Precedence: this > the store's `consistency` option > the adapter's declared\n   * `capabilities.consistency.default`. See {@link VectorConsistency}.\n   */\n  consistency(mode: VectorConsistency): this {\n    this.#consistency = mode\n    return this\n  }\n\n  then<TR1 = VectorMatch[], TR2 = never>(\n    onfulfilled?: ((value: VectorMatch[]) => TR1 | PromiseLike<TR1>) | null,\n    onrejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null\n  ): PromiseLike<TR1 | TR2> {\n    return this.#run().then(onfulfilled as any, onrejected as any)\n  }\n\n  async #run(): Promise<VectorMatch[]> {\n    if (!this.#selectCalled) {\n      throw new E_VECTOR_STORE_PROJECTION_REQUIRED()\n    }\n\n    const filter = this.buildFilter()\n\n    const plan: SearchPlan = {\n      collection: this.#collection,\n      near: this.#near,\n      filter,\n      topK: this.#topK,\n      offset: this.#offset,\n      projection: this.#projection,\n    }\n\n    this.#validateRawFilters(plan.filter)\n\n    return await this.#sink.executeSearch(plan)\n  }\n\n  /** Terminal: insert or replace `records` in the collection. */\n  async upsert(records: VectorRecord[]): Promise<void> {\n    const plan: UpsertPlan = {\n      collection: this.#collection,\n      records,\n      consistency: this.#consistency,\n    }\n    await this.#sink.executeUpsert(plan)\n  }\n\n  /** Terminal: delete records matching the accumulated filter (or the `id IN [...]` fast path). */\n  async delete(): Promise<void> {\n    const ids = this.extractIdsFromFilter()\n    const filter = this.buildFilter()\n\n    const plan: DeletePlan = {\n      collection: this.#collection,\n      ids: ids.length > 0 ? ids : undefined,\n      filter: filter && Object.keys(filter).length > 0 ? filter : undefined,\n      consistency: this.#consistency,\n    }\n\n    await this.#sink.executeDelete(plan)\n  }\n\n  #validateRawFilters(filter: VectorFilter | undefined): void {\n    if (!filter) {\n      return\n    }\n\n    if (isRawFilter(filter)) {\n      const raw = filter.$raw as string\n      const placeholders = (raw.match(/\\?/g) || []).length\n      if (placeholders !== filter.$bindings?.length) {\n        throw new E_VECTOR_STORE_RAW_BINDING_MISMATCH([placeholders, filter.$bindings?.length ?? 0])\n      }\n      return\n    }\n\n    if ('and' in filter && filter.and) {\n      for (const f of filter.and) {\n        this.#validateRawFilters(f)\n      }\n    }\n\n    if ('or' in filter && filter.or) {\n      for (const f of filter.or) {\n        this.#validateRawFilters(f)\n      }\n    }\n\n    if ('not' in filter && filter.not) {\n      this.#validateRawFilters(filter.not)\n    }\n  }\n}\n\nexport { VectorQueryBuilder, FilterBuilder }\n"],"mappings":"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"}