{"version":3,"file":"typesense.mjs","names":["#opts","#client","#ensure","#dims","#project","#parseMeta"],"sources":["../../../src/batteries/vector/typesense/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/typesense\n *\n * Typesense adapter. Each collection is a Typesense collection with a `float[]` vector field\n * (native `vector_query` KNN). Metadata is stored as a JSON string field and filtered with\n * the neutral filter tree's JS reference evaluator for exact cross-adapter parity (Typesense\n * filter_by requires per-field schema declaration, which the neutral metadata model doesn't\n * have). Document + id are plain fields.\n *\n * Driver: `typesense` (pure JS).\n */\n\nimport { evaluateFilter } from '../filters'\nimport { normalizeScore } from '../helpers'\nimport { BaseVectorStore } from '../contract'\nimport { validateRecords } from '../validation'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport {\n  E_VECTOR_STORE_DRIVER_UNAVAILABLE,\n  E_VECTOR_STORE_CONNECTION_FAILED,\n  E_VECTOR_STORE_COLLECTION_FAILED,\n  E_VECTOR_STORE_UPSERT_FAILED,\n  E_VECTOR_STORE_SEARCH_FAILED,\n  E_VECTOR_STORE_DELETE_FAILED,\n  E_VECTOR_STORE_DIMENSION_MISMATCH,\n  E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n} from '../exceptions'\nimport type { SearchPlan, UpsertPlan, DeletePlan, CollectionSpec } from '../plan'\nimport type {\n  VectorMatch,\n  VectorStoreCapabilities,\n  BaseVectorStoreOptions,\n  VectorMetadata,\n  DistanceMetric,\n} from '../types'\n\nexport interface TypesenseVectorStoreOptions extends BaseVectorStoreOptions {\n  /** Connection and authentication parameters for the backend. */\n  connection?: {\n    host?: string\n    port?: number\n    protocol?: string\n    apiKey?: string\n    url?: string\n  }\n}\n\nconst getTypesense = async () => {\n  try {\n    const mod = await import('typesense')\n    return (mod as any).default ?? mod\n  } catch {\n    throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['typesense'])\n  }\n}\n\nexport class TypesenseVectorStore extends BaseVectorStore {\n  readonly capabilities: VectorStoreCapabilities = {\n    transactions: false,\n    namedVectors: false,\n    rename: false,\n    rawSql: false,\n    builtInEncoding: false,\n    // Typesense indexes writes synchronously (searchable on resolve). The option is a no-op.\n    consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n  }\n\n  #client: any | null = null\n  #dims: Map<string, number> = new Map()\n\n  get #opts(): TypesenseVectorStoreOptions {\n    return this.options as TypesenseVectorStoreOptions\n  }\n\n  /** Static availability probe: whether this adapter's runtime driver can load in the current environment. */\n  static isAvailable(): boolean {\n    return typeof process !== 'undefined'\n  }\n  isAvailable(): boolean {\n    return typeof process !== 'undefined'\n  }\n\n  async connect(): Promise<void> {\n    if (this.#client) return\n    const Typesense = await getTypesense()\n    const c = this.#opts.connection || {}\n    let node: any\n    if (c.url) {\n      const u = new URL(c.url)\n      node = {\n        host: u.hostname,\n        port: Number(u.port) || (u.protocol === 'https:' ? 443 : 8108),\n        protocol: u.protocol.replace(':', ''),\n      }\n    } else {\n      node = { host: c.host ?? 'localhost', port: c.port ?? 8108, protocol: c.protocol ?? 'http' }\n    }\n    try {\n      this.#client = new Typesense.Client({\n        nodes: [node],\n        apiKey: c.apiKey ?? 'xyz',\n        connectionTimeoutSeconds: 5,\n      })\n    } catch (err) {\n      throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n    }\n  }\n\n  async close(): Promise<void> {\n    this.#client = null\n  }\n\n  async #ensure(): Promise<any> {\n    if (!this.#client) await this.connect()\n    return this.#client!\n  }\n\n  async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n    const client = await this.#ensure()\n    this.#dims.set(spec.collection, spec.vector.dimensions)\n    if (ifNotExists && (await this.hasCollection(spec.collection))) return\n    try {\n      await client.collections().create({\n        name: spec.collection,\n        fields: [\n          { name: 'id', type: 'string' },\n          { name: 'vec', type: 'float[]', num_dim: spec.vector.dimensions },\n          { name: 'document', type: 'string', optional: true },\n          { name: 'metadata', type: 'string', optional: true },\n        ],\n      })\n    } catch (err) {\n      throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', String(err)])\n    }\n  }\n\n  async dropCollection(collection: string, ifExists: boolean): Promise<void> {\n    const client = await this.#ensure()\n    if (ifExists && !(await this.hasCollection(collection))) return\n    try {\n      await client.collections(collection).delete()\n      this.#dims.delete(collection)\n    } catch (err) {\n      const msg = String(err)\n      if (ifExists && msg.includes('Not Found')) return\n      throw new E_VECTOR_STORE_COLLECTION_FAILED(['dropCollection', msg])\n    }\n  }\n\n  async hasCollection(collection: string): Promise<boolean> {\n    const client = await this.#ensure()\n    try {\n      await client.collections(collection).retrieve()\n      return true\n    } catch {\n      return false\n    }\n  }\n\n  async renameCollection(_from: string, _to: string): Promise<void> {\n    throw new E_VECTOR_STORE_UNSUPPORTED_OPERATION(['renameCollection', 'typesense'])\n  }\n\n  async executeUpsert(plan: UpsertPlan): Promise<void> {\n    if (plan.records.length === 0) return\n    validateRecords(plan.records)\n    const client = await this.#ensure()\n    const expected = this.#opts.dimensions ?? this.#dims.get(plan.collection)\n    try {\n      const docs: any[] = []\n      for (const r of plan.records) {\n        let vector = r.vector\n        if (!vector && r.document) {\n          const [v] = await this.encode([r.document], 'document')\n          vector = v\n        }\n        if (!vector) {\n          throw new E_VECTOR_STORE_UPSERT_FAILED(['Record missing vector and document'])\n        }\n        if (expected !== undefined && vector.length !== expected) {\n          throw new E_VECTOR_STORE_DIMENSION_MISMATCH([expected, vector.length])\n        }\n        docs.push({\n          id: r.id,\n          vec: vector,\n          document: r.document ?? '',\n          metadata: r.metadata ? JSON.stringify(r.metadata) : '{}',\n        })\n      }\n      await client.collections(plan.collection).documents().import(docs, { action: 'upsert' })\n    } catch (err) {\n      if (\n        isInstanceOf(err, 'E_VECTOR_STORE_DIMENSION_MISMATCH', E_VECTOR_STORE_DIMENSION_MISMATCH) ||\n        isInstanceOf(err, 'E_VECTOR_STORE_UPSERT_FAILED', E_VECTOR_STORE_UPSERT_FAILED)\n      ) {\n        throw err\n      }\n      throw new E_VECTOR_STORE_UPSERT_FAILED([String(err)])\n    }\n  }\n\n  async executeSearch(plan: SearchPlan): Promise<VectorMatch[]> {\n    const client = await this.#ensure()\n    const metric = this.#opts.metric ?? 'cosine'\n    let queryVector: number[] | undefined\n    if (plan.near) {\n      if ('vector' in plan.near) {\n        queryVector = plan.near.vector\n      } else if ('serverText' in plan.near) {\n        const [v] = await this.encode([plan.near.serverText], 'query')\n        queryVector = v\n      } else if ('id' in plan.near) {\n        try {\n          const doc = await client.collections(plan.collection).documents(plan.near.id).retrieve()\n          queryVector = doc.vec as number[]\n        } catch {\n          queryVector = undefined\n        }\n        if (!queryVector) {\n          throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n        }\n      }\n    }\n\n    const offset = plan.offset ?? 0\n    try {\n      const coll = client.collections(plan.collection).documents()\n      if (queryVector) {\n        // Over-fetch then JS-filter for exact cross-adapter filter semantics.\n        const k = Math.max(plan.topK + offset, plan.topK) + (plan.filter ? 250 : 0)\n        const res = await coll.search({\n          q: '*',\n          vector_query: `vec:([${queryVector.join(',')}], k:${k})`,\n          per_page: Math.min(250, k),\n        })\n        const hits = (res.hits ?? []) as any[]\n        const mapped = hits.map((hit) => ({\n          match: this.#project(hit.document, plan, metric, hit.vector_distance),\n          meta: this.#parseMeta(hit.document.metadata),\n        }))\n        const filtered = plan.filter\n          ? mapped.filter((m) => evaluateFilter(plan.filter!, m.meta))\n          : mapped\n        return filtered.slice(offset, offset + plan.topK).map((m) => m.match)\n      } else {\n        const res = await coll.search({ q: '*', query_by: 'document', per_page: 250 })\n        const hits = (res.hits ?? []) as any[]\n        const mapped = hits.map((hit) => ({\n          match: this.#project(hit.document, plan, metric, undefined),\n          meta: this.#parseMeta(hit.document.metadata),\n        }))\n        const filtered = plan.filter\n          ? mapped.filter((m) => evaluateFilter(plan.filter!, m.meta))\n          : mapped\n        return filtered.slice(offset, offset + plan.topK).map((m) => m.match)\n      }\n    } catch (err) {\n      throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n    }\n  }\n\n  #parseMeta(val: unknown): VectorMetadata {\n    if (typeof val === 'string') {\n      try {\n        return JSON.parse(val) as VectorMetadata\n      } catch {\n        return {}\n      }\n    }\n    if (val && typeof val === 'object') return val as VectorMetadata\n    return {}\n  }\n\n  #project(doc: any, plan: SearchPlan, metric: string, dist: number | undefined): VectorMatch {\n    const proj = plan.projection\n    const out: VectorMatch = {}\n    if (proj.id) out.id = doc.id as string\n    if (proj.vector && Array.isArray(doc.vec)) out.vector = doc.vec as number[]\n    if (proj.document) out.document = (doc.document ?? undefined) as string | undefined\n    if (proj.metadata) out.metadata = this.#parseMeta(doc.metadata)\n    if (dist !== undefined && dist !== null) {\n      out.score = normalizeScore(Number(dist), metric as DistanceMetric, 'distance')\n    }\n    return out\n  }\n\n  async executeDelete(plan: DeletePlan): Promise<void> {\n    const client = await this.#ensure()\n    const collection = client.collections(plan.collection)\n    const coll = collection.documents()\n    // Delete a single document by id: documents(id).delete() (NOT documents().delete(id),\n    // which targets the bulk filter endpoint).\n    const deleteOne = async (id: string): Promise<void> => {\n      await collection\n        .documents(id)\n        .delete()\n        .catch(() => undefined)\n    }\n    try {\n      if (plan.ids && plan.ids.length > 0) {\n        for (const id of plan.ids) await deleteOne(id)\n      } else if (plan.filter) {\n        // Resolve ids via a scan + JS evaluator, then delete by id.\n        const res = await coll.search({ q: '*', query_by: 'document', per_page: 250 })\n        const hits = (res.hits ?? []) as any[]\n        const targets = hits\n          .filter((hit) => evaluateFilter(plan.filter!, this.#parseMeta(hit.document.metadata)))\n          .map((hit) => hit.document.id as string)\n        for (const id of targets) await deleteOne(id)\n      } else {\n        // Delete-all: bulk delete by an always-true filter; fall back to per-id on error.\n        try {\n          await coll.delete({ filter_by: 'id:!= ' })\n        } catch {\n          const res = await coll.search({ q: '*', query_by: 'document', per_page: 250 })\n          const hits = (res.hits ?? []) as any[]\n          for (const hit of hits) await deleteOne(hit.document.id as string)\n        }\n      }\n    } catch (err) {\n      throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n    }\n  }\n}\n"],"mappings":"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"}