{"version":3,"sources":["/home/runner/work/libsql-vector/libsql-vector/dist/index.cjs","../src/index.ts"],"names":[],"mappings":"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","file":"/home/runner/work/libsql-vector/libsql-vector/dist/index.cjs","sourcesContent":[null,"import { Client, ResultSet, Value, LibsqlError, InValue } from \"@libsql/client\";\n\nexport type ColumnDefinition = {\n  name: string;\n  type: string;\n};\n\nexport interface Vector {\n  id: string | number;\n  vector: number[];\n  [key: string]: Value | number[];\n}\n\nexport interface QueryOptions {\n  topK: number;\n  includeVectors?: boolean;\n  filter?: string;\n}\n\nexport interface QueryResponse {\n  id: string | number;\n  score: number;\n  vector?: number[];\n  [key: string]: Value | number[] | undefined;\n}\n\nexport interface IndexOptions {\n  tableName?: string;\n  dimensions: number;\n  columns: ColumnDefinition[];\n  debug?: boolean;\n}\n\nexport interface ListOptions {\n  cursor?: string;\n  limit?: number;\n  includeVectors?: boolean;\n  includeMetadata?: boolean;\n}\n\nexport interface ListResponse {\n  items: ListItem[];\n  nextCursor: string | null;\n}\n\nexport interface ListItem {\n  id: string | number;\n  vector?: number[];\n  metadata?: Record<string, Value>;\n  [key: string]: Value | number[] | undefined | Record<string, Value>;\n}\n\nexport interface RetrieveOptions {\n  includeVector?: boolean;\n  includeMetadata?: boolean;\n}\n\nexport interface RetrieveResponse {\n  id: string | number;\n  vector?: number[];\n  metadata?: Record<string, Value>;\n  [key: string]: Value | number[] | undefined | Record<string, Value>;\n}\n\nexport class Index {\n  private client: Client;\n  private tableName: string;\n  private dimensions: number;\n  private columns: ColumnDefinition[];\n  private debug: boolean;\n\n  constructor(client: Client, options: IndexOptions) {\n    this.client = client;\n    this.tableName = options.tableName || \"vector_index\";\n    this.dimensions = options.dimensions;\n    this.columns = options.columns;\n    this.debug = options.debug || false;\n  }\n\n  private log(...args: any[]): void {\n    if (this.debug) {\n      console.log(...args);\n    }\n  }\n\n  async initialize(): Promise<void> {\n    await this.createTable();\n    await this.createIndex();\n  }\n\n  async upsert(vectors: Vector | Vector[]): Promise<string> {\n    const vectorArray = Array.isArray(vectors) ? vectors : [vectors];\n\n    const columnNames = [\n      \"id\",\n      \"embedding\",\n      ...this.columns.map((col) => col.name),\n    ];\n\n    for (const vec of vectorArray) {\n      const values = [\n        `'${vec.id.toString().replace(/'/g, \"''\")}'`,\n        // `vector32(x'${Buffer.from(new Float32Array(vec.vector).buffer).toString(\"hex\")}')`,\n        `vector32('[${vec.vector.join(\", \")}]')`,\n        ...this.columns.map((col) => {\n          const value = vec[col.name];\n          return typeof value === \"string\"\n            ? `'${value.replace(/'/g, \"''\")}'`\n            : value;\n        }),\n      ];\n\n      const sql = `\n        INSERT OR REPLACE INTO ${this.tableName} (${columnNames.join(\", \")})\n        VALUES (${values.join(\", \")})\n      `;\n\n      this.log(\"Upsert SQL:\", sql);\n\n      await this.client.execute(sql);\n    }\n\n    return \"Success\";\n  }\n\n  async query(\n    queryVector: number[],\n    options: QueryOptions,\n  ): Promise<QueryResponse[]> {\n    const { topK, includeVectors = false, filter = \"\" } = options;\n\n    const selectClauses = [\n      `${this.tableName}.id`,\n      `1 - vector_distance_cos(embedding, vector32('[${queryVector.join(\", \")}]')) as similarity`,\n      ...this.columns.map((col) => col.name),\n    ];\n\n    if (includeVectors)\n      selectClauses.push(\"vector_extract(embedding) as vector\");\n\n    const sql = `\n        SELECT ${selectClauses.join(\", \")}\n        FROM ${this.tableName}\n        ${filter ? `WHERE ${filter}` : \"\"}\n        ORDER BY similarity DESC\n        LIMIT ?\n      `;\n\n    this.log(\"Query SQL:\", sql);\n\n    const result: ResultSet = await this.client.execute({ sql, args: [topK] });\n\n    this.log(\"Query result:\", result.rows);\n\n    return result.rows.map((row) => {\n      const response: QueryResponse = {\n        id: this.ensureIdType(row.id),\n        score: this.ensureNumber(row.similarity),\n      };\n\n      if (includeVectors) {\n        response.vector = this.parseVector(row.vector);\n      }\n\n      this.columns.forEach((col) => {\n        response[col.name] = row[col.name];\n      });\n\n      return response;\n    });\n  }\n\n  async list(options: ListOptions = {}): Promise<ListResponse> {\n    const {\n      cursor,\n      limit = 10,\n      includeVectors = false,\n      includeMetadata = true,\n    } = options;\n\n    const selectClauses = [`${this.tableName}.id`];\n\n    if (includeVectors) {\n      selectClauses.push(`vector_extract(embedding) as vector`);\n    }\n\n    if (includeMetadata) {\n      this.columns.forEach((col) => selectClauses.push(col.name));\n    }\n\n    let sql = `SELECT ${selectClauses.join(\", \")} FROM ${this.tableName}`;\n    const args: any[] = [];\n\n    if (cursor) {\n      sql += ` WHERE id > ?`;\n      args.push(cursor);\n    }\n\n    sql += ` ORDER BY id LIMIT ?`;\n    args.push(limit + 1); // Fetch one extra to determine if there's a next page\n\n    this.log(\"List SQL:\", sql);\n    this.log(\"List args:\", args);\n\n    const result = await this.client.execute({ sql, args });\n\n    if (!result || !result.rows || result.rows.length === 0) {\n      return { items: [], nextCursor: null };\n    }\n\n    const items: ListItem[] = result.rows.slice(0, limit).map((row) => {\n      const item: ListItem = { id: this.ensureIdType(row.id) };\n\n      if (includeVectors && row.vector) {\n        item.vector = this.parseVector(row.vector);\n      }\n\n      if (includeMetadata) {\n        item.metadata = {};\n        this.columns.forEach((col) => {\n          item.metadata![col.name] = row[col.name];\n        });\n      }\n\n      return item;\n    });\n\n    let nextCursor: string | null = null;\n\n    if (result.rows.length > limit) {\n      const lastItem = result.rows[limit - 1];\n\n      if (lastItem && lastItem.id != null) {\n        nextCursor = lastItem.id.toString();\n      }\n    }\n\n    return { items, nextCursor };\n  }\n\n  async retrieve(\n    ids: string | number | (string | number)[],\n    options: RetrieveOptions = {},\n  ): Promise<RetrieveResponse | RetrieveResponse[]> {\n    const { includeVector = true, includeMetadata = true } = options;\n    const idsArray = Array.isArray(ids) ? ids : [ids];\n\n    const selectClauses = [`${this.tableName}.id`];\n    if (includeVector) {\n      selectClauses.push(`vector_extract(embedding) as vector`);\n    }\n    if (includeMetadata) {\n      this.columns.forEach((col) => selectClauses.push(col.name));\n    }\n\n    const sql = `\n      SELECT ${selectClauses.join(\", \")}\n      FROM ${this.tableName}\n      WHERE id IN (${idsArray.map(() => \"?\").join(\", \")})\n    `;\n\n    this.log(\"Retrieve SQL:\", sql);\n    this.log(\"Retrieve args:\", idsArray);\n\n    const result = await this.client.execute({ sql, args: idsArray });\n\n    const items: RetrieveResponse[] = result.rows.map((row) => {\n      const item: RetrieveResponse = { id: this.ensureIdType(row.id) };\n      if (includeVector && row.vector) {\n        item.vector = this.parseVector(row.vector);\n      }\n      if (includeMetadata) {\n        item.metadata = {};\n        this.columns.forEach((col) => {\n          item.metadata![col.name] = row[col.name];\n        });\n      }\n      return item;\n    });\n\n    return Array.isArray(ids) ? items : items[0];\n  }\n\n  private async createTable(): Promise<void> {\n    const columnDefinitions = this.columns\n      .map((col) => `${col.name} ${col.type}`)\n      .join(\", \");\n\n    const sql = `\n      CREATE TABLE IF NOT EXISTS ${this.tableName} (\n        id TEXT PRIMARY KEY,\n        embedding F32_BLOB(${this.dimensions}),\n        ${columnDefinitions}\n      )\n    `;\n\n    this.log(\"Create table SQL:\", sql);\n\n    await this.client.execute(sql);\n  }\n\n  private async createIndex(): Promise<void> {\n    const sql = `CREATE INDEX IF NOT EXISTS idx_${this.tableName}_embedding ON ${this.tableName}(libsql_vector_idx(embedding))`;\n\n    this.log(\"Create index SQL:\", sql);\n\n    await this.client.execute(sql);\n  }\n\n  private ensureIdType(value: Value): string | number {\n    if (typeof value === \"string\" || typeof value === \"number\") {\n      return value;\n    }\n\n    if (typeof value === \"bigint\") {\n      return Number(value);\n    }\n\n    throw new Error(`Invalid id type: ${typeof value}`);\n  }\n\n  private ensureNumber(value: Value): number {\n    if (typeof value === \"number\") {\n      return value;\n    }\n\n    if (typeof value === \"string\") {\n      return parseFloat(value);\n    }\n\n    if (typeof value === \"bigint\") {\n      return Number(value);\n    }\n\n    throw new Error(`Invalid score type: ${typeof value}`);\n  }\n\n  private parseVector(value: Value): number[] | undefined {\n    if (typeof value === \"string\") {\n      try {\n        return JSON.parse(value);\n      } catch (e) {\n        throw new Error(`Failed to parse vector: ${e}`);\n      }\n    }\n    if (value instanceof ArrayBuffer) {\n      // Make this configurable? Float32Array\n      return Array.from(new Float32Array(value));\n    }\n    if (value === null) {\n      return undefined;\n    }\n    throw new Error(`Invalid vector type: ${typeof value}`);\n  }\n}\n\nexport { LibsqlError };\n"]}