chromadb
Version:
A JavaScript interface for chroma
1,647 lines (1,636 loc) • 142 kB
JavaScript
import {
__publicField
} from "./chunk-NSSMTXJJ.mjs";
// src/deno.ts
if (typeof globalThis.Deno !== "undefined") {
const OriginalRequest = globalThis.Request;
const PatchedRequest = function(input, init) {
if (init && typeof init === "object") {
const cleanInit = { ...init };
if ("client" in cleanInit) {
delete cleanInit.client;
}
return new OriginalRequest(input, cleanInit);
}
return new OriginalRequest(input, init);
};
Object.setPrototypeOf(PatchedRequest, OriginalRequest);
Object.defineProperty(PatchedRequest, "prototype", {
value: OriginalRequest.prototype,
writable: false
});
globalThis.Request = PatchedRequest;
}
// src/types.ts
var baseRecordSetFields = [
"ids",
"embeddings",
"metadatas",
"documents",
"uris"
];
var recordSetFields = [...baseRecordSetFields, "ids"];
var IncludeEnum = /* @__PURE__ */ ((IncludeEnum2) => {
IncludeEnum2["distances"] = "distances";
IncludeEnum2["documents"] = "documents";
IncludeEnum2["embeddings"] = "embeddings";
IncludeEnum2["metadatas"] = "metadatas";
IncludeEnum2["uris"] = "uris";
return IncludeEnum2;
})(IncludeEnum || {});
var GetResult = class {
/**
* Creates a new GetResult instance.
* @param data - The result data containing all fields
*/
constructor({
documents,
embeddings,
ids,
include,
metadatas,
uris
}) {
this.documents = documents;
this.embeddings = embeddings;
this.ids = ids;
this.include = include;
this.metadatas = metadatas;
this.uris = uris;
}
/**
* Converts the result to a row-based format for easier iteration.
* @returns Object containing include fields and array of record objects
*/
rows() {
return this.ids.map((id, index) => {
return {
id,
document: this.include.includes("documents") ? this.documents[index] : void 0,
embedding: this.include.includes("embeddings") ? this.embeddings[index] : void 0,
metadata: this.include.includes("metadatas") ? this.metadatas[index] : void 0,
uri: this.include.includes("uris") ? this.uris[index] : void 0
};
});
}
};
var QueryResult = class {
/**
* Creates a new QueryResult instance.
* @param data - The query result data containing all fields
*/
constructor({
distances,
documents,
embeddings,
ids,
include,
metadatas,
uris
}) {
this.distances = distances;
this.documents = documents;
this.embeddings = embeddings;
this.ids = ids;
this.include = include;
this.metadatas = metadatas;
this.uris = uris;
}
/**
* Converts the query result to a row-based format for easier iteration.
* @returns Object containing include fields and structured query results
*/
rows() {
const queries = [];
for (let q2 = 0; q2 < this.ids.length; q2++) {
const records = this.ids[q2].map((id, index) => {
return {
id,
document: this.include.includes("documents") ? this.documents[q2][index] : void 0,
embedding: this.include.includes("embeddings") ? this.embeddings[q2][index] : void 0,
metadata: this.include.includes("metadatas") ? this.metadatas[q2][index] : void 0,
uri: this.include.includes("uris") ? this.uris[q2][index] : void 0,
distance: this.include.includes("distances") ? this.distances[q2][index] : void 0
};
});
queries.push(records);
}
return queries;
}
};
// ../../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/dist/index.js
var A = async (t, r) => {
let e = typeof r == "function" ? await r(t) : r;
if (e) return t.scheme === "bearer" ? `Bearer ${e}` : t.scheme === "basic" ? `Basic ${btoa(e)}` : e;
};
var R = { bodySerializer: (t) => JSON.stringify(t, (r, e) => typeof e == "bigint" ? e.toString() : e) };
var U = (t) => {
switch (t) {
case "label":
return ".";
case "matrix":
return ";";
case "simple":
return ",";
default:
return "&";
}
};
var _ = (t) => {
switch (t) {
case "form":
return ",";
case "pipeDelimited":
return "|";
case "spaceDelimited":
return "%20";
default:
return ",";
}
};
var D = (t) => {
switch (t) {
case "label":
return ".";
case "matrix":
return ";";
case "simple":
return ",";
default:
return "&";
}
};
var O = ({ allowReserved: t, explode: r, name: e, style: a, value: i }) => {
if (!r) {
let s = (t ? i : i.map((l) => encodeURIComponent(l))).join(_(a));
switch (a) {
case "label":
return `.${s}`;
case "matrix":
return `;${e}=${s}`;
case "simple":
return s;
default:
return `${e}=${s}`;
}
}
let o = U(a), n = i.map((s) => a === "label" || a === "simple" ? t ? s : encodeURIComponent(s) : y({ allowReserved: t, name: e, value: s })).join(o);
return a === "label" || a === "matrix" ? o + n : n;
};
var y = ({ allowReserved: t, name: r, value: e }) => {
if (e == null) return "";
if (typeof e == "object") throw new Error("Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these.");
return `${r}=${t ? e : encodeURIComponent(e)}`;
};
var q = ({ allowReserved: t, explode: r, name: e, style: a, value: i }) => {
if (i instanceof Date) return `${e}=${i.toISOString()}`;
if (a !== "deepObject" && !r) {
let s = [];
Object.entries(i).forEach(([f, u]) => {
s = [...s, f, t ? u : encodeURIComponent(u)];
});
let l = s.join(",");
switch (a) {
case "form":
return `${e}=${l}`;
case "label":
return `.${l}`;
case "matrix":
return `;${e}=${l}`;
default:
return l;
}
}
let o = D(a), n = Object.entries(i).map(([s, l]) => y({ allowReserved: t, name: a === "deepObject" ? `${e}[${s}]` : s, value: l })).join(o);
return a === "label" || a === "matrix" ? o + n : n;
};
var H = /\{[^{}]+\}/g;
var B = ({ path: t, url: r }) => {
let e = r, a = r.match(H);
if (a) for (let i of a) {
let o = false, n = i.substring(1, i.length - 1), s = "simple";
n.endsWith("*") && (o = true, n = n.substring(0, n.length - 1)), n.startsWith(".") ? (n = n.substring(1), s = "label") : n.startsWith(";") && (n = n.substring(1), s = "matrix");
let l = t[n];
if (l == null) continue;
if (Array.isArray(l)) {
e = e.replace(i, O({ explode: o, name: n, style: s, value: l }));
continue;
}
if (typeof l == "object") {
e = e.replace(i, q({ explode: o, name: n, style: s, value: l }));
continue;
}
if (s === "matrix") {
e = e.replace(i, `;${y({ name: n, value: l })}`);
continue;
}
let f = encodeURIComponent(s === "label" ? `.${l}` : l);
e = e.replace(i, f);
}
return e;
};
var E = ({ allowReserved: t, array: r, object: e } = {}) => (i) => {
let o = [];
if (i && typeof i == "object") for (let n in i) {
let s = i[n];
if (s != null) {
if (Array.isArray(s)) {
o = [...o, O({ allowReserved: t, explode: true, name: n, style: "form", value: s, ...r })];
continue;
}
if (typeof s == "object") {
o = [...o, q({ allowReserved: t, explode: true, name: n, style: "deepObject", value: s, ...e })];
continue;
}
o = [...o, y({ allowReserved: t, name: n, value: s })];
}
}
return o.join("&");
};
var P = (t) => {
if (!t) return "stream";
let r = t.split(";")[0]?.trim();
if (r) {
if (r.startsWith("application/json") || r.endsWith("+json")) return "json";
if (r === "multipart/form-data") return "formData";
if (["application/", "audio/", "image/", "video/"].some((e) => r.startsWith(e))) return "blob";
if (r.startsWith("text/")) return "text";
}
};
var I = async ({ security: t, ...r }) => {
for (let e of t) {
let a = await A(e, r.auth);
if (!a) continue;
let i = e.name ?? "Authorization";
switch (e.in) {
case "query":
r.query || (r.query = {}), r.query[i] = a;
break;
case "cookie":
r.headers.append("Cookie", `${i}=${a}`);
break;
case "header":
default:
r.headers.set(i, a);
break;
}
return;
}
};
var S = (t) => W({ baseUrl: t.baseUrl, path: t.path, query: t.query, querySerializer: typeof t.querySerializer == "function" ? t.querySerializer : E(t.querySerializer), url: t.url });
var W = ({ baseUrl: t, path: r, query: e, querySerializer: a, url: i }) => {
let o = i.startsWith("/") ? i : `/${i}`, n = (t ?? "") + o;
r && (n = B({ path: r, url: n }));
let s = e ? a(e) : "";
return s.startsWith("?") && (s = s.substring(1)), s && (n += `?${s}`), n;
};
var C = (t, r) => {
let e = { ...t, ...r };
return e.baseUrl?.endsWith("/") && (e.baseUrl = e.baseUrl.substring(0, e.baseUrl.length - 1)), e.headers = x(t.headers, r.headers), e;
};
var x = (...t) => {
let r = new Headers();
for (let e of t) {
if (!e || typeof e != "object") continue;
let a = e instanceof Headers ? e.entries() : Object.entries(e);
for (let [i, o] of a) if (o === null) r.delete(i);
else if (Array.isArray(o)) for (let n of o) r.append(i, n);
else o !== void 0 && r.set(i, typeof o == "object" ? JSON.stringify(o) : o);
}
return r;
};
var h = class {
constructor() {
__publicField(this, "_fns");
this._fns = [];
}
clear() {
this._fns = [];
}
exists(r) {
return this._fns.indexOf(r) !== -1;
}
eject(r) {
let e = this._fns.indexOf(r);
e !== -1 && (this._fns = [...this._fns.slice(0, e), ...this._fns.slice(e + 1)]);
}
use(r) {
this._fns = [...this._fns, r];
}
};
var T = () => ({ error: new h(), request: new h(), response: new h() });
var N = E({ allowReserved: false, array: { explode: true, style: "form" }, object: { explode: true, style: "deepObject" } });
var Q = { "Content-Type": "application/json" };
var w = (t = {}) => ({ ...R, headers: Q, parseAs: "auto", querySerializer: N, ...t });
var J = (t = {}) => {
let r = C(w(), t), e = () => ({ ...r }), a = (n) => (r = C(r, n), e()), i = T(), o = async (n) => {
let s = { ...r, ...n, fetch: n.fetch ?? r.fetch ?? globalThis.fetch, headers: x(r.headers, n.headers) };
s.security && await I({ ...s, security: s.security }), s.body && s.bodySerializer && (s.body = s.bodySerializer(s.body)), (s.body === void 0 || s.body === "") && s.headers.delete("Content-Type");
let l = S(s), f = { redirect: "follow", ...s }, u = new Request(l, f);
for (let p of i.request._fns) u = await p(u, s);
let k = s.fetch, c = await k(u);
for (let p of i.response._fns) c = await p(c, u, s);
let m = { request: u, response: c };
if (c.ok) {
if (c.status === 204 || c.headers.get("Content-Length") === "0") return { data: {}, ...m };
let p = (s.parseAs === "auto" ? P(c.headers.get("Content-Type")) : s.parseAs) ?? "json";
if (p === "stream") return { data: c.body, ...m };
let b = await c[p]();
return p === "json" && (s.responseValidator && await s.responseValidator(b), s.responseTransformer && (b = await s.responseTransformer(b))), { data: b, ...m };
}
let g = await c.text();
try {
g = JSON.parse(g);
} catch {
}
let d = g;
for (let p of i.error._fns) d = await p(g, c, u, s);
if (d = d || {}, s.throwOnError) throw d;
return { error: d, ...m };
};
return { buildUrl: S, connect: (n) => o({ ...n, method: "CONNECT" }), delete: (n) => o({ ...n, method: "DELETE" }), get: (n) => o({ ...n, method: "GET" }), getConfig: e, head: (n) => o({ ...n, method: "HEAD" }), interceptors: i, options: (n) => o({ ...n, method: "OPTIONS" }), patch: (n) => o({ ...n, method: "PATCH" }), post: (n) => o({ ...n, method: "POST" }), put: (n) => o({ ...n, method: "PUT" }), request: o, setConfig: a, trace: (n) => o({ ...n, method: "TRACE" }) };
};
// src/api/client.gen.ts
var client = J(w({
baseUrl: "http://localhost:8000",
throwOnError: true
}));
// src/api/sdk.gen.ts
var DefaultService = class {
/**
* Retrieves the current user's identity, tenant, and databases.
*/
static getUserIdentity(options) {
return (options?.client ?? client).get({
url: "/api/v2/auth/identity",
...options
});
}
/**
* Retrieves a collection by Chroma Resource Name.
*/
static getCollectionByCrn(options) {
return (options.client ?? client).get({
url: "/api/v2/collections/{crn}",
...options
});
}
/**
* Health check endpoint that returns 200 if the server and executor are ready
*/
static healthcheck(options) {
return (options?.client ?? client).get({
url: "/api/v2/healthcheck",
...options
});
}
/**
* Heartbeat endpoint that returns a nanosecond timestamp of the current time.
*/
static heartbeat(options) {
return (options?.client ?? client).get({
url: "/api/v2/heartbeat",
...options
});
}
/**
* Pre-flight checks endpoint reporting basic readiness info.
*/
static preFlightChecks(options) {
return (options?.client ?? client).get({
url: "/api/v2/pre-flight-checks",
...options
});
}
/**
* Reset endpoint allowing authorized users to reset the database.
*/
static reset(options) {
return (options?.client ?? client).post({
url: "/api/v2/reset",
...options
});
}
/**
* Creates a new tenant.
*/
static createTenant(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Returns an existing tenant by name.
*/
static getTenant(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant_name}",
...options
});
}
/**
* Updates an existing tenant by name.
*/
static updateTenant(options) {
return (options.client ?? client).patch({
url: "/api/v2/tenants/{tenant_name}",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Lists all databases for a given tenant.
*/
static listDatabases(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant}/databases",
...options
});
}
/**
* Creates a new database for a given tenant.
*/
static createDatabase(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Deletes a specific database.
*/
static deleteDatabase(options) {
return (options.client ?? client).delete({
url: "/api/v2/tenants/{tenant}/databases/{database}",
...options
});
}
/**
* Retrieves a specific database by name.
*/
static getDatabase(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant}/databases/{database}",
...options
});
}
/**
* Lists all collections in the specified database.
*/
static listCollections(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections",
...options
});
}
/**
* Creates a new collection under the specified database.
*/
static createCollection(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Deletes a collection in a given database.
*/
static deleteCollection(options) {
return (options.client ?? client).delete({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}",
...options
});
}
/**
* Retrieves a collection by ID or name.
*/
static getCollection(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}",
...options
});
}
/**
* Updates an existing collection's name or metadata.
*/
static updateCollection(options) {
return (options.client ?? client).put({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Adds records to a collection.
*/
static collectionAdd(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/add",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Retrieves the number of records in a collection.
*/
static collectionCount(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/count",
...options
});
}
/**
* Deletes records in a collection. Can filter by IDs or metadata.
*/
static collectionDelete(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/delete",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Forks an existing collection.
*/
static forkCollection(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/fork",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Retrieves records from a collection by ID or metadata filter.
*/
static collectionGet(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/get",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Query a collection in a variety of ways, including vector search, metadata filtering, and full-text search
*/
static collectionQuery(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/query",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Search records from a collection with hybrid criterias.
*/
static collectionSearch(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/search",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Register a new task for a collection
*/
static createTask(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/tasks/create",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Remove a task
*/
static removeTask(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/tasks/delete",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Updates records in a collection by ID.
*/
static collectionUpdate(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/update",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Upserts records in a collection (create if not exists, otherwise update).
*/
static collectionUpsert(options) {
return (options.client ?? client).post({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections/{collection_id}/upsert",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers
}
});
}
/**
* Retrieves the total number of collections in a given database.
*/
static countCollections(options) {
return (options.client ?? client).get({
url: "/api/v2/tenants/{tenant}/databases/{database}/collections_count",
...options
});
}
/**
* Returns the version of the server.
*/
static version(options) {
return (options?.client ?? client).get({
url: "/api/v2/version",
...options
});
}
};
// src/errors.ts
var ChromaError = class extends Error {
constructor(name, message, cause) {
super(message);
this.cause = cause;
this.name = name;
}
};
var ChromaConnectionError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaConnectionError";
}
};
var ChromaServerError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaServerError";
}
};
var ChromaClientError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaClientError";
}
};
var ChromaUnauthorizedError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaAuthError";
}
};
var ChromaForbiddenError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaForbiddenError";
}
};
var ChromaNotFoundError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaNotFoundError";
}
};
var ChromaValueError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaValueError";
}
};
var InvalidCollectionError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "InvalidCollectionError";
}
};
var InvalidArgumentError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "InvalidArgumentError";
}
};
var ChromaUniqueError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaUniqueError";
}
};
var ChromaQuotaExceededError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaQuotaExceededError";
}
};
var ChromaRateLimitError = class extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = "ChromaRateLimitError";
}
};
function createErrorByType(type, message) {
switch (type) {
case "InvalidCollection":
return new InvalidCollectionError(message);
case "InvalidArgumentError":
return new InvalidArgumentError(message);
default:
return void 0;
}
}
// src/utils.ts
var DEFAULT_TENANT = "default_tenant";
var DEFAULT_DATABASE = "default_database";
var defaultAdminClientArgs = {
host: "localhost",
port: 8e3,
ssl: false
};
var defaultChromaClientArgs = {
...defaultAdminClientArgs,
tenant: DEFAULT_TENANT,
database: DEFAULT_DATABASE
};
var normalizeMethod = (method) => {
if (method) {
switch (method.toUpperCase()) {
case "GET":
return "GET";
case "POST":
return "POST";
case "PUT":
return "PUT";
case "DELETE":
return "DELETE";
case "HEAD":
return "HEAD";
case "CONNECT":
return "CONNECT";
case "OPTIONS":
return "OPTIONS";
case "PATCH":
return "PATCH";
case "TRACE":
return "TRACE";
default:
return void 0;
}
}
return void 0;
};
var validateRecordSetLengthConsistency = (recordSet) => {
const lengths = Object.entries(recordSet).filter(
([field, value]) => recordSetFields.includes(field) && value !== void 0
).map(([field, value]) => [field, value.length]);
if (lengths.length === 0) {
throw new ChromaValueError(
`At least one of ${recordSetFields.join(", ")} must be provided`
);
}
const zeroLength = lengths.filter(([_2, length]) => length === 0).map(([field, _2]) => field);
if (zeroLength.length > 0) {
throw new ChromaValueError(
`Non-empty lists are required for ${zeroLength.join(", ")}`
);
}
if (new Set(lengths.map(([_2, length]) => length)).size > 1) {
throw new ChromaValueError(
`Unequal lengths for fields ${lengths.map(([field, _2]) => field).join(", ")}`
);
}
};
var validateEmbeddings = ({
embeddings,
fieldName = "embeddings"
}) => {
if (!Array.isArray(embeddings)) {
throw new ChromaValueError(
`Expected '${fieldName}' to be an array, but got ${typeof embeddings}`
);
}
if (embeddings.length === 0) {
throw new ChromaValueError(
"Expected embeddings to be an array with at least one item"
);
}
if (!embeddings.filter((e) => e.every((n) => typeof n === "number"))) {
throw new ChromaValueError(
"Expected each embedding to be an array of numbers"
);
}
embeddings.forEach((embedding, i) => {
if (embedding.length === 0) {
throw new ChromaValueError(
`Expected each embedding to be a non-empty array of numbers, but got an empty array at index ${i}`
);
}
});
};
var validateDocuments = ({
documents,
nullable = false,
fieldName = "documents"
}) => {
if (!Array.isArray(documents)) {
throw new ChromaValueError(
`Expected '${fieldName}' to be an array, but got ${typeof documents}`
);
}
if (documents.length === 0) {
throw new ChromaValueError(
`Expected '${fieldName}' to be a non-empty list`
);
}
documents.forEach((document) => {
if (!nullable && typeof document !== "string" && !document) {
throw new ChromaValueError(
`Expected each document to be a string, but got ${typeof document}`
);
}
});
};
var validateIDs = (ids) => {
if (!Array.isArray(ids)) {
throw new ChromaValueError(
`Expected 'ids' to be an array, but got ${typeof ids}`
);
}
if (ids.length === 0) {
throw new ChromaValueError("Expected 'ids' to be a non-empty list");
}
const nonStrings = ids.map((id, i) => [id, i]).filter(([id, _2]) => typeof id !== "string").map(([_2, i]) => i);
if (nonStrings.length > 0) {
throw new ChromaValueError(
`Found non-string IDs at ${nonStrings.join(", ")}`
);
}
const seen = /* @__PURE__ */ new Set();
const duplicates = ids.filter((id) => {
if (seen.has(id)) {
return id;
}
seen.add(id);
});
let message = "Expected IDs to be unique, but found duplicates of";
if (duplicates.length > 0 && duplicates.length <= 5) {
throw new ChromaValueError(`${message} ${duplicates.join(", ")}`);
}
if (duplicates.length > 0) {
throw new ChromaValueError(
`${message} ${duplicates.slice(0, 5).join(", ")}, ..., ${duplicates.slice(duplicates.length - 5).join(", ")}`
);
}
};
var validateSparseVector = (v) => {
if (typeof v !== "object" || v === null) {
return false;
}
const candidate = v;
const indices = candidate.indices;
const values = candidate.values;
if (!Array.isArray(indices) || !Array.isArray(values)) {
return false;
}
return indices.every((e) => typeof e === "number") && values.every((e) => typeof e === "number");
};
var validateMetadata = (metadata) => {
if (!metadata) {
return;
}
if (Object.keys(metadata).length === 0) {
throw new ChromaValueError("Expected metadata to be non-empty");
}
if (!Object.values(metadata).every(
(v) => v === null || v === void 0 || typeof v === "string" || typeof v === "number" || typeof v === "boolean" || validateSparseVector(v)
)) {
throw new ChromaValueError(
"Expected metadata to be a string, number, boolean, SparseVector, or nullable"
);
}
};
var SPARSE_VECTOR_TYPE = "sparse_vector";
var toSerializedSparseVector = (vector) => ({
"#type": SPARSE_VECTOR_TYPE,
indices: vector.indices,
values: vector.values
});
var serializeMetadata = (metadata) => {
if (metadata === void 0) {
return void 0;
}
if (metadata === null) {
return null;
}
const result = {};
Object.entries(metadata).forEach(([key, value]) => {
if (validateSparseVector(value)) {
result[key] = toSerializedSparseVector(value);
} else {
result[key] = value ?? null;
}
});
return result;
};
var serializeMetadatas = (metadatas) => {
if (metadatas === void 0) {
return void 0;
}
if (metadatas === null) {
return null;
}
return metadatas.map((metadata) => serializeMetadata(metadata) ?? null);
};
var isSerializedSparseVector = (value) => {
if (typeof value !== "object" || value === null) {
return false;
}
const candidate = value;
if (candidate["#type"] !== SPARSE_VECTOR_TYPE) {
return false;
}
return validateSparseVector(candidate);
};
var deserializeMetadataValue = (value) => {
if (isSerializedSparseVector(value)) {
return {
indices: value.indices,
values: value.values
};
}
return value;
};
var deserializeMetadata = (metadata) => {
if (metadata === void 0) {
return void 0;
}
if (metadata === null) {
return null;
}
const result = {};
Object.entries(metadata).forEach(([key, value]) => {
result[key] = deserializeMetadataValue(value);
});
return result;
};
var deserializeMetadatas = (metadatas) => {
if (metadatas === void 0) {
return void 0;
}
if (metadatas === null) {
return null;
}
return metadatas.map((metadata) => deserializeMetadata(metadata) ?? null);
};
var deserializeMetadataMatrix = (metadatas) => {
if (metadatas === void 0) {
return void 0;
}
if (metadatas === null) {
return null;
}
return metadatas.map((metadataArray) => {
if (metadataArray === null) {
return null;
}
const deserialized = deserializeMetadatas(metadataArray);
return deserialized ?? [];
});
};
var validateMetadatas = (metadatas) => {
if (!Array.isArray(metadatas)) {
throw new ChromaValueError(
`Expected metadatas to be an array, but got ${typeof metadatas}`
);
}
metadatas.forEach((metadata) => validateMetadata(metadata));
};
var validateBaseRecordSet = ({
recordSet,
update = false,
embeddingsField = "embeddings",
documentsField = "documents"
}) => {
if (!recordSet.embeddings && !recordSet.documents && !update) {
throw new ChromaValueError(
`At least one of '${embeddingsField}' and '${documentsField}' must be provided`
);
}
if (recordSet.embeddings) {
validateEmbeddings({
embeddings: recordSet.embeddings,
fieldName: embeddingsField
});
}
if (recordSet.documents) {
validateDocuments({
documents: recordSet.documents,
fieldName: documentsField
});
}
if (recordSet.metadatas) {
validateMetadatas(recordSet.metadatas);
}
};
var validateMaxBatchSize = (recordSetLength, maxBatchSize) => {
if (recordSetLength > maxBatchSize) {
throw new ChromaValueError(
`Record set length ${recordSetLength} exceeds max batch size ${maxBatchSize}`
);
}
};
var validateWhere = (where) => {
if (typeof where !== "object") {
throw new ChromaValueError("Expected where to be a non-empty object");
}
if (Object.keys(where).length != 1) {
throw new ChromaValueError(
`Expected 'where' to have exactly one operator, but got ${Object.keys(where).length}`
);
}
Object.entries(where).forEach(([key, value]) => {
if (key !== "$and" && key !== "$or" && key !== "$in" && key !== "$nin" && !["string", "number", "boolean", "object"].includes(typeof value)) {
throw new ChromaValueError(
`Expected 'where' value to be a string, number, boolean, or an operator expression, but got ${value}`
);
}
if (key === "$and" || key === "$or") {
if (Object.keys(value).length <= 1) {
throw new ChromaValueError(
`Expected 'where' value for $and or $or to be a list of 'where' expressions, but got ${value}`
);
}
value.forEach((w2) => validateWhere(w2));
return;
}
if (typeof value === "object") {
if (Object.keys(value).length != 1) {
throw new ChromaValueError(
`Expected operator expression to have one operator, but got ${value}`
);
}
const [operator, operand] = Object.entries(value)[0];
if (["$gt", "$gte", "$lt", "$lte"].includes(operator) && typeof operand !== "number") {
throw new ChromaValueError(
`Expected operand value to be a number for ${operator}, but got ${typeof operand}`
);
}
if (["$in", "$nin"].includes(operator) && !Array.isArray(operand)) {
throw new ChromaValueError(
`Expected operand value to be an array for ${operator}, but got ${operand}`
);
}
if (!["$gt", "$gte", "$lt", "$lte", "$ne", "$eq", "$in", "$nin"].includes(
operator
)) {
throw new ChromaValueError(
`Expected operator to be one of $gt, $gte, $lt, $lte, $ne, $eq, $in, $nin, but got ${operator}`
);
}
if (!["string", "number", "boolean"].includes(typeof operand) && !Array.isArray(operand)) {
throw new ChromaValueError(
"Expected operand value to be a string, number, boolean, or a list of those types"
);
}
if (Array.isArray(operand) && (operand.length === 0 || !operand.every((item) => typeof item === typeof operand[0]))) {
throw new ChromaValueError(
"Expected 'where' operand value to be a non-empty list and all values to be of the same type"
);
}
}
});
};
var validateWhereDocument = (whereDocument) => {
if (typeof whereDocument !== "object") {
throw new ChromaValueError(
"Expected 'whereDocument' to be a non-empty object"
);
}
if (Object.keys(whereDocument).length != 1) {
throw new ChromaValueError(
`Expected 'whereDocument' to have exactly one operator, but got ${whereDocument}`
);
}
const [operator, operand] = Object.entries(whereDocument)[0];
if (![
"$contains",
"$not_contains",
"$matches",
"$not_matches",
"$regex",
"$not_regex",
"$and",
"$or"
].includes(operator)) {
throw new ChromaValueError(
`Expected 'whereDocument' operator to be one of $contains, $not_contains, $matches, $not_matches, $regex, $not_regex, $and, or $or, but got ${operator}`
);
}
if (operator === "$and" || operator === "$or") {
if (!Array.isArray(operand)) {
throw new ChromaValueError(
`Expected operand for ${operator} to be a list of 'whereDocument' expressions, but got ${operand}`
);
}
if (operand.length <= 1) {
throw new ChromaValueError(
`Expected 'whereDocument' operand for ${operator} to be a list with at least two 'whereDocument' expressions`
);
}
operand.forEach((item) => validateWhereDocument(item));
}
if ((operand === "$contains" || operand === "$not_contains" || operand === "$regex" || operand === "$not_regex") && (typeof operator !== "string" || operator.length === 0)) {
throw new ChromaValueError(
`Expected operand for ${operator} to be a non empty string, but got ${operand}`
);
}
};
var validateInclude = ({
include,
exclude
}) => {
if (!Array.isArray(include)) {
throw new ChromaValueError("Expected 'include' to be a non-empty array");
}
const validValues = Object.keys(IncludeEnum);
include.forEach((item) => {
if (typeof item !== "string") {
throw new ChromaValueError("Expected 'include' items to be strings");
}
if (!validValues.includes(item)) {
throw new ChromaValueError(
`Expected 'include' items to be one of ${validValues.join(
", "
)}, but got ${item}`
);
}
if (exclude?.includes(item)) {
throw new ChromaValueError(`${item} is not allowed for this operation`);
}
});
};
var validateNResults = (nResults) => {
if (typeof nResults !== "number") {
throw new ChromaValueError(
`Expected 'nResults' to be a number, but got ${typeof nResults}`
);
}
if (nResults <= 0) {
throw new ChromaValueError("Number of requested results has to positive");
}
};
var parseConnectionPath = (path) => {
try {
const url = new URL(path);
const ssl = url.protocol === "https:";
const host = url.hostname;
const port = url.port;
return {
ssl,
host,
port: Number(port)
};
} catch {
throw new ChromaValueError(`Invalid URL: ${path}`);
}
};
var packEmbedding = (embedding) => {
const buffer = new ArrayBuffer(embedding.length * 4);
const view = new Float32Array(buffer);
for (let i = 0; i < embedding.length; i++) {
view[i] = embedding[i];
}
return buffer;
};
var embeddingsToBase64Bytes = (embeddings) => {
return embeddings.map((embedding) => {
const buffer = packEmbedding(embedding);
const uint8Array = new Uint8Array(buffer);
const binaryString = Array.from(
uint8Array,
(byte) => String.fromCharCode(byte)
).join("");
return btoa(binaryString);
});
};
// src/embedding-function.ts
var knownEmbeddingFunctions = /* @__PURE__ */ new Map();
var knownSparseEmbeddingFunctions = /* @__PURE__ */ new Map();
var registerEmbeddingFunction = (name, fn) => {
if (knownEmbeddingFunctions.has(name)) {
throw new ChromaValueError(
`Embedding function with name ${name} is already registered.`
);
}
knownEmbeddingFunctions.set(name, fn);
};
var registerSparseEmbeddingFunction = (name, fn) => {
if (knownSparseEmbeddingFunctions.has(name)) {
throw new ChromaValueError(
`Sparse embedding function with name ${name} is already registered.`
);
}
knownSparseEmbeddingFunctions.set(name, fn);
};
var getEmbeddingFunction = (collectionName, efConfig) => {
if (!efConfig) {
console.warn(
`No embedding function configuration found for collection ${collectionName}. 'add' and 'query' will fail unless you provide them embeddings directly.`
);
return void 0;
}
if (efConfig.type === "legacy") {
console.warn(
`No embedding function configuration found for collection ${collectionName}. 'add' and 'query' will fail unless you provide them embeddings directly.`
);
return void 0;
}
if (efConfig.type === "unknown") {
console.warn(
`Unknown embedding function configuration for collection ${collectionName}. 'add' and 'query' will fail unless you provide them embeddings directly.`
);
return void 0;
}
if (efConfig.type !== "known") {
return void 0;
}
const name = efConfig.name;
const embeddingFunction = knownEmbeddingFunctions.get(name);
if (!embeddingFunction) {
console.warn(
`Collection ${collectionName} was created with the ${embeddingFunction} embedding function. However, the @chroma-core/${embeddingFunction} package is not install. 'add' and 'query' will fail unless you provide them embeddings directly, or install the @chroma-core/${embeddingFunction} package.`
);
return void 0;
}
let constructorConfig = efConfig.type === "known" ? efConfig.config : {};
try {
if (embeddingFunction.buildFromConfig) {
return embeddingFunction.buildFromConfig(constructorConfig);
}
console.warn(
`Embedding function ${name} does not define a 'buildFromConfig' function. 'add' and 'query' will fail unless you provide them embeddings directly.`
);
return void 0;
} catch (e) {
console.warn(
`Embedding function ${name} failed to build with config: ${constructorConfig}. 'add' and 'query' will fail unless you provide them embeddings directly. Error: ${e}`
);
return void 0;
}
};
var getSparseEmbeddingFunction = (collectionName, efConfig) => {
if (!efConfig) {
return void 0;
}
if (efConfig.type === "legacy") {
return void 0;
}
if (efConfig.type === "unknown") {
console.warn(
`Unknown embedding function configuration for collection ${collectionName}. 'add' and 'query' will fail unless you provide them embeddings directly.`
);
return void 0;
}
if (efConfig.type !== "known") {
return void 0;
}
const name = efConfig.name;
const sparseEmbeddingFunction = knownSparseEmbeddingFunctions.get(name);
if (!sparseEmbeddingFunction) {
console.warn(
`Collection ${collectionName} was created with the ${name} sparse embedding function. However, the @chroma-core/${name} package is not installed.`
);
return void 0;
}
let constructorConfig = efConfig.type === "known" ? efConfig.config : {};
try {
if (sparseEmbeddingFunction.buildFromConfig) {
return sparseEmbeddingFunction.buildFromConfig(constructorConfig);
}
console.warn(
`Sparse embedding function ${name} does not define a 'buildFromConfig' function.`
);
return void 0;
} catch (e) {
console.warn(
`Sparse embedding function ${name} failed to build with config: ${constructorConfig}. Error: ${e}`
);
return void 0;
}
};
var serializeEmbeddingFunction = ({
embeddingFunction,
configEmbeddingFunction
}) => {
if (embeddingFunction && configEmbeddingFunction) {
throw new ChromaValueError(
"Embedding function provided when already defined in the collection configuration"
);
}
if (!embeddingFunction && !configEmbeddingFunction) {
return void 0;
}
const ef = embeddingFunction || configEmbeddingFunction;
if (!ef.getConfig || !ef.name || !ef.constructor.buildFromConfig) {
return { type: "legacy" };
}
if (ef.validateConfig) ef.validateConfig(ef.getConfig());
return {
name: ef.name,
type: "known",
config: ef.getConfig()
};
};
var getDefaultEFConfig = async () => {
try {
const { DefaultEmbeddingFunction } = await import("@chroma-core/default-embed");
if (!knownEmbeddingFunctions.has(new DefaultEmbeddingFunction().name)) {
registerEmbeddingFunction("default", DefaultEmbeddingFunction);
}
} catch (e) {
console.error(e);
throw new Error(
"Cannot instantiate a collection with the DefaultEmbeddingFunction. Please install @chroma-core/default-embed, or provide a different embedding function"
);
}
return {
name: "default",
type: "known",
config: {}
};
};
// src/collection-configuration.ts
var processCreateCollectionConfig = async ({
configuration,
embeddingFunction,
metadata
}) => {
if (configuration?.hnsw && configuration?.spann) {
throw new ChromaValueError(
"Cannot specify both HNSW and SPANN configurations"
);
}
let embeddingFunctionConfiguration = serializeEmbeddingFunction({
embeddingFunction: embeddingFunction ?? void 0,
configEmbeddingFunction: configuration?.embeddingFunction
});
if (!embeddingFunctionConfiguration && embeddingFunction !== null) {
embeddingFunctionConfiguration = await getDefaultEFConfig();
}
const overallEf = embeddingFunction || configuration?.embeddingFunction;
if (overallEf && overallEf.defaultSpace && overallEf.supportedSpaces) {
if (configuration?.hnsw === void 0 && configuration?.spann === void 0) {
if (metadata === void 0 || metadata?.["hnsw:space"] === void 0) {
if (!configuration) configuration = {};
configuration.hnsw = { space: overallEf.defaultSpace() };
}
}
if (configuration?.hnsw && !configuration.hnsw.space && overallEf.defaultSpace) {
configuration.hnsw.space = overallEf.defaultSpace();
}
if (configuration?.spann && !configuration.spann.space && overallEf.defaultSpace) {
configuration.spann.space = overallEf.defaultSpace();
}
if (overallEf.supportedSpaces) {
const supportedSpaces = overallEf.supportedSpaces();
if (configuration?.hnsw?.space && !supportedSpaces.includes(configuration.hnsw.space)) {
console.warn(
`Space '${configuration.hnsw.space}' is not supported by embedding function '${overallEf.name || "unknown"}'. Supported spaces: ${supportedSpaces.join(", ")}`
);
}
if (configuration?.spann?.space && !supportedSpaces.includes(configuration.spann.space)) {
console.warn(
`Space '${configuration.spann.space}' is not supported by embedding function '${overallEf.name || "unknown"}'. Supported spaces: ${supportedSpaces.join(", ")}`
);
}
if (!configuration?.hnsw && !configuration?.spann && metadata && typeof metadata["hnsw:space"] === "string" && !supportedSpaces.includes(metadata["hnsw:space"])) {
console.warn(
`Space '${metadata["hnsw:space"]}' from metadata is not supported by embedding function '${overallEf.name || "unknown"}'. Supported spaces: ${supportedSpaces.join(", ")}`
);
}
}
}
return {
...configuration || {},
embedding_function: embeddingFunctionConfiguration
};
};
var processUpdateCollectionConfig = async ({
collectionName,
currentConfiguration,
currentEmbeddingFunction,
newConfiguration
}) => {
if (newConfiguration.hnsw && typeof newConfiguration.hnsw !== "object") {
throw new ChromaValueError(
"Invalid HNSW config provided in UpdateCollectionConfiguration"
);
}
if (newConfiguration.spann && typeof newConfiguration.spann !== "object") {
throw new ChromaValueError(
"Invalid SPANN config provided in UpdateCollectionConfiguration"
);
}
const embeddingFunction = currentEmbeddingFunction || getEmbeddingFunction(
collectionName,
currentConfiguration.embeddingFunction ?? void 0
);
const newEmbeddingFunction = newConfiguration.embeddingFunction;
if (embeddingFunction && embeddingFunction.validateConfigUpdate && newEmbeddingFunction && newEmbeddingFunction.getConfig) {
embeddingFunction.validateConfigUpdate(newEmbeddingFunction.getConfig());
}
return {
updateConfiguration: {
hnsw: newConfiguration.hnsw,
spann: newConfiguration.spann,
embedding_function: newEmbeddingFunction && serializeEmbeddingFunction({ embeddingFunction: newEmbeddingFunction })
},
updateEmbeddingFunction: newEmbeddingFunction
};
};
// src/execution/expression/common.ts
var isPlainObject = (value) => {
if (typeof value !== "object" || value === null) {
return false;
}
if (Array.isArray(value)) {
return false;
}
const prototype = Object.getPrototypeOf(value);
return prototype === Object.prototype || prototype === null;
};
var deepClone = (value) => JSON.parse(JSON.stringify(value));
var iterableToArray = (values) => {
if (Array.isArray(values)) {
return values.slice();
}
return Array.from(values);
};
var assertNonEmptyArray = (values, message) => {
if (values.length === 0) {
throw new Error(message);
}
};
// src/execution/expression/where.ts
var WhereExpressionBase = class {
and(other) {
const target = WhereExpression.from(other);
if (!target) {
return this;
}
return AndWhere.combine(this, target);
}
or(other) {
const target = WhereExpression.from(other);
if (!target) {
return this;
}
return OrWhere.combine(this, target);
}
};
var WhereExpression = class _WhereExpression extends WhereExpressionBase {
static from(input) {
if (input instanceof _WhereExpression) {
return input;
}
if (input === null || input === void 0) {
return void 0;
}
if (!isPlainObject(input)) {
throw new TypeError("Where input must be a WhereExpression or plain object");
}
return parseWhereDict(input);
}
};
var AndWhere = class _AndWhere extends WhereExpression {
constructor(conditions) {
super();
this.conditions = conditions;
}
toJSON() {
return { $and: this.conditions.map((condition) => condition.toJSON()) };
}
get operands() {
return this.conditions.slice();
}
static combine(left, right) {
const flattened = [];
const add = (expr) => {
if (expr instanceof _AndWhere) {
flattened.push(...expr.operands);
} else {
flattened.push(expr);
}
};
add(left);
add(right);
if (flattened.length === 1) {
return flattened[0];
}
return new _AndWhere(flattened);
}
};
var OrWhere = class _OrWhere extends WhereExpression {
constructor(conditions) {
super();
this.conditions = conditions;
}
toJSON() {
return { $or: this.conditions.map((condition) => condition.toJSON()) };
}
get operands() {
return this.conditions.slice();
}
static combine(left, right) {
const flattened = [];
const add = (expr) => {
if (expr instanceof _OrWhere) {
flattened.push(...expr.operands);
} else {
flattened.push(expr);
}
};
add(left);
add(right);
if (flattened.length === 1) {
return flattened[0];
}
return new _OrWhere(flattened);
}
};
var ComparisonWhere = class extends WhereExpression {
constructor(key, operator, value) {
super();
this.key = key;
this.operator = operator;
this.value = value;
}
toJSON() {
return {
[this.key]: {
[this.operator]: this.value
}
};
}
};
var comparisonOperatorMap = /*