UNPKG

chromadb

Version:

A JavaScript interface for chroma

1 lines 317 kB
{"version":3,"sources":["../src/deno.ts","../src/types.ts","../../../node_modules/.pnpm/@hey-api+client-fetch@0.10.0_@hey-api+openapi-ts@0.67.3_typescript@5.8.3_/node_modules/@hey-api/client-core/src/auth.ts","../../../node_modules/.pnpm/@hey-api+client-fetch@0.10.0_@hey-api+openapi-ts@0.67.3_typescript@5.8.3_/node_modules/@hey-api/client-core/src/bodySerializer.ts","../../../node_modules/.pnpm/@hey-api+client-fetch@0.10.0_@hey-api+openapi-ts@0.67.3_typescript@5.8.3_/node_modules/@hey-api/client-core/src/pathSerializer.ts","../../../node_modules/.pnpm/@hey-api+client-fetch@0.10.0_@hey-api+openapi-ts@0.67.3_typescript@5.8.3_/node_modules/@hey-api/client-fetch/src/utils.ts","../../../node_modules/.pnpm/@hey-api+client-fetch@0.10.0_@hey-api+openapi-ts@0.67.3_typescript@5.8.3_/node_modules/@hey-api/client-fetch/src/client.ts","../src/api/client.gen.ts","../src/api/sdk.gen.ts","../src/errors.ts","../src/utils.ts","../src/embedding-function.ts","../src/collection-configuration.ts","../src/execution/expression/common.ts","../src/execution/expression/where.ts","../src/execution/expression/key.ts","../src/execution/expression/limit.ts","../src/execution/expression/select.ts","../src/execution/expression/rank.ts","../src/execution/expression/search.ts","../src/execution/expression/searchResult.ts","../src/schema.ts","../src/collection.ts","../src/next.ts","../src/chroma-fetch.ts","../src/admin-client.ts","../src/chroma-client.ts","../src/cloud-client.ts"],"sourcesContent":["// Deno compatibility patch for @hey-api/client-fetch\n// This must be imported before any @hey-api/client-fetch code\n\nif (typeof (globalThis as any).Deno !== \"undefined\") {\n // Store the original Request constructor\n const OriginalRequest = globalThis.Request;\n\n // Create a patched Request constructor that strips Deno-incompatible properties\n const PatchedRequest = function (\n input: RequestInfo | URL,\n init?: RequestInit,\n ) {\n if (init && typeof init === \"object\") {\n const cleanInit = { ...init };\n if (\"client\" in cleanInit) {\n delete (cleanInit as any).client;\n }\n return new OriginalRequest(input, cleanInit);\n }\n return new OriginalRequest(input, init);\n } as any;\n\n // Copy over static properties and prototype\n Object.setPrototypeOf(PatchedRequest, OriginalRequest);\n Object.defineProperty(PatchedRequest, \"prototype\", {\n value: OriginalRequest.prototype,\n writable: false,\n });\n\n // Replace the global Request constructor\n globalThis.Request = PatchedRequest;\n}\n","import { GetUserIdentityResponse, Include, SparseVector } from \"./api\";\n\n/**\n * User identity information including tenant and database access.\n */\nexport type UserIdentity = GetUserIdentityResponse;\n\n/**\n * Re-export SparseVector type for external use\n */\nexport type { SparseVector };\n\n/**\n * Metadata that can be associated with a collection.\n * Values must be boolean, number, or string types.\n */\nexport type CollectionMetadata = Record<\n string,\n boolean | number | string | SparseVector | null\n>;\n\n/**\n * Metadata that can be associated with individual records.\n * Values must be boolean, number, or string types.\n */\nexport type Metadata = Record<\n string,\n boolean | number | string | SparseVector | null\n>;\n\n/**\n * Base interface for record sets containing optional fields.\n */\nexport interface BaseRecordSet {\n /** Array of embedding vectors */\n embeddings?: number[][];\n /** Array of metadata objects */\n metadatas?: Metadata[];\n /** Array of document text content */\n documents?: string[];\n /** Array of URIs/URLs */\n uris?: string[];\n}\n\nexport const baseRecordSetFields = [\n \"ids\",\n \"embeddings\",\n \"metadatas\",\n \"documents\",\n \"uris\",\n];\n\n/**\n * Complete record set with required IDs for operations like add/update.\n */\nexport interface RecordSet extends BaseRecordSet {\n /** Array of unique record identifiers */\n ids: string[];\n}\n\nexport interface PreparedRecordSet extends Omit<RecordSet, \"embeddings\"> {\n embeddings?: number[][] | string[];\n}\n\nexport interface PreparedInsertRecordSet extends PreparedRecordSet {\n embeddings: number[][] | string[];\n}\n\nexport const recordSetFields = [...baseRecordSetFields, \"ids\"];\n\n/**\n * Record set for query operations with required embeddings.\n */\nexport interface QueryRecordSet extends BaseRecordSet {\n /** Optional array of record IDs to filter by */\n ids?: string[];\n /** Array of query embedding vectors (required for queries) */\n embeddings: number[][];\n}\n\ntype LiteralValue = string | number | boolean;\n\ntype LogicalOperator = \"$and\" | \"$or\";\n\ntype WhereOperator = \"$gt\" | \"$gte\" | \"$lt\" | \"$lte\" | \"$ne\" | \"$eq\";\n\ntype InclusionExclusionOperator = \"$in\" | \"$nin\";\n\ntype OperatorExpression =\n | { $gt: LiteralValue }\n | { $gte: LiteralValue }\n | { $lt: LiteralValue }\n | { $lte: LiteralValue }\n | { $ne: LiteralValue }\n | { $eq: LiteralValue }\n | { $and: LiteralValue }\n | { $or: LiteralValue }\n | { $in: LiteralValue[] }\n | { $nin: LiteralValue[] };\n\n/**\n * Where clause for filtering records based on metadata.\n * Supports field equality, comparison operators, and logical operators.\n */\nexport type Where =\n | { [key: string]: LiteralValue | OperatorExpression }\n | { $and: Where[] }\n | { $or: Where[] };\n\ntype WhereDocumentOperator =\n | \"$contains\"\n | \"$not_contains\"\n | \"$matches\"\n | \"$not_matches\"\n | \"$regex\"\n | \"$not_regex\"\n | LogicalOperator;\n\n/**\n * Where clause for filtering based on document content.\n * Supports text search operators and logical combinations.\n */\nexport type WhereDocument =\n | { $contains: string }\n | { $not_contains: string }\n | { $matches: string }\n | { $not_matches: string }\n | { $regex: string }\n | { $not_regex: string }\n | { $and: WhereDocument[] }\n | { $or: WhereDocument[] };\n\n/**\n * Enum specifying which fields to include in query results.\n */\nexport enum IncludeEnum {\n /** Include similarity distances in results */\n distances = \"distances\",\n /** Include document text content in results */\n documents = \"documents\",\n /** Include embedding vectors in results */\n embeddings = \"embeddings\",\n /** Include metadata objects in results */\n metadatas = \"metadatas\",\n /** Include URIs in results */\n uris = \"uris\",\n}\n\n/**\n * Result class for get operations, containing retrieved records.\n * @template TMeta - The type of metadata associated with records\n */\nexport class GetResult<TMeta extends Metadata = Metadata> {\n public readonly documents: (string | null)[];\n public readonly embeddings: number[][];\n public readonly ids: string[];\n public readonly include: Include[];\n public readonly metadatas: (TMeta | null)[];\n public readonly uris: (string | null)[];\n\n /**\n * Creates a new GetResult instance.\n * @param data - The result data containing all fields\n */\n constructor({\n documents,\n embeddings,\n ids,\n include,\n metadatas,\n uris,\n }: {\n documents: (string | null)[];\n embeddings: number[][];\n ids: string[];\n include: Include[];\n metadatas: (TMeta | null)[];\n uris: (string | null)[];\n }) {\n this.documents = documents;\n this.embeddings = embeddings;\n this.ids = ids;\n this.include = include;\n this.metadatas = metadatas;\n this.uris = uris;\n }\n\n /**\n * Converts the result to a row-based format for easier iteration.\n * @returns Object containing include fields and array of record objects\n */\n public rows() {\n return this.ids.map((id, index) => {\n return {\n id,\n document: this.include.includes(\"documents\")\n ? this.documents[index]\n : undefined,\n embedding: this.include.includes(\"embeddings\")\n ? this.embeddings[index]\n : undefined,\n metadata: this.include.includes(\"metadatas\")\n ? this.metadatas[index]\n : undefined,\n uri: this.include.includes(\"uris\") ? this.uris[index] : undefined,\n };\n });\n }\n}\n\n/**\n * Interface for query results in row format.\n * @template TMeta - The type of metadata associated with records\n */\nexport interface QueryRowResult<TMeta extends Metadata = Metadata> {\n /** Similarity distance to the query (if included) */\n distance?: number | null;\n /** Document text content (if included) */\n document?: string | null;\n /** Embedding vector (if included) */\n embedding?: number[] | null;\n /** Unique record identifier */\n id: string;\n /** Record metadata (if included) */\n metadata?: TMeta | null;\n /** Record URI (if included) */\n uri?: string | null;\n}\n\n/**\n * Result class for query operations, containing search results.\n * @template TMeta - The type of metadata associated with records\n */\nexport class QueryResult<TMeta extends Metadata = Metadata> {\n public readonly distances: (number | null)[][];\n public readonly documents: (string | null)[][];\n public readonly embeddings: (number[] | null)[][];\n public readonly ids: string[][];\n public readonly include: Include[];\n public readonly metadatas: (TMeta | null)[][];\n public readonly uris: (string | null)[][];\n\n /**\n * Creates a new QueryResult instance.\n * @param data - The query result data containing all fields\n */\n constructor({\n distances,\n documents,\n embeddings,\n ids,\n include,\n metadatas,\n uris,\n }: {\n distances: (number | null)[][];\n documents: (string | null)[][];\n embeddings: (number[] | null)[][];\n ids: string[][];\n include: Include[];\n metadatas: (TMeta | null)[][];\n uris: (string | null)[][];\n }) {\n this.distances = distances;\n this.documents = documents;\n this.embeddings = embeddings;\n this.ids = ids;\n this.include = include;\n this.metadatas = metadatas;\n this.uris = uris;\n }\n\n /**\n * Converts the query result to a row-based format for easier iteration.\n * @returns Object containing include fields and structured query results\n */\n public rows(): QueryRowResult<TMeta>[][] {\n const queries: {\n distance?: number | null;\n document?: string | null;\n embedding?: number[] | null;\n id: string;\n metadata?: TMeta | null;\n uri?: string | null;\n }[][] = [];\n\n for (let q = 0; q < this.ids.length; q++) {\n const records = this.ids[q].map((id, index) => {\n return {\n id,\n document: this.include.includes(\"documents\")\n ? this.documents[q][index]\n : undefined,\n embedding: this.include.includes(\"embeddings\")\n ? this.embeddings[q][index]\n : undefined,\n metadata: this.include.includes(\"metadatas\")\n ? this.metadatas[q][index]\n : undefined,\n uri: this.include.includes(\"uris\") ? this.uris[q][index] : undefined,\n distance: this.include.includes(\"distances\")\n ? this.distances[q][index]\n : undefined,\n };\n });\n\n queries.push(records);\n }\n\n return queries;\n }\n}\n","export type AuthToken = string | undefined;\n\nexport interface Auth {\n /**\n * Which part of the request do we use to send the auth?\n *\n * @default 'header'\n */\n in?: 'header' | 'query' | 'cookie';\n /**\n * Header or query parameter name.\n *\n * @default 'Authorization'\n */\n name?: string;\n scheme?: 'basic' | 'bearer';\n type: 'apiKey' | 'http';\n}\n\nexport const getAuthToken = async (\n auth: Auth,\n callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,\n): Promise<string | undefined> => {\n const token =\n typeof callback === 'function' ? await callback(auth) : callback;\n\n if (!token) {\n return;\n }\n\n if (auth.scheme === 'bearer') {\n return `Bearer ${token}`;\n }\n\n if (auth.scheme === 'basic') {\n return `Basic ${btoa(token)}`;\n }\n\n return token;\n};\n","import type {\n ArrayStyle,\n ObjectStyle,\n SerializerOptions,\n} from './pathSerializer';\n\nexport type QuerySerializer = (query: Record<string, unknown>) => string;\n\nexport type BodySerializer = (body: any) => any;\n\nexport interface QuerySerializerOptions {\n allowReserved?: boolean;\n array?: SerializerOptions<ArrayStyle>;\n object?: SerializerOptions<ObjectStyle>;\n}\n\nconst serializeFormDataPair = (data: FormData, key: string, value: unknown) => {\n if (typeof value === 'string' || value instanceof Blob) {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nconst serializeUrlSearchParamsPair = (\n data: URLSearchParams,\n key: string,\n value: unknown,\n) => {\n if (typeof value === 'string') {\n data.append(key, value);\n } else {\n data.append(key, JSON.stringify(value));\n }\n};\n\nexport const formDataBodySerializer = {\n bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(\n body: T,\n ) => {\n const data = new FormData();\n\n Object.entries(body).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeFormDataPair(data, key, v));\n } else {\n serializeFormDataPair(data, key, value);\n }\n });\n\n return data;\n },\n};\n\nexport const jsonBodySerializer = {\n bodySerializer: <T>(body: T) =>\n JSON.stringify(body, (key, value) =>\n typeof value === 'bigint' ? value.toString() : value,\n ),\n};\n\nexport const urlSearchParamsBodySerializer = {\n bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(\n body: T,\n ) => {\n const data = new URLSearchParams();\n\n Object.entries(body).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));\n } else {\n serializeUrlSearchParamsPair(data, key, value);\n }\n });\n\n return data.toString();\n },\n};\n","interface SerializeOptions<T>\n extends SerializePrimitiveOptions,\n SerializerOptions<T> {}\n\ninterface SerializePrimitiveOptions {\n allowReserved?: boolean;\n name: string;\n}\n\nexport interface SerializerOptions<T> {\n /**\n * @default true\n */\n explode: boolean;\n style: T;\n}\n\nexport type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';\nexport type ArraySeparatorStyle = ArrayStyle | MatrixStyle;\ntype MatrixStyle = 'label' | 'matrix' | 'simple';\nexport type ObjectStyle = 'form' | 'deepObject';\ntype ObjectSeparatorStyle = ObjectStyle | MatrixStyle;\n\ninterface SerializePrimitiveParam extends SerializePrimitiveOptions {\n value: string;\n}\n\nexport const separatorArrayExplode = (style: ArraySeparatorStyle) => {\n switch (style) {\n case 'label':\n return '.';\n case 'matrix':\n return ';';\n case 'simple':\n return ',';\n default:\n return '&';\n }\n};\n\nexport const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {\n switch (style) {\n case 'form':\n return ',';\n case 'pipeDelimited':\n return '|';\n case 'spaceDelimited':\n return '%20';\n default:\n return ',';\n }\n};\n\nexport const separatorObjectExplode = (style: ObjectSeparatorStyle) => {\n switch (style) {\n case 'label':\n return '.';\n case 'matrix':\n return ';';\n case 'simple':\n return ',';\n default:\n return '&';\n }\n};\n\nexport const serializeArrayParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ArraySeparatorStyle> & {\n value: unknown[];\n}) => {\n if (!explode) {\n const joinedValues = (\n allowReserved ? value : value.map((v) => encodeURIComponent(v as string))\n ).join(separatorArrayNoExplode(style));\n switch (style) {\n case 'label':\n return `.${joinedValues}`;\n case 'matrix':\n return `;${name}=${joinedValues}`;\n case 'simple':\n return joinedValues;\n default:\n return `${name}=${joinedValues}`;\n }\n }\n\n const separator = separatorArrayExplode(style);\n const joinedValues = value\n .map((v) => {\n if (style === 'label' || style === 'simple') {\n return allowReserved ? v : encodeURIComponent(v as string);\n }\n\n return serializePrimitiveParam({\n allowReserved,\n name,\n value: v as string,\n });\n })\n .join(separator);\n return style === 'label' || style === 'matrix'\n ? separator + joinedValues\n : joinedValues;\n};\n\nexport const serializePrimitiveParam = ({\n allowReserved,\n name,\n value,\n}: SerializePrimitiveParam) => {\n if (value === undefined || value === null) {\n return '';\n }\n\n if (typeof value === 'object') {\n throw new Error(\n 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',\n );\n }\n\n return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;\n};\n\nexport const serializeObjectParam = ({\n allowReserved,\n explode,\n name,\n style,\n value,\n}: SerializeOptions<ObjectSeparatorStyle> & {\n value: Record<string, unknown> | Date;\n}) => {\n if (value instanceof Date) {\n return `${name}=${value.toISOString()}`;\n }\n\n if (style !== 'deepObject' && !explode) {\n let values: string[] = [];\n Object.entries(value).forEach(([key, v]) => {\n values = [\n ...values,\n key,\n allowReserved ? (v as string) : encodeURIComponent(v as string),\n ];\n });\n const joinedValues = values.join(',');\n switch (style) {\n case 'form':\n return `${name}=${joinedValues}`;\n case 'label':\n return `.${joinedValues}`;\n case 'matrix':\n return `;${name}=${joinedValues}`;\n default:\n return joinedValues;\n }\n }\n\n const separator = separatorObjectExplode(style);\n const joinedValues = Object.entries(value)\n .map(([key, v]) =>\n serializePrimitiveParam({\n allowReserved,\n name: style === 'deepObject' ? `${name}[${key}]` : key,\n value: v as string,\n }),\n )\n .join(separator);\n return style === 'label' || style === 'matrix'\n ? separator + joinedValues\n : joinedValues;\n};\n","import type {\n QuerySerializer,\n QuerySerializerOptions,\n} from '@hey-api/client-core';\nimport {\n getAuthToken,\n jsonBodySerializer,\n serializeArrayParam,\n serializeObjectParam,\n serializePrimitiveParam,\n} from '@hey-api/client-core';\n\nimport type { Client, ClientOptions, Config, RequestOptions } from './types';\n\ninterface PathSerializer {\n path: Record<string, unknown>;\n url: string;\n}\n\nconst PATH_PARAM_RE = /\\{[^{}]+\\}/g;\n\ntype ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';\ntype MatrixStyle = 'label' | 'matrix' | 'simple';\ntype ArraySeparatorStyle = ArrayStyle | MatrixStyle;\n\nconst defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {\n let url = _url;\n const matches = _url.match(PATH_PARAM_RE);\n if (matches) {\n for (const match of matches) {\n let explode = false;\n let name = match.substring(1, match.length - 1);\n let style: ArraySeparatorStyle = 'simple';\n\n if (name.endsWith('*')) {\n explode = true;\n name = name.substring(0, name.length - 1);\n }\n\n if (name.startsWith('.')) {\n name = name.substring(1);\n style = 'label';\n } else if (name.startsWith(';')) {\n name = name.substring(1);\n style = 'matrix';\n }\n\n const value = path[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n url = url.replace(\n match,\n serializeArrayParam({ explode, name, style, value }),\n );\n continue;\n }\n\n if (typeof value === 'object') {\n url = url.replace(\n match,\n serializeObjectParam({\n explode,\n name,\n style,\n value: value as Record<string, unknown>,\n }),\n );\n continue;\n }\n\n if (style === 'matrix') {\n url = url.replace(\n match,\n `;${serializePrimitiveParam({\n name,\n value: value as string,\n })}`,\n );\n continue;\n }\n\n const replaceValue = encodeURIComponent(\n style === 'label' ? `.${value as string}` : (value as string),\n );\n url = url.replace(match, replaceValue);\n }\n }\n return url;\n};\n\nexport const createQuerySerializer = <T = unknown>({\n allowReserved,\n array,\n object,\n}: QuerySerializerOptions = {}) => {\n const querySerializer = (queryParams: T) => {\n let search: string[] = [];\n if (queryParams && typeof queryParams === 'object') {\n for (const name in queryParams) {\n const value = queryParams[name];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n if (Array.isArray(value)) {\n search = [\n ...search,\n serializeArrayParam({\n allowReserved,\n explode: true,\n name,\n style: 'form',\n value,\n ...array,\n }),\n ];\n continue;\n }\n\n if (typeof value === 'object') {\n search = [\n ...search,\n serializeObjectParam({\n allowReserved,\n explode: true,\n name,\n style: 'deepObject',\n value: value as Record<string, unknown>,\n ...object,\n }),\n ];\n continue;\n }\n\n search = [\n ...search,\n serializePrimitiveParam({\n allowReserved,\n name,\n value: value as string,\n }),\n ];\n }\n }\n return search.join('&');\n };\n return querySerializer;\n};\n\n/**\n * Infers parseAs value from provided Content-Type header.\n */\nexport const getParseAs = (\n contentType: string | null,\n): Exclude<Config['parseAs'], 'auto'> => {\n if (!contentType) {\n // If no Content-Type header is provided, the best we can do is return the raw response body,\n // which is effectively the same as the 'stream' option.\n return 'stream';\n }\n\n const cleanContent = contentType.split(';')[0]?.trim();\n\n if (!cleanContent) {\n return;\n }\n\n if (\n cleanContent.startsWith('application/json') ||\n cleanContent.endsWith('+json')\n ) {\n return 'json';\n }\n\n if (cleanContent === 'multipart/form-data') {\n return 'formData';\n }\n\n if (\n ['application/', 'audio/', 'image/', 'video/'].some((type) =>\n cleanContent.startsWith(type),\n )\n ) {\n return 'blob';\n }\n\n if (cleanContent.startsWith('text/')) {\n return 'text';\n }\n};\n\nexport const setAuthParams = async ({\n security,\n ...options\n}: Pick<Required<RequestOptions>, 'security'> &\n Pick<RequestOptions, 'auth' | 'query'> & {\n headers: Headers;\n }) => {\n for (const auth of security) {\n const token = await getAuthToken(auth, options.auth);\n\n if (!token) {\n continue;\n }\n\n const name = auth.name ?? 'Authorization';\n\n switch (auth.in) {\n case 'query':\n if (!options.query) {\n options.query = {};\n }\n options.query[name] = token;\n break;\n case 'cookie':\n options.headers.append('Cookie', `${name}=${token}`);\n break;\n case 'header':\n default:\n options.headers.set(name, token);\n break;\n }\n\n return;\n }\n};\n\nexport const buildUrl: Client['buildUrl'] = (options) => {\n const url = getUrl({\n baseUrl: options.baseUrl as string,\n path: options.path,\n query: options.query,\n querySerializer:\n typeof options.querySerializer === 'function'\n ? options.querySerializer\n : createQuerySerializer(options.querySerializer),\n url: options.url,\n });\n return url;\n};\n\nexport const getUrl = ({\n baseUrl,\n path,\n query,\n querySerializer,\n url: _url,\n}: {\n baseUrl?: string;\n path?: Record<string, unknown>;\n query?: Record<string, unknown>;\n querySerializer: QuerySerializer;\n url: string;\n}) => {\n const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;\n let url = (baseUrl ?? '') + pathUrl;\n if (path) {\n url = defaultPathSerializer({ path, url });\n }\n let search = query ? querySerializer(query) : '';\n if (search.startsWith('?')) {\n search = search.substring(1);\n }\n if (search) {\n url += `?${search}`;\n }\n return url;\n};\n\nexport const mergeConfigs = (a: Config, b: Config): Config => {\n const config = { ...a, ...b };\n if (config.baseUrl?.endsWith('/')) {\n config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);\n }\n config.headers = mergeHeaders(a.headers, b.headers);\n return config;\n};\n\nexport const mergeHeaders = (\n ...headers: Array<Required<Config>['headers'] | undefined>\n): Headers => {\n const mergedHeaders = new Headers();\n for (const header of headers) {\n if (!header || typeof header !== 'object') {\n continue;\n }\n\n const iterator =\n header instanceof Headers ? header.entries() : Object.entries(header);\n\n for (const [key, value] of iterator) {\n if (value === null) {\n mergedHeaders.delete(key);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n mergedHeaders.append(key, v as string);\n }\n } else if (value !== undefined) {\n // assume object headers are meant to be JSON stringified, i.e. their\n // content value in OpenAPI specification is 'application/json'\n mergedHeaders.set(\n key,\n typeof value === 'object' ? JSON.stringify(value) : (value as string),\n );\n }\n }\n }\n return mergedHeaders;\n};\n\ntype ErrInterceptor<Err, Res, Req, Options> = (\n error: Err,\n response: Res,\n request: Req,\n options: Options,\n) => Err | Promise<Err>;\n\ntype ReqInterceptor<Req, Options> = (\n request: Req,\n options: Options,\n) => Req | Promise<Req>;\n\ntype ResInterceptor<Res, Req, Options> = (\n response: Res,\n request: Req,\n options: Options,\n) => Res | Promise<Res>;\n\nclass Interceptors<Interceptor> {\n _fns: Interceptor[];\n\n constructor() {\n this._fns = [];\n }\n\n clear() {\n this._fns = [];\n }\n\n exists(fn: Interceptor) {\n return this._fns.indexOf(fn) !== -1;\n }\n\n eject(fn: Interceptor) {\n const index = this._fns.indexOf(fn);\n if (index !== -1) {\n this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)];\n }\n }\n\n use(fn: Interceptor) {\n this._fns = [...this._fns, fn];\n }\n}\n\n// `createInterceptors()` response, meant for external use as it does not\n// expose internals\nexport interface Middleware<Req, Res, Err, Options> {\n error: Pick<\n Interceptors<ErrInterceptor<Err, Res, Req, Options>>,\n 'eject' | 'use'\n >;\n request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'>;\n response: Pick<\n Interceptors<ResInterceptor<Res, Req, Options>>,\n 'eject' | 'use'\n >;\n}\n\n// do not add `Middleware` as return type so we can use _fns internally\nexport const createInterceptors = <Req, Res, Err, Options>() => ({\n error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),\n request: new Interceptors<ReqInterceptor<Req, Options>>(),\n response: new Interceptors<ResInterceptor<Res, Req, Options>>(),\n});\n\nconst defaultQuerySerializer = createQuerySerializer({\n allowReserved: false,\n array: {\n explode: true,\n style: 'form',\n },\n object: {\n explode: true,\n style: 'deepObject',\n },\n});\n\nconst defaultHeaders = {\n 'Content-Type': 'application/json',\n};\n\nexport const createConfig = <T extends ClientOptions = ClientOptions>(\n override: Config<Omit<ClientOptions, keyof T> & T> = {},\n): Config<Omit<ClientOptions, keyof T> & T> => ({\n ...jsonBodySerializer,\n headers: defaultHeaders,\n parseAs: 'auto',\n querySerializer: defaultQuerySerializer,\n ...override,\n});\n","import type { Client, Config, RequestOptions } from './types';\nimport {\n buildUrl,\n createConfig,\n createInterceptors,\n getParseAs,\n mergeConfigs,\n mergeHeaders,\n setAuthParams,\n} from './utils';\n\ntype ReqInit = Omit<RequestInit, 'body' | 'headers'> & {\n body?: any;\n headers: ReturnType<typeof mergeHeaders>;\n};\n\nexport const createClient = (config: Config = {}): Client => {\n let _config = mergeConfigs(createConfig(), config);\n\n const getConfig = (): Config => ({ ..._config });\n\n const setConfig = (config: Config): Config => {\n _config = mergeConfigs(_config, config);\n return getConfig();\n };\n\n const interceptors = createInterceptors<\n Request,\n Response,\n unknown,\n RequestOptions\n >();\n\n // @ts-expect-error\n const request: Client['request'] = async (options) => {\n const opts = {\n ..._config,\n ...options,\n fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,\n headers: mergeHeaders(_config.headers, options.headers),\n };\n\n if (opts.security) {\n await setAuthParams({\n ...opts,\n security: opts.security,\n });\n }\n\n if (opts.body && opts.bodySerializer) {\n opts.body = opts.bodySerializer(opts.body);\n }\n\n // remove Content-Type header if body is empty to avoid sending invalid requests\n if (opts.body === undefined || opts.body === '') {\n opts.headers.delete('Content-Type');\n }\n\n const url = buildUrl(opts);\n const requestInit: ReqInit = {\n redirect: 'follow',\n ...opts,\n };\n\n let request = new Request(url, requestInit);\n\n for (const fn of interceptors.request._fns) {\n request = await fn(request, opts);\n }\n\n // fetch must be assigned here, otherwise it would throw the error:\n // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n const _fetch = opts.fetch!;\n let response = await _fetch(request);\n\n for (const fn of interceptors.response._fns) {\n response = await fn(response, request, opts);\n }\n\n const result = {\n request,\n response,\n };\n\n if (response.ok) {\n if (\n response.status === 204 ||\n response.headers.get('Content-Length') === '0'\n ) {\n return {\n data: {},\n ...result,\n };\n }\n\n const parseAs =\n (opts.parseAs === 'auto'\n ? getParseAs(response.headers.get('Content-Type'))\n : opts.parseAs) ?? 'json';\n\n if (parseAs === 'stream') {\n return {\n data: response.body,\n ...result,\n };\n }\n\n let data = await response[parseAs]();\n if (parseAs === 'json') {\n if (opts.responseValidator) {\n await opts.responseValidator(data);\n }\n\n if (opts.responseTransformer) {\n data = await opts.responseTransformer(data);\n }\n }\n\n return {\n data,\n ...result,\n };\n }\n\n let error = await response.text();\n\n try {\n error = JSON.parse(error);\n } catch {\n // noop\n }\n\n let finalError = error;\n\n for (const fn of interceptors.error._fns) {\n finalError = (await fn(error, response, request, opts)) as string;\n }\n\n finalError = finalError || ({} as string);\n\n if (opts.throwOnError) {\n throw finalError;\n }\n\n return {\n error: finalError,\n ...result,\n };\n };\n\n return {\n buildUrl,\n connect: (options) => request({ ...options, method: 'CONNECT' }),\n delete: (options) => request({ ...options, method: 'DELETE' }),\n get: (options) => request({ ...options, method: 'GET' }),\n getConfig,\n head: (options) => request({ ...options, method: 'HEAD' }),\n interceptors,\n options: (options) => request({ ...options, method: 'OPTIONS' }),\n patch: (options) => request({ ...options, method: 'PATCH' }),\n post: (options) => request({ ...options, method: 'POST' }),\n put: (options) => request({ ...options, method: 'PUT' }),\n request,\n setConfig,\n trace: (options) => request({ ...options, method: 'TRACE' }),\n };\n};\n","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from './types.gen';\nimport { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from '@hey-api/client-fetch';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions>({\n baseUrl: 'http://localhost:8000',\n throwOnError: true\n}));","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';\nimport type { GetUserIdentityData, GetUserIdentityResponse2, GetUserIdentityError, GetCollectionByCrnData, GetCollectionByCrnResponse, GetCollectionByCrnError, HealthcheckData, HealthcheckResponse, HealthcheckError, HeartbeatData, HeartbeatResponse2, HeartbeatError, PreFlightChecksData, PreFlightChecksResponse, PreFlightChecksError, ResetData, ResetResponse, ResetError, CreateTenantData, CreateTenantResponse2, CreateTenantError, GetTenantData, GetTenantResponse2, GetTenantError, UpdateTenantData, UpdateTenantResponse2, UpdateTenantError, ListDatabasesData, ListDatabasesResponse, ListDatabasesError, CreateDatabaseData, CreateDatabaseResponse2, CreateDatabaseError, DeleteDatabaseData, DeleteDatabaseResponse2, DeleteDatabaseError, GetDatabaseData, GetDatabaseResponse, GetDatabaseError, ListCollectionsData, ListCollectionsResponse, ListCollectionsError, CreateCollectionData, CreateCollectionResponse, CreateCollectionError, DeleteCollectionData, DeleteCollectionResponse, DeleteCollectionError, GetCollectionData, GetCollectionResponse, GetCollectionError, UpdateCollectionData, UpdateCollectionResponse2, UpdateCollectionError, CollectionAddData, CollectionAddResponse, CollectionCountData, CollectionCountResponse, CollectionCountError, CollectionDeleteData, CollectionDeleteResponse, CollectionDeleteError, ForkCollectionData, ForkCollectionResponse, ForkCollectionError, CollectionGetData, CollectionGetResponse, CollectionGetError, CollectionQueryData, CollectionQueryResponse, CollectionQueryError, CollectionSearchData, CollectionSearchResponse, CollectionSearchError, CreateTaskData, CreateTaskResponse2, CreateTaskError, RemoveTaskData, RemoveTaskResponse2, RemoveTaskError, CollectionUpdateData, CollectionUpdateResponse, CollectionUpsertData, CollectionUpsertResponse, CollectionUpsertError, CountCollectionsData, CountCollectionsResponse, CountCollectionsError, VersionData, VersionResponse } from './types.gen';\nimport { client as _heyApiClient } from './client.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\nexport class DefaultService {\n /**\n * Retrieves the current user's identity, tenant, and databases.\n */\n public static getUserIdentity<ThrowOnError extends boolean = true>(options?: Options<GetUserIdentityData, ThrowOnError>) {\n return (options?.client ?? _heyApiClient).get<GetUserIdentityResponse2, GetUserIdentityError, ThrowOnError>({\n url: '/api/v2/auth/identity',\n ...options\n });\n }\n \n /**\n * Retrieves a collection by Chroma Resource Name.\n */\n public static getCollectionByCrn<ThrowOnError extends boolean = true>(options: Options<GetCollectionByCrnData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<GetCollectionByCrnResponse, GetCollectionByCrnError, ThrowOnError>({\n url: '/api/v2/collections/{crn}',\n ...options\n });\n }\n \n /**\n * Health check endpoint that returns 200 if the server and executor are ready\n */\n public static healthcheck<ThrowOnError extends boolean = true>(options?: Options<HealthcheckData, ThrowOnError>) {\n return (options?.client ?? _heyApiClient).get<HealthcheckResponse, HealthcheckError, ThrowOnError>({\n url: '/api/v2/healthcheck',\n ...options\n });\n }\n \n /**\n * Heartbeat endpoint that returns a nanosecond timestamp of the current time.\n */\n public static heartbeat<ThrowOnError extends boolean = true>(options?: Options<HeartbeatData, ThrowOnError>) {\n return (options?.client ?? _heyApiClient).get<HeartbeatResponse2, HeartbeatError, ThrowOnError>({\n url: '/api/v2/heartbeat',\n ...options\n });\n }\n \n /**\n * Pre-flight checks endpoint reporting basic readiness info.\n */\n public static preFlightChecks<ThrowOnError extends boolean = true>(options?: Options<PreFlightChecksData, ThrowOnError>) {\n return (options?.client ?? _heyApiClient).get<PreFlightChecksResponse, PreFlightChecksError, ThrowOnError>({\n url: '/api/v2/pre-flight-checks',\n ...options\n });\n }\n \n /**\n * Reset endpoint allowing authorized users to reset the database.\n */\n public static reset<ThrowOnError extends boolean = true>(options?: Options<ResetData, ThrowOnError>) {\n return (options?.client ?? _heyApiClient).post<ResetResponse, ResetError, ThrowOnError>({\n url: '/api/v2/reset',\n ...options\n });\n }\n \n /**\n * Creates a new tenant.\n */\n public static createTenant<ThrowOnError extends boolean = true>(options: Options<CreateTenantData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CreateTenantResponse2, CreateTenantError, ThrowOnError>({\n url: '/api/v2/tenants',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Returns an existing tenant by name.\n */\n public static getTenant<ThrowOnError extends boolean = true>(options: Options<GetTenantData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<GetTenantResponse2, GetTenantError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant_name}',\n ...options\n });\n }\n \n /**\n * Updates an existing tenant by name.\n */\n public static updateTenant<ThrowOnError extends boolean = true>(options: Options<UpdateTenantData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).patch<UpdateTenantResponse2, UpdateTenantError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant_name}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Lists all databases for a given tenant.\n */\n public static listDatabases<ThrowOnError extends boolean = true>(options: Options<ListDatabasesData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<ListDatabasesResponse, ListDatabasesError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases',\n ...options\n });\n }\n \n /**\n * Creates a new database for a given tenant.\n */\n public static createDatabase<ThrowOnError extends boolean = true>(options: Options<CreateDatabaseData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CreateDatabaseResponse2, CreateDatabaseError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Deletes a specific database.\n */\n public static deleteDatabase<ThrowOnError extends boolean = true>(options: Options<DeleteDatabaseData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).delete<DeleteDatabaseResponse2, DeleteDatabaseError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}',\n ...options\n });\n }\n \n /**\n * Retrieves a specific database by name.\n */\n public static getDatabase<ThrowOnError extends boolean = true>(options: Options<GetDatabaseData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<GetDatabaseResponse, GetDatabaseError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}',\n ...options\n });\n }\n \n /**\n * Lists all collections in the specified database.\n */\n public static listCollections<ThrowOnError extends boolean = true>(options: Options<ListCollectionsData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<ListCollectionsResponse, ListCollectionsError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections',\n ...options\n });\n }\n \n /**\n * Creates a new collection under the specified database.\n */\n public static createCollection<ThrowOnError extends boolean = true>(options: Options<CreateCollectionData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CreateCollectionResponse, CreateCollectionError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Deletes a collection in a given database.\n */\n public static deleteCollection<ThrowOnError extends boolean = true>(options: Options<DeleteCollectionData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).delete<DeleteCollectionResponse, DeleteCollectionError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}',\n ...options\n });\n }\n \n /**\n * Retrieves a collection by ID or name.\n */\n public static getCollection<ThrowOnError extends boolean = true>(options: Options<GetCollectionData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<GetCollectionResponse, GetCollectionError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}',\n ...options\n });\n }\n \n /**\n * Updates an existing collection's name or metadata.\n */\n public static updateCollection<ThrowOnError extends boolean = true>(options: Options<UpdateCollectionData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).put<UpdateCollectionResponse2, UpdateCollectionError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Adds records to a collection.\n */\n public static collectionAdd<ThrowOnError extends boolean = true>(options: Options<CollectionAddData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CollectionAddResponse, unknown, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/add',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Retrieves the number of records in a collection.\n */\n public static collectionCount<ThrowOnError extends boolean = true>(options: Options<CollectionCountData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).get<CollectionCountResponse, CollectionCountError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/count',\n ...options\n });\n }\n \n /**\n * Deletes records in a collection. Can filter by IDs or metadata.\n */\n public static collectionDelete<ThrowOnError extends boolean = true>(options: Options<CollectionDeleteData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CollectionDeleteResponse, CollectionDeleteError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/delete',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Forks an existing collection.\n */\n public static forkCollection<ThrowOnError extends boolean = true>(options: Options<ForkCollectionData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<ForkCollectionResponse, ForkCollectionError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/fork',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Retrieves records from a collection by ID or metadata filter.\n */\n public static collectionGet<ThrowOnError extends boolean = true>(options: Options<CollectionGetData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CollectionGetResponse, CollectionGetError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/get',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Query a collection in a variety of ways, including vector search, metadata filtering, and full-text search\n */\n public static collectionQuery<ThrowOnError extends boolean = true>(options: Options<CollectionQueryData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CollectionQueryResponse, CollectionQueryError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/query',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Search records from a collection with hybrid criterias.\n */\n public static collectionSearch<ThrowOnError extends boolean = true>(options: Options<CollectionSearchData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CollectionSearchResponse, CollectionSearchError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/search',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Register a new task for a collection\n */\n public static createTask<ThrowOnError extends boolean = true>(options: Options<CreateTaskData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<CreateTaskResponse2, CreateTaskError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/tasks/create',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n }\n \n /**\n * Remove a task\n */\n public static removeTask<ThrowOnError extends boolean = true>(options: Options<RemoveTaskData, ThrowOnError>) {\n return (options.client ?? _heyApiClient).post<RemoveTaskResponse2, RemoveTaskError, ThrowOnError>({\n url: '/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/tasks/delete',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n