import { DEFAULT_HEADERS } from '../lib/constants' import { StorageError } from '../lib/common/errors' import { Fetch, vectorsApi } from '../lib/common/fetch' import BaseApiClient from '../lib/common/BaseApiClient' import { ApiResponse, PutVectorsOptions, GetVectorsOptions, GetVectorsResponse, DeleteVectorsOptions, ListVectorsOptions, ListVectorsResponse, QueryVectorsOptions, QueryVectorsResponse, } from '../lib/types' /** * @hidden * Base implementation for vector data operations. * Use {@link VectorIndexScope} via `supabase.storage.vectors.from('bucket').index('idx')` instead. */ export default class VectorDataApi extends BaseApiClient { /** Creates a new VectorDataApi instance */ constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) { const finalUrl = url.replace(/\/$/, '') const finalHeaders = { ...DEFAULT_HEADERS, 'Content-Type': 'application/json', ...headers } super(finalUrl, finalHeaders, fetch, 'vectors') } /** Inserts or updates vectors in batch (1-500 per request) */ async putVectors(options: PutVectorsOptions): Promise> { // Validate batch size if (options.vectors.length < 1 || options.vectors.length > 500) { throw new Error('Vector batch size must be between 1 and 500 items') } return this.handleOperation(async () => { const data = await vectorsApi.post(this.fetch, `${this.url}/PutVectors`, options, { headers: this.headers, }) return data || {} }) } /** Retrieves vectors by their keys in batch */ async getVectors(options: GetVectorsOptions): Promise> { return this.handleOperation(async () => { return await vectorsApi.post(this.fetch, `${this.url}/GetVectors`, options, { headers: this.headers, }) }) } /** Lists vectors in an index with pagination */ async listVectors(options: ListVectorsOptions): Promise> { // Validate segment configuration if (options.segmentCount !== undefined) { if (options.segmentCount < 1 || options.segmentCount > 16) { throw new Error('segmentCount must be between 1 and 16') } if (options.segmentIndex !== undefined) { if (options.segmentIndex < 0 || options.segmentIndex >= options.segmentCount) { throw new Error(`segmentIndex must be between 0 and ${options.segmentCount - 1}`) } } } return this.handleOperation(async () => { return await vectorsApi.post(this.fetch, `${this.url}/ListVectors`, options, { headers: this.headers, }) }) } /** Queries for similar vectors using approximate nearest neighbor search */ async queryVectors(options: QueryVectorsOptions): Promise> { return this.handleOperation(async () => { return await vectorsApi.post(this.fetch, `${this.url}/QueryVectors`, options, { headers: this.headers, }) }) } /** Deletes vectors by their keys in batch (1-500 per request) */ async deleteVectors(options: DeleteVectorsOptions): Promise> { // Validate batch size if (options.keys.length < 1 || options.keys.length > 500) { throw new Error('Keys batch size must be between 1 and 500 items') } return this.handleOperation(async () => { const data = await vectorsApi.post(this.fetch, `${this.url}/DeleteVectors`, options, { headers: this.headers, }) return data || {} }) } }