@vectororm/adapter-chroma 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # @vectororm/adapter-chroma
2
+
3
+ [![npm](https://img.shields.io/npm/v/@vectororm/adapter-chroma)](https://www.npmjs.com/package/@vectororm/adapter-chroma)
4
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+
6
+ [ChromaDB](https://www.trychroma.com/) adapter for [Glyph VectorORM](https://github.com/aviramroi/VectorORM).
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @vectororm/core @vectororm/adapter-chroma
12
+ ```
13
+
14
+ ## Prerequisites
15
+
16
+ ChromaDB running locally or accessible via network:
17
+
18
+ ```bash
19
+ docker run -p 8000:8000 chromadb/chroma
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Standalone Adapter
25
+
26
+ ```typescript
27
+ import { ChromaAdapter } from '@vectororm/adapter-chroma';
28
+
29
+ const adapter = new ChromaAdapter({
30
+ host: 'localhost',
31
+ port: 8000
32
+ });
33
+
34
+ await adapter.connect();
35
+
36
+ // Create a collection
37
+ await adapter.createCollection('my-docs', 1536, 'cosine');
38
+
39
+ // Upsert vectors
40
+ await adapter.upsert('my-docs', [
41
+ {
42
+ id: 'doc-1',
43
+ embedding: [0.1, 0.2, ...],
44
+ metadata: { title: 'My Document', __v_partition: 'finance' },
45
+ text: 'Document content...'
46
+ }
47
+ ]);
48
+
49
+ // Search with filters
50
+ const results = await adapter.search('my-docs', queryVector, {
51
+ topK: 10,
52
+ filter: { field: '__v_partition', op: 'eq', value: 'finance' }
53
+ });
54
+ ```
55
+
56
+ ### With RAGClient
57
+
58
+ ```typescript
59
+ import { RAGClient } from '@vectororm/core';
60
+ import { ChromaAdapter } from '@vectororm/adapter-chroma';
61
+
62
+ const client = new RAGClient({
63
+ adapter: new ChromaAdapter({ host: 'localhost', port: 8000 }),
64
+ embedder: myEmbedder,
65
+ llm: myLLM,
66
+ defaultCollection: 'docs'
67
+ });
68
+
69
+ await client.createCollection('docs');
70
+ await client.ingest(['documents/*.pdf'], 'docs');
71
+ const result = await client.retrieve('search query');
72
+ ```
73
+
74
+ ## Configuration
75
+
76
+ ```typescript
77
+ interface ChromaConfig {
78
+ host?: string; // Default: 'localhost'
79
+ port?: number; // Default: 8000
80
+ apiKey?: string; // Optional, for Chroma Cloud
81
+ ssl?: boolean; // Default: false for localhost
82
+ tenant?: string; // Optional multi-tenancy
83
+ database?: string; // Optional database name
84
+ }
85
+ ```
86
+
87
+ Environment variable fallbacks: `CHROMA_HOST`, `CHROMA_PORT`, `CHROMA_API_KEY`, `CHROMA_SSL`.
88
+
89
+ ## Features
90
+
91
+ - Full CRUD operations (upsert, fetch, delete)
92
+ - Metadata filtering with Glyph universal filter translation
93
+ - Collection management (create, delete, exists, stats)
94
+ - Batch iteration for enrichment pipelines
95
+ - Metadata updates without re-uploading vectors
96
+
97
+ ## Documentation
98
+
99
+ - [API Guide](https://github.com/aviramroi/VectorORM/blob/main/docs/guide.md)
100
+ - [Full Project](https://github.com/aviramroi/VectorORM)
101
+
102
+ ## License
103
+
104
+ Apache-2.0
package/dist/index.cjs ADDED
@@ -0,0 +1,423 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ChromaAdapter: () => ChromaAdapter
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/chroma-adapter.ts
28
+ var import_core = require("@vectororm/core");
29
+ var import_chromadb = require("chromadb");
30
+ var ChromaAdapter = class extends import_core.VectorDBAdapter {
31
+ config;
32
+ client = null;
33
+ collectionCache = /* @__PURE__ */ new Map();
34
+ constructor(config = {}) {
35
+ super();
36
+ this.config = config;
37
+ }
38
+ // ============================================================================
39
+ // CONNECTION MANAGEMENT
40
+ // ============================================================================
41
+ async connect() {
42
+ try {
43
+ const host = this.config.host || process.env.CHROMA_HOST || "localhost";
44
+ const port = this.config.port || (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8e3);
45
+ const ssl = this.config.ssl !== void 0 ? this.config.ssl : process.env.CHROMA_SSL === "true" || host !== "localhost";
46
+ const protocol = ssl ? "https" : "http";
47
+ const path = `${protocol}://${host}:${port}`;
48
+ const clientConfig = { path };
49
+ const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;
50
+ if (apiKey) {
51
+ clientConfig.auth = { provider: "token", credentials: apiKey };
52
+ }
53
+ if (this.config.tenant) {
54
+ clientConfig.tenant = this.config.tenant;
55
+ }
56
+ if (this.config.database) {
57
+ clientConfig.database = this.config.database;
58
+ }
59
+ this.client = new import_chromadb.ChromaClient(clientConfig);
60
+ await this.client.heartbeat();
61
+ } catch (error) {
62
+ throw new Error(
63
+ `Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,
64
+ { cause: error }
65
+ );
66
+ }
67
+ }
68
+ async disconnect() {
69
+ this.client = null;
70
+ this.collectionCache.clear();
71
+ }
72
+ async isConnected() {
73
+ if (!this.client) return false;
74
+ try {
75
+ await this.client.heartbeat();
76
+ return true;
77
+ } catch {
78
+ return false;
79
+ }
80
+ }
81
+ // ============================================================================
82
+ // COLLECTION MANAGEMENT
83
+ // ============================================================================
84
+ async createCollection(name, dimension, metric = "cosine") {
85
+ if (!this.client) {
86
+ throw new Error("Not connected. Call connect() first.");
87
+ }
88
+ try {
89
+ const chromaMetric = this.mapDistanceMetric(metric);
90
+ const collection = await this.client.createCollection({
91
+ name,
92
+ metadata: {
93
+ "hnsw:space": chromaMetric,
94
+ dimension: dimension.toString()
95
+ }
96
+ });
97
+ this.collectionCache.set(name, collection);
98
+ } catch (error) {
99
+ throw new Error(
100
+ `Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
101
+ { cause: error }
102
+ );
103
+ }
104
+ }
105
+ async deleteCollection(name) {
106
+ if (!this.client) {
107
+ throw new Error("Not connected. Call connect() first.");
108
+ }
109
+ try {
110
+ await this.client.deleteCollection({ name });
111
+ this.collectionCache.delete(name);
112
+ } catch (error) {
113
+ throw new Error(
114
+ `Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
115
+ { cause: error }
116
+ );
117
+ }
118
+ }
119
+ async collectionExists(name) {
120
+ if (!this.client) {
121
+ throw new Error("Not connected. Call connect() first.");
122
+ }
123
+ try {
124
+ const collections = await this.client.listCollections();
125
+ return collections.some((col) => col.name === name);
126
+ } catch (error) {
127
+ throw new Error(
128
+ `Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,
129
+ { cause: error }
130
+ );
131
+ }
132
+ }
133
+ async getCollectionStats(name) {
134
+ if (!this.client) {
135
+ throw new Error("Not connected. Call connect() first.");
136
+ }
137
+ try {
138
+ const collection = await this.getCollection(name);
139
+ const count = await collection.count();
140
+ const metadata = collection.metadata || {};
141
+ const dimension = metadata.dimension ? parseInt(metadata.dimension, 10) : 0;
142
+ const metricStr = metadata["hnsw:space"] || "cosine";
143
+ const metric = this.unmapDistanceMetric(metricStr);
144
+ return {
145
+ vectorCount: count,
146
+ dimension,
147
+ metric,
148
+ ...metadata
149
+ };
150
+ } catch (error) {
151
+ throw new Error(
152
+ `Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,
153
+ { cause: error }
154
+ );
155
+ }
156
+ }
157
+ // ============================================================================
158
+ // VECTOR OPERATIONS
159
+ // ============================================================================
160
+ async upsert(collection, records) {
161
+ if (!this.client) {
162
+ throw new Error("Not connected. Call connect() first.");
163
+ }
164
+ try {
165
+ const col = await this.getCollection(collection);
166
+ const ids = records.map((r) => r.id);
167
+ const embeddings = records.map((r) => r.embedding);
168
+ const metadatas = records.map((r) => r.metadata || {});
169
+ await col.upsert({
170
+ ids,
171
+ embeddings,
172
+ metadatas
173
+ });
174
+ } catch (error) {
175
+ throw new Error(
176
+ `Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
177
+ { cause: error }
178
+ );
179
+ }
180
+ }
181
+ async fetch(collection, ids) {
182
+ if (!this.client) {
183
+ throw new Error("Not connected. Call connect() first.");
184
+ }
185
+ try {
186
+ const col = await this.getCollection(collection);
187
+ const response = await col.get({
188
+ ids,
189
+ include: ["embeddings", "metadatas"]
190
+ });
191
+ const records = [];
192
+ if (response.ids && response.ids.length > 0) {
193
+ for (let i = 0; i < response.ids.length; i++) {
194
+ records.push({
195
+ id: response.ids[i],
196
+ embedding: response.embeddings?.[i] || [],
197
+ metadata: response.metadatas?.[i] || {}
198
+ });
199
+ }
200
+ }
201
+ return records;
202
+ } catch (error) {
203
+ throw new Error(
204
+ `Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
205
+ { cause: error }
206
+ );
207
+ }
208
+ }
209
+ async delete(collection, ids) {
210
+ if (!this.client) {
211
+ throw new Error("Not connected. Call connect() first.");
212
+ }
213
+ try {
214
+ const col = await this.getCollection(collection);
215
+ await col.delete({ ids });
216
+ } catch (error) {
217
+ throw new Error(
218
+ `Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
219
+ { cause: error }
220
+ );
221
+ }
222
+ }
223
+ // ============================================================================
224
+ // METADATA OPERATIONS
225
+ // ============================================================================
226
+ async updateMetadata(collection, updates) {
227
+ if (!this.client) {
228
+ throw new Error("Not connected. Call connect() first.");
229
+ }
230
+ try {
231
+ const col = await this.getCollection(collection);
232
+ for (const update of updates) {
233
+ await col.update({
234
+ ids: [update.id],
235
+ metadatas: [update.metadata]
236
+ });
237
+ }
238
+ } catch (error) {
239
+ throw new Error(
240
+ `Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
241
+ { cause: error }
242
+ );
243
+ }
244
+ }
245
+ // ============================================================================
246
+ // SEARCH OPERATIONS
247
+ // ============================================================================
248
+ async search(collection, queryVector, options) {
249
+ if (!this.client) {
250
+ throw new Error("Not connected. Call connect() first.");
251
+ }
252
+ try {
253
+ const col = await this.getCollection(collection);
254
+ const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
255
+ const include = ["distances"];
256
+ if (options?.includeMetadata !== false) {
257
+ include.push("metadatas");
258
+ }
259
+ if (options?.includeValues) {
260
+ include.push("embeddings");
261
+ }
262
+ const response = await col.query({
263
+ queryEmbeddings: [queryVector],
264
+ nResults: options?.topK || 10,
265
+ where: chromaFilter,
266
+ include
267
+ });
268
+ const records = [];
269
+ if (response.ids && response.ids[0]) {
270
+ const resultIds = response.ids[0];
271
+ const distances = response.distances?.[0] || [];
272
+ const embeddings = response.embeddings?.[0] || [];
273
+ const metadatas = response.metadatas?.[0] || [];
274
+ for (let i = 0; i < resultIds.length; i++) {
275
+ const record = {
276
+ id: resultIds[i],
277
+ embedding: options?.includeValues ? embeddings[i] || [] : [],
278
+ metadata: options?.includeMetadata !== false ? metadatas[i] || {} : {}
279
+ };
280
+ if (distances[i] !== void 0) {
281
+ record.score = 1 / (1 + distances[i]);
282
+ }
283
+ records.push(record);
284
+ }
285
+ }
286
+ return { records };
287
+ } catch (error) {
288
+ throw new Error(
289
+ `Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
290
+ { cause: error }
291
+ );
292
+ }
293
+ }
294
+ // ============================================================================
295
+ // FILTER TRANSLATION
296
+ // ============================================================================
297
+ translateFilter(filter) {
298
+ if ("and" in filter) {
299
+ const conditions = filter.and;
300
+ const translated = conditions.map((c) => this.translateFilter(c));
301
+ return { $and: translated };
302
+ }
303
+ if ("or" in filter) {
304
+ const conditions = filter.or;
305
+ const translated = conditions.map((c) => this.translateFilter(c));
306
+ return { $or: translated };
307
+ }
308
+ const { field, op, value } = filter;
309
+ const operatorMap = {
310
+ eq: "$eq",
311
+ ne: "$ne",
312
+ gt: "$gt",
313
+ gte: "$gte",
314
+ lt: "$lt",
315
+ lte: "$lte",
316
+ in: "$in",
317
+ nin: "$nin"
318
+ };
319
+ const chromaOp = operatorMap[op];
320
+ if (!chromaOp) {
321
+ throw new Error(
322
+ `Unsupported filter operator: ${op}`,
323
+ { cause: { filter } }
324
+ );
325
+ }
326
+ return {
327
+ [field]: {
328
+ [chromaOp]: value
329
+ }
330
+ };
331
+ }
332
+ // ============================================================================
333
+ // ITERATION
334
+ // ============================================================================
335
+ async *iterate(collection, options) {
336
+ if (!this.client) {
337
+ throw new Error("Not connected. Call connect() first.");
338
+ }
339
+ try {
340
+ const col = await this.getCollection(collection);
341
+ const batchSize = options?.batchSize || 100;
342
+ const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
343
+ let offset = 0;
344
+ let hasMore = true;
345
+ while (hasMore) {
346
+ const response = await col.get({
347
+ where: chromaFilter,
348
+ limit: batchSize,
349
+ offset,
350
+ include: ["embeddings", "metadatas"]
351
+ });
352
+ if (response.ids && response.ids.length > 0) {
353
+ const records = [];
354
+ for (let i = 0; i < response.ids.length; i++) {
355
+ records.push({
356
+ id: response.ids[i],
357
+ embedding: response.embeddings?.[i] || [],
358
+ metadata: response.metadatas?.[i] || {}
359
+ });
360
+ }
361
+ yield records;
362
+ hasMore = response.ids.length === batchSize;
363
+ offset += batchSize;
364
+ } else {
365
+ hasMore = false;
366
+ }
367
+ }
368
+ } catch (error) {
369
+ throw new Error(
370
+ `Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
371
+ { cause: error }
372
+ );
373
+ }
374
+ }
375
+ // ============================================================================
376
+ // CAPABILITY FLAGS
377
+ // ============================================================================
378
+ supportsMetadataUpdate() {
379
+ return true;
380
+ }
381
+ supportsFiltering() {
382
+ return true;
383
+ }
384
+ supportsBatchOperations() {
385
+ return true;
386
+ }
387
+ // ============================================================================
388
+ // HELPER METHODS
389
+ // ============================================================================
390
+ async getCollection(name) {
391
+ if (this.collectionCache.has(name)) {
392
+ return this.collectionCache.get(name);
393
+ }
394
+ if (!this.client) {
395
+ throw new Error("Not connected. Call connect() first.");
396
+ }
397
+ const collection = await this.client.getCollection({ name, embeddingFunction: void 0 });
398
+ this.collectionCache.set(name, collection);
399
+ return collection;
400
+ }
401
+ mapDistanceMetric(metric) {
402
+ const metricMap = {
403
+ cosine: "cosine",
404
+ euclidean: "l2",
405
+ dotProduct: "ip"
406
+ // Inner product
407
+ };
408
+ return metricMap[metric] || "cosine";
409
+ }
410
+ unmapDistanceMetric(chromaMetric) {
411
+ const metricMap = {
412
+ cosine: "cosine",
413
+ l2: "euclidean",
414
+ ip: "dotProduct"
415
+ };
416
+ return metricMap[chromaMetric] || "cosine";
417
+ }
418
+ };
419
+ // Annotate the CommonJS export names for ESM import in node:
420
+ 0 && (module.exports = {
421
+ ChromaAdapter
422
+ });
423
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/chroma-adapter.ts"],"sourcesContent":["// Chroma adapter exports\nexport { ChromaAdapter } from './chroma-adapter';\nexport type { ChromaConfig } from './types';\n","import {\n VectorDBAdapter,\n type VectorRecord,\n type SearchResult,\n type UniversalFilter,\n type CollectionStats,\n type MetadataUpdate,\n type DistanceMetric,\n} from '@vectororm/core';\nimport { ChromaClient, type Collection } from 'chromadb';\nimport type { ChromaConfig } from './types.js';\n\n/**\n * ChromaAdapter implements VectorDBAdapter for Chroma vector database.\n *\n * Supports both self-hosted and cloud Chroma instances.\n * Uses chromadb npm package for native TypeScript support.\n */\nexport class ChromaAdapter extends VectorDBAdapter {\n private config: ChromaConfig;\n private client: ChromaClient | null = null;\n private collectionCache: Map<string, Collection> = new Map();\n\n constructor(config: ChromaConfig = {}) {\n super();\n this.config = config;\n }\n\n // ============================================================================\n // CONNECTION MANAGEMENT\n // ============================================================================\n\n async connect(): Promise<void> {\n try {\n const host = this.config.host || process.env.CHROMA_HOST || 'localhost';\n const port = this.config.port ||\n (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8000);\n\n // Determine SSL usage\n const ssl = this.config.ssl !== undefined\n ? this.config.ssl\n : (process.env.CHROMA_SSL === 'true' || host !== 'localhost');\n\n const protocol = ssl ? 'https' : 'http';\n const path = `${protocol}://${host}:${port}`;\n\n const clientConfig: any = { path };\n\n // Add auth if API key is provided\n const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;\n if (apiKey) {\n clientConfig.auth = { provider: 'token', credentials: apiKey };\n }\n\n // Add tenant/database if provided\n if (this.config.tenant) {\n clientConfig.tenant = this.config.tenant;\n }\n if (this.config.database) {\n clientConfig.database = this.config.database;\n }\n\n this.client = new ChromaClient(clientConfig);\n\n // Verify connection by getting heartbeat\n await this.client.heartbeat();\n } catch (error) {\n throw new Error(\n `Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n this.collectionCache.clear();\n }\n\n async isConnected(): Promise<boolean> {\n if (!this.client) return false;\n\n try {\n await this.client.heartbeat();\n return true;\n } catch {\n return false;\n }\n }\n\n // ============================================================================\n // COLLECTION MANAGEMENT\n // ============================================================================\n\n async createCollection(\n name: string,\n dimension: number,\n metric: DistanceMetric = 'cosine'\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n // Map our metric to Chroma distance function\n const chromaMetric = this.mapDistanceMetric(metric);\n\n const collection = await this.client.createCollection({\n name,\n metadata: {\n 'hnsw:space': chromaMetric,\n dimension: dimension.toString(),\n },\n });\n\n this.collectionCache.set(name, collection);\n } catch (error) {\n throw new Error(\n `Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async deleteCollection(name: string): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n await this.client.deleteCollection({ name });\n this.collectionCache.delete(name);\n } catch (error) {\n throw new Error(\n `Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async collectionExists(name: string): Promise<boolean> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collections = await this.client.listCollections();\n return collections.some((col: any) => col.name === name);\n } catch (error) {\n throw new Error(\n `Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async getCollectionStats(name: string): Promise<CollectionStats> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collection = await this.getCollection(name);\n const count = await collection.count();\n\n // Get metadata from collection\n const metadata = (collection as any).metadata || {};\n const dimension = metadata.dimension\n ? parseInt(metadata.dimension, 10)\n : 0;\n\n const metricStr = metadata['hnsw:space'] || 'cosine';\n const metric = this.unmapDistanceMetric(metricStr);\n\n return {\n vectorCount: count,\n dimension,\n metric,\n ...metadata,\n };\n } catch (error) {\n throw new Error(\n `Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // VECTOR OPERATIONS\n // ============================================================================\n\n async upsert(collection: string, records: VectorRecord[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const ids = records.map((r) => r.id);\n const embeddings = records.map((r) => r.embedding);\n const metadatas = records.map((r) => r.metadata || {});\n\n await col.upsert({\n ids,\n embeddings,\n metadatas,\n });\n } catch (error) {\n throw new Error(\n `Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async fetch(collection: string, ids: string[]): Promise<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const response = await col.get({\n ids,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids.length > 0) {\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n }\n\n return records;\n } catch (error) {\n throw new Error(\n `Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async delete(collection: string, ids: string[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n await col.delete({ ids });\n } catch (error) {\n throw new Error(\n `Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // METADATA OPERATIONS\n // ============================================================================\n\n async updateMetadata(\n collection: string,\n updates: MetadataUpdate[]\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n // Chroma supports metadata updates via update method\n for (const update of updates) {\n await col.update({\n ids: [update.id],\n metadatas: [update.metadata],\n });\n }\n } catch (error) {\n throw new Error(\n `Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // SEARCH OPERATIONS\n // ============================================================================\n\n async search(\n collection: string,\n queryVector: number[],\n options?: {\n topK?: number;\n filter?: UniversalFilter;\n includeMetadata?: boolean;\n includeValues?: boolean;\n }\n ): Promise<SearchResult> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n const include: any[] = ['distances' as any];\n if (options?.includeMetadata !== false) {\n include.push('metadatas' as any);\n }\n if (options?.includeValues) {\n include.push('embeddings' as any);\n }\n\n const response = await col.query({\n queryEmbeddings: [queryVector],\n nResults: options?.topK || 10,\n where: chromaFilter,\n include,\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids[0]) {\n const resultIds = response.ids[0];\n const distances = response.distances?.[0] || [];\n const embeddings = response.embeddings?.[0] || [];\n const metadatas = response.metadatas?.[0] || [];\n\n for (let i = 0; i < resultIds.length; i++) {\n const record: VectorRecord = {\n id: resultIds[i],\n embedding: options?.includeValues ? (embeddings[i] || []) : [],\n metadata: options?.includeMetadata !== false ? (metadatas[i] || {}) : {},\n };\n\n // Convert distance to score (inverse relationship)\n if (distances[i] !== undefined) {\n record.score = 1 / (1 + distances[i]);\n }\n\n records.push(record);\n }\n }\n\n return { records };\n } catch (error) {\n throw new Error(\n `Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // FILTER TRANSLATION\n // ============================================================================\n\n translateFilter(filter: UniversalFilter): any {\n // Handle compound AND filter\n if ('and' in filter) {\n const conditions = filter.and;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $and: translated };\n }\n\n // Handle compound OR filter\n if ('or' in filter) {\n const conditions = filter.or;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $or: translated };\n }\n\n // Handle basic filter condition\n const { field, op, value } = filter as any;\n\n // Operator mapping to Chroma's MongoDB-like syntax\n const operatorMap: Record<string, string> = {\n eq: '$eq',\n ne: '$ne',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n in: '$in',\n nin: '$nin',\n };\n\n const chromaOp = operatorMap[op];\n if (!chromaOp) {\n throw new Error(\n `Unsupported filter operator: ${op}`,\n { cause: { filter } }\n );\n }\n\n return {\n [field]: {\n [chromaOp]: value,\n },\n };\n }\n\n // ============================================================================\n // ITERATION\n // ============================================================================\n\n async *iterate(\n collection: string,\n options?: {\n batchSize?: number;\n filter?: UniversalFilter;\n }\n ): AsyncIterableIterator<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n const batchSize = options?.batchSize || 100;\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n // Chroma uses offset/limit pagination\n let offset = 0;\n let hasMore = true;\n\n while (hasMore) {\n const response = await col.get({\n where: chromaFilter,\n limit: batchSize,\n offset,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n if (response.ids && response.ids.length > 0) {\n const records: VectorRecord[] = [];\n\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n\n yield records;\n\n // Check if there are more results\n hasMore = response.ids.length === batchSize;\n offset += batchSize;\n } else {\n hasMore = false;\n }\n }\n } catch (error) {\n throw new Error(\n `Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // CAPABILITY FLAGS\n // ============================================================================\n\n supportsMetadataUpdate(): boolean {\n return true; // Chroma supports metadata updates\n }\n\n supportsFiltering(): boolean {\n return true; // Chroma supports metadata filtering\n }\n\n supportsBatchOperations(): boolean {\n return true; // Chroma supports batch operations\n }\n\n // ============================================================================\n // HELPER METHODS\n // ============================================================================\n\n private async getCollection(name: string): Promise<Collection> {\n if (this.collectionCache.has(name)) {\n return this.collectionCache.get(name)!;\n }\n\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n const collection = await this.client.getCollection({ name, embeddingFunction: undefined as any });\n this.collectionCache.set(name, collection);\n return collection;\n }\n\n private mapDistanceMetric(metric: DistanceMetric): string {\n const metricMap: Record<DistanceMetric, string> = {\n cosine: 'cosine',\n euclidean: 'l2',\n dotProduct: 'ip', // Inner product\n };\n\n return metricMap[metric] || 'cosine';\n }\n\n private unmapDistanceMetric(chromaMetric: string): DistanceMetric {\n const metricMap: Record<string, DistanceMetric> = {\n cosine: 'cosine',\n l2: 'euclidean',\n ip: 'dotProduct',\n };\n\n return metricMap[chromaMetric] || 'cosine';\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,84 @@
1
+ import { VectorDBAdapter, DistanceMetric, CollectionStats, VectorRecord, MetadataUpdate, UniversalFilter, SearchResult } from '@vectororm/core';
2
+
3
+ /**
4
+ * Configuration for ChromaAdapter.
5
+ *
6
+ * Supports hybrid config: explicit values or environment variables.
7
+ * Chroma can be self-hosted or used via cloud service.
8
+ */
9
+ interface ChromaConfig {
10
+ /**
11
+ * Chroma API key (optional for self-hosted).
12
+ * Falls back to CHROMA_API_KEY environment variable.
13
+ */
14
+ apiKey?: string;
15
+ /**
16
+ * Chroma server host.
17
+ * Falls back to CHROMA_HOST environment variable.
18
+ * Defaults to 'localhost'.
19
+ */
20
+ host?: string;
21
+ /**
22
+ * Chroma server port.
23
+ * Falls back to CHROMA_PORT environment variable.
24
+ * Defaults to 8000.
25
+ */
26
+ port?: number;
27
+ /**
28
+ * Use SSL/TLS for connection.
29
+ * Falls back to CHROMA_SSL environment variable.
30
+ * Defaults to false for localhost, true for remote hosts.
31
+ */
32
+ ssl?: boolean;
33
+ /**
34
+ * Optional tenant ID for multi-tenancy support.
35
+ */
36
+ tenant?: string;
37
+ /**
38
+ * Optional database name.
39
+ */
40
+ database?: string;
41
+ }
42
+
43
+ /**
44
+ * ChromaAdapter implements VectorDBAdapter for Chroma vector database.
45
+ *
46
+ * Supports both self-hosted and cloud Chroma instances.
47
+ * Uses chromadb npm package for native TypeScript support.
48
+ */
49
+ declare class ChromaAdapter extends VectorDBAdapter {
50
+ private config;
51
+ private client;
52
+ private collectionCache;
53
+ constructor(config?: ChromaConfig);
54
+ connect(): Promise<void>;
55
+ disconnect(): Promise<void>;
56
+ isConnected(): Promise<boolean>;
57
+ createCollection(name: string, dimension: number, metric?: DistanceMetric): Promise<void>;
58
+ deleteCollection(name: string): Promise<void>;
59
+ collectionExists(name: string): Promise<boolean>;
60
+ getCollectionStats(name: string): Promise<CollectionStats>;
61
+ upsert(collection: string, records: VectorRecord[]): Promise<void>;
62
+ fetch(collection: string, ids: string[]): Promise<VectorRecord[]>;
63
+ delete(collection: string, ids: string[]): Promise<void>;
64
+ updateMetadata(collection: string, updates: MetadataUpdate[]): Promise<void>;
65
+ search(collection: string, queryVector: number[], options?: {
66
+ topK?: number;
67
+ filter?: UniversalFilter;
68
+ includeMetadata?: boolean;
69
+ includeValues?: boolean;
70
+ }): Promise<SearchResult>;
71
+ translateFilter(filter: UniversalFilter): any;
72
+ iterate(collection: string, options?: {
73
+ batchSize?: number;
74
+ filter?: UniversalFilter;
75
+ }): AsyncIterableIterator<VectorRecord[]>;
76
+ supportsMetadataUpdate(): boolean;
77
+ supportsFiltering(): boolean;
78
+ supportsBatchOperations(): boolean;
79
+ private getCollection;
80
+ private mapDistanceMetric;
81
+ private unmapDistanceMetric;
82
+ }
83
+
84
+ export { ChromaAdapter, type ChromaConfig };
@@ -0,0 +1,84 @@
1
+ import { VectorDBAdapter, DistanceMetric, CollectionStats, VectorRecord, MetadataUpdate, UniversalFilter, SearchResult } from '@vectororm/core';
2
+
3
+ /**
4
+ * Configuration for ChromaAdapter.
5
+ *
6
+ * Supports hybrid config: explicit values or environment variables.
7
+ * Chroma can be self-hosted or used via cloud service.
8
+ */
9
+ interface ChromaConfig {
10
+ /**
11
+ * Chroma API key (optional for self-hosted).
12
+ * Falls back to CHROMA_API_KEY environment variable.
13
+ */
14
+ apiKey?: string;
15
+ /**
16
+ * Chroma server host.
17
+ * Falls back to CHROMA_HOST environment variable.
18
+ * Defaults to 'localhost'.
19
+ */
20
+ host?: string;
21
+ /**
22
+ * Chroma server port.
23
+ * Falls back to CHROMA_PORT environment variable.
24
+ * Defaults to 8000.
25
+ */
26
+ port?: number;
27
+ /**
28
+ * Use SSL/TLS for connection.
29
+ * Falls back to CHROMA_SSL environment variable.
30
+ * Defaults to false for localhost, true for remote hosts.
31
+ */
32
+ ssl?: boolean;
33
+ /**
34
+ * Optional tenant ID for multi-tenancy support.
35
+ */
36
+ tenant?: string;
37
+ /**
38
+ * Optional database name.
39
+ */
40
+ database?: string;
41
+ }
42
+
43
+ /**
44
+ * ChromaAdapter implements VectorDBAdapter for Chroma vector database.
45
+ *
46
+ * Supports both self-hosted and cloud Chroma instances.
47
+ * Uses chromadb npm package for native TypeScript support.
48
+ */
49
+ declare class ChromaAdapter extends VectorDBAdapter {
50
+ private config;
51
+ private client;
52
+ private collectionCache;
53
+ constructor(config?: ChromaConfig);
54
+ connect(): Promise<void>;
55
+ disconnect(): Promise<void>;
56
+ isConnected(): Promise<boolean>;
57
+ createCollection(name: string, dimension: number, metric?: DistanceMetric): Promise<void>;
58
+ deleteCollection(name: string): Promise<void>;
59
+ collectionExists(name: string): Promise<boolean>;
60
+ getCollectionStats(name: string): Promise<CollectionStats>;
61
+ upsert(collection: string, records: VectorRecord[]): Promise<void>;
62
+ fetch(collection: string, ids: string[]): Promise<VectorRecord[]>;
63
+ delete(collection: string, ids: string[]): Promise<void>;
64
+ updateMetadata(collection: string, updates: MetadataUpdate[]): Promise<void>;
65
+ search(collection: string, queryVector: number[], options?: {
66
+ topK?: number;
67
+ filter?: UniversalFilter;
68
+ includeMetadata?: boolean;
69
+ includeValues?: boolean;
70
+ }): Promise<SearchResult>;
71
+ translateFilter(filter: UniversalFilter): any;
72
+ iterate(collection: string, options?: {
73
+ batchSize?: number;
74
+ filter?: UniversalFilter;
75
+ }): AsyncIterableIterator<VectorRecord[]>;
76
+ supportsMetadataUpdate(): boolean;
77
+ supportsFiltering(): boolean;
78
+ supportsBatchOperations(): boolean;
79
+ private getCollection;
80
+ private mapDistanceMetric;
81
+ private unmapDistanceMetric;
82
+ }
83
+
84
+ export { ChromaAdapter, type ChromaConfig };
package/dist/index.js ADDED
@@ -0,0 +1,398 @@
1
+ // src/chroma-adapter.ts
2
+ import {
3
+ VectorDBAdapter
4
+ } from "@vectororm/core";
5
+ import { ChromaClient } from "chromadb";
6
+ var ChromaAdapter = class extends VectorDBAdapter {
7
+ config;
8
+ client = null;
9
+ collectionCache = /* @__PURE__ */ new Map();
10
+ constructor(config = {}) {
11
+ super();
12
+ this.config = config;
13
+ }
14
+ // ============================================================================
15
+ // CONNECTION MANAGEMENT
16
+ // ============================================================================
17
+ async connect() {
18
+ try {
19
+ const host = this.config.host || process.env.CHROMA_HOST || "localhost";
20
+ const port = this.config.port || (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8e3);
21
+ const ssl = this.config.ssl !== void 0 ? this.config.ssl : process.env.CHROMA_SSL === "true" || host !== "localhost";
22
+ const protocol = ssl ? "https" : "http";
23
+ const path = `${protocol}://${host}:${port}`;
24
+ const clientConfig = { path };
25
+ const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;
26
+ if (apiKey) {
27
+ clientConfig.auth = { provider: "token", credentials: apiKey };
28
+ }
29
+ if (this.config.tenant) {
30
+ clientConfig.tenant = this.config.tenant;
31
+ }
32
+ if (this.config.database) {
33
+ clientConfig.database = this.config.database;
34
+ }
35
+ this.client = new ChromaClient(clientConfig);
36
+ await this.client.heartbeat();
37
+ } catch (error) {
38
+ throw new Error(
39
+ `Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,
40
+ { cause: error }
41
+ );
42
+ }
43
+ }
44
+ async disconnect() {
45
+ this.client = null;
46
+ this.collectionCache.clear();
47
+ }
48
+ async isConnected() {
49
+ if (!this.client) return false;
50
+ try {
51
+ await this.client.heartbeat();
52
+ return true;
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+ // ============================================================================
58
+ // COLLECTION MANAGEMENT
59
+ // ============================================================================
60
+ async createCollection(name, dimension, metric = "cosine") {
61
+ if (!this.client) {
62
+ throw new Error("Not connected. Call connect() first.");
63
+ }
64
+ try {
65
+ const chromaMetric = this.mapDistanceMetric(metric);
66
+ const collection = await this.client.createCollection({
67
+ name,
68
+ metadata: {
69
+ "hnsw:space": chromaMetric,
70
+ dimension: dimension.toString()
71
+ }
72
+ });
73
+ this.collectionCache.set(name, collection);
74
+ } catch (error) {
75
+ throw new Error(
76
+ `Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
77
+ { cause: error }
78
+ );
79
+ }
80
+ }
81
+ async deleteCollection(name) {
82
+ if (!this.client) {
83
+ throw new Error("Not connected. Call connect() first.");
84
+ }
85
+ try {
86
+ await this.client.deleteCollection({ name });
87
+ this.collectionCache.delete(name);
88
+ } catch (error) {
89
+ throw new Error(
90
+ `Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,
91
+ { cause: error }
92
+ );
93
+ }
94
+ }
95
+ async collectionExists(name) {
96
+ if (!this.client) {
97
+ throw new Error("Not connected. Call connect() first.");
98
+ }
99
+ try {
100
+ const collections = await this.client.listCollections();
101
+ return collections.some((col) => col.name === name);
102
+ } catch (error) {
103
+ throw new Error(
104
+ `Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,
105
+ { cause: error }
106
+ );
107
+ }
108
+ }
109
+ async getCollectionStats(name) {
110
+ if (!this.client) {
111
+ throw new Error("Not connected. Call connect() first.");
112
+ }
113
+ try {
114
+ const collection = await this.getCollection(name);
115
+ const count = await collection.count();
116
+ const metadata = collection.metadata || {};
117
+ const dimension = metadata.dimension ? parseInt(metadata.dimension, 10) : 0;
118
+ const metricStr = metadata["hnsw:space"] || "cosine";
119
+ const metric = this.unmapDistanceMetric(metricStr);
120
+ return {
121
+ vectorCount: count,
122
+ dimension,
123
+ metric,
124
+ ...metadata
125
+ };
126
+ } catch (error) {
127
+ throw new Error(
128
+ `Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,
129
+ { cause: error }
130
+ );
131
+ }
132
+ }
133
+ // ============================================================================
134
+ // VECTOR OPERATIONS
135
+ // ============================================================================
136
+ async upsert(collection, records) {
137
+ if (!this.client) {
138
+ throw new Error("Not connected. Call connect() first.");
139
+ }
140
+ try {
141
+ const col = await this.getCollection(collection);
142
+ const ids = records.map((r) => r.id);
143
+ const embeddings = records.map((r) => r.embedding);
144
+ const metadatas = records.map((r) => r.metadata || {});
145
+ await col.upsert({
146
+ ids,
147
+ embeddings,
148
+ metadatas
149
+ });
150
+ } catch (error) {
151
+ throw new Error(
152
+ `Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
153
+ { cause: error }
154
+ );
155
+ }
156
+ }
157
+ async fetch(collection, ids) {
158
+ if (!this.client) {
159
+ throw new Error("Not connected. Call connect() first.");
160
+ }
161
+ try {
162
+ const col = await this.getCollection(collection);
163
+ const response = await col.get({
164
+ ids,
165
+ include: ["embeddings", "metadatas"]
166
+ });
167
+ const records = [];
168
+ if (response.ids && response.ids.length > 0) {
169
+ for (let i = 0; i < response.ids.length; i++) {
170
+ records.push({
171
+ id: response.ids[i],
172
+ embedding: response.embeddings?.[i] || [],
173
+ metadata: response.metadatas?.[i] || {}
174
+ });
175
+ }
176
+ }
177
+ return records;
178
+ } catch (error) {
179
+ throw new Error(
180
+ `Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
181
+ { cause: error }
182
+ );
183
+ }
184
+ }
185
+ async delete(collection, ids) {
186
+ if (!this.client) {
187
+ throw new Error("Not connected. Call connect() first.");
188
+ }
189
+ try {
190
+ const col = await this.getCollection(collection);
191
+ await col.delete({ ids });
192
+ } catch (error) {
193
+ throw new Error(
194
+ `Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
195
+ { cause: error }
196
+ );
197
+ }
198
+ }
199
+ // ============================================================================
200
+ // METADATA OPERATIONS
201
+ // ============================================================================
202
+ async updateMetadata(collection, updates) {
203
+ if (!this.client) {
204
+ throw new Error("Not connected. Call connect() first.");
205
+ }
206
+ try {
207
+ const col = await this.getCollection(collection);
208
+ for (const update of updates) {
209
+ await col.update({
210
+ ids: [update.id],
211
+ metadatas: [update.metadata]
212
+ });
213
+ }
214
+ } catch (error) {
215
+ throw new Error(
216
+ `Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
217
+ { cause: error }
218
+ );
219
+ }
220
+ }
221
+ // ============================================================================
222
+ // SEARCH OPERATIONS
223
+ // ============================================================================
224
+ async search(collection, queryVector, options) {
225
+ if (!this.client) {
226
+ throw new Error("Not connected. Call connect() first.");
227
+ }
228
+ try {
229
+ const col = await this.getCollection(collection);
230
+ const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
231
+ const include = ["distances"];
232
+ if (options?.includeMetadata !== false) {
233
+ include.push("metadatas");
234
+ }
235
+ if (options?.includeValues) {
236
+ include.push("embeddings");
237
+ }
238
+ const response = await col.query({
239
+ queryEmbeddings: [queryVector],
240
+ nResults: options?.topK || 10,
241
+ where: chromaFilter,
242
+ include
243
+ });
244
+ const records = [];
245
+ if (response.ids && response.ids[0]) {
246
+ const resultIds = response.ids[0];
247
+ const distances = response.distances?.[0] || [];
248
+ const embeddings = response.embeddings?.[0] || [];
249
+ const metadatas = response.metadatas?.[0] || [];
250
+ for (let i = 0; i < resultIds.length; i++) {
251
+ const record = {
252
+ id: resultIds[i],
253
+ embedding: options?.includeValues ? embeddings[i] || [] : [],
254
+ metadata: options?.includeMetadata !== false ? metadatas[i] || {} : {}
255
+ };
256
+ if (distances[i] !== void 0) {
257
+ record.score = 1 / (1 + distances[i]);
258
+ }
259
+ records.push(record);
260
+ }
261
+ }
262
+ return { records };
263
+ } catch (error) {
264
+ throw new Error(
265
+ `Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
266
+ { cause: error }
267
+ );
268
+ }
269
+ }
270
+ // ============================================================================
271
+ // FILTER TRANSLATION
272
+ // ============================================================================
273
+ translateFilter(filter) {
274
+ if ("and" in filter) {
275
+ const conditions = filter.and;
276
+ const translated = conditions.map((c) => this.translateFilter(c));
277
+ return { $and: translated };
278
+ }
279
+ if ("or" in filter) {
280
+ const conditions = filter.or;
281
+ const translated = conditions.map((c) => this.translateFilter(c));
282
+ return { $or: translated };
283
+ }
284
+ const { field, op, value } = filter;
285
+ const operatorMap = {
286
+ eq: "$eq",
287
+ ne: "$ne",
288
+ gt: "$gt",
289
+ gte: "$gte",
290
+ lt: "$lt",
291
+ lte: "$lte",
292
+ in: "$in",
293
+ nin: "$nin"
294
+ };
295
+ const chromaOp = operatorMap[op];
296
+ if (!chromaOp) {
297
+ throw new Error(
298
+ `Unsupported filter operator: ${op}`,
299
+ { cause: { filter } }
300
+ );
301
+ }
302
+ return {
303
+ [field]: {
304
+ [chromaOp]: value
305
+ }
306
+ };
307
+ }
308
+ // ============================================================================
309
+ // ITERATION
310
+ // ============================================================================
311
+ async *iterate(collection, options) {
312
+ if (!this.client) {
313
+ throw new Error("Not connected. Call connect() first.");
314
+ }
315
+ try {
316
+ const col = await this.getCollection(collection);
317
+ const batchSize = options?.batchSize || 100;
318
+ const chromaFilter = options?.filter ? this.translateFilter(options.filter) : void 0;
319
+ let offset = 0;
320
+ let hasMore = true;
321
+ while (hasMore) {
322
+ const response = await col.get({
323
+ where: chromaFilter,
324
+ limit: batchSize,
325
+ offset,
326
+ include: ["embeddings", "metadatas"]
327
+ });
328
+ if (response.ids && response.ids.length > 0) {
329
+ const records = [];
330
+ for (let i = 0; i < response.ids.length; i++) {
331
+ records.push({
332
+ id: response.ids[i],
333
+ embedding: response.embeddings?.[i] || [],
334
+ metadata: response.metadatas?.[i] || {}
335
+ });
336
+ }
337
+ yield records;
338
+ hasMore = response.ids.length === batchSize;
339
+ offset += batchSize;
340
+ } else {
341
+ hasMore = false;
342
+ }
343
+ }
344
+ } catch (error) {
345
+ throw new Error(
346
+ `Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,
347
+ { cause: error }
348
+ );
349
+ }
350
+ }
351
+ // ============================================================================
352
+ // CAPABILITY FLAGS
353
+ // ============================================================================
354
+ supportsMetadataUpdate() {
355
+ return true;
356
+ }
357
+ supportsFiltering() {
358
+ return true;
359
+ }
360
+ supportsBatchOperations() {
361
+ return true;
362
+ }
363
+ // ============================================================================
364
+ // HELPER METHODS
365
+ // ============================================================================
366
+ async getCollection(name) {
367
+ if (this.collectionCache.has(name)) {
368
+ return this.collectionCache.get(name);
369
+ }
370
+ if (!this.client) {
371
+ throw new Error("Not connected. Call connect() first.");
372
+ }
373
+ const collection = await this.client.getCollection({ name, embeddingFunction: void 0 });
374
+ this.collectionCache.set(name, collection);
375
+ return collection;
376
+ }
377
+ mapDistanceMetric(metric) {
378
+ const metricMap = {
379
+ cosine: "cosine",
380
+ euclidean: "l2",
381
+ dotProduct: "ip"
382
+ // Inner product
383
+ };
384
+ return metricMap[metric] || "cosine";
385
+ }
386
+ unmapDistanceMetric(chromaMetric) {
387
+ const metricMap = {
388
+ cosine: "cosine",
389
+ l2: "euclidean",
390
+ ip: "dotProduct"
391
+ };
392
+ return metricMap[chromaMetric] || "cosine";
393
+ }
394
+ };
395
+ export {
396
+ ChromaAdapter
397
+ };
398
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chroma-adapter.ts"],"sourcesContent":["import {\n VectorDBAdapter,\n type VectorRecord,\n type SearchResult,\n type UniversalFilter,\n type CollectionStats,\n type MetadataUpdate,\n type DistanceMetric,\n} from '@vectororm/core';\nimport { ChromaClient, type Collection } from 'chromadb';\nimport type { ChromaConfig } from './types.js';\n\n/**\n * ChromaAdapter implements VectorDBAdapter for Chroma vector database.\n *\n * Supports both self-hosted and cloud Chroma instances.\n * Uses chromadb npm package for native TypeScript support.\n */\nexport class ChromaAdapter extends VectorDBAdapter {\n private config: ChromaConfig;\n private client: ChromaClient | null = null;\n private collectionCache: Map<string, Collection> = new Map();\n\n constructor(config: ChromaConfig = {}) {\n super();\n this.config = config;\n }\n\n // ============================================================================\n // CONNECTION MANAGEMENT\n // ============================================================================\n\n async connect(): Promise<void> {\n try {\n const host = this.config.host || process.env.CHROMA_HOST || 'localhost';\n const port = this.config.port ||\n (process.env.CHROMA_PORT ? parseInt(process.env.CHROMA_PORT, 10) : 8000);\n\n // Determine SSL usage\n const ssl = this.config.ssl !== undefined\n ? this.config.ssl\n : (process.env.CHROMA_SSL === 'true' || host !== 'localhost');\n\n const protocol = ssl ? 'https' : 'http';\n const path = `${protocol}://${host}:${port}`;\n\n const clientConfig: any = { path };\n\n // Add auth if API key is provided\n const apiKey = this.config.apiKey || process.env.CHROMA_API_KEY;\n if (apiKey) {\n clientConfig.auth = { provider: 'token', credentials: apiKey };\n }\n\n // Add tenant/database if provided\n if (this.config.tenant) {\n clientConfig.tenant = this.config.tenant;\n }\n if (this.config.database) {\n clientConfig.database = this.config.database;\n }\n\n this.client = new ChromaClient(clientConfig);\n\n // Verify connection by getting heartbeat\n await this.client.heartbeat();\n } catch (error) {\n throw new Error(\n `Chroma connection failed: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n this.collectionCache.clear();\n }\n\n async isConnected(): Promise<boolean> {\n if (!this.client) return false;\n\n try {\n await this.client.heartbeat();\n return true;\n } catch {\n return false;\n }\n }\n\n // ============================================================================\n // COLLECTION MANAGEMENT\n // ============================================================================\n\n async createCollection(\n name: string,\n dimension: number,\n metric: DistanceMetric = 'cosine'\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n // Map our metric to Chroma distance function\n const chromaMetric = this.mapDistanceMetric(metric);\n\n const collection = await this.client.createCollection({\n name,\n metadata: {\n 'hnsw:space': chromaMetric,\n dimension: dimension.toString(),\n },\n });\n\n this.collectionCache.set(name, collection);\n } catch (error) {\n throw new Error(\n `Failed to create Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async deleteCollection(name: string): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n await this.client.deleteCollection({ name });\n this.collectionCache.delete(name);\n } catch (error) {\n throw new Error(\n `Failed to delete Chroma collection ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async collectionExists(name: string): Promise<boolean> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collections = await this.client.listCollections();\n return collections.some((col: any) => col.name === name);\n } catch (error) {\n throw new Error(\n `Failed to check if Chroma collection ${name} exists: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async getCollectionStats(name: string): Promise<CollectionStats> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const collection = await this.getCollection(name);\n const count = await collection.count();\n\n // Get metadata from collection\n const metadata = (collection as any).metadata || {};\n const dimension = metadata.dimension\n ? parseInt(metadata.dimension, 10)\n : 0;\n\n const metricStr = metadata['hnsw:space'] || 'cosine';\n const metric = this.unmapDistanceMetric(metricStr);\n\n return {\n vectorCount: count,\n dimension,\n metric,\n ...metadata,\n };\n } catch (error) {\n throw new Error(\n `Failed to get Chroma collection stats for ${name}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // VECTOR OPERATIONS\n // ============================================================================\n\n async upsert(collection: string, records: VectorRecord[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const ids = records.map((r) => r.id);\n const embeddings = records.map((r) => r.embedding);\n const metadatas = records.map((r) => r.metadata || {});\n\n await col.upsert({\n ids,\n embeddings,\n metadatas,\n });\n } catch (error) {\n throw new Error(\n `Failed to upsert vectors to Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async fetch(collection: string, ids: string[]): Promise<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const response = await col.get({\n ids,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids.length > 0) {\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n }\n\n return records;\n } catch (error) {\n throw new Error(\n `Failed to fetch vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n async delete(collection: string, ids: string[]): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n await col.delete({ ids });\n } catch (error) {\n throw new Error(\n `Failed to delete vectors from Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // METADATA OPERATIONS\n // ============================================================================\n\n async updateMetadata(\n collection: string,\n updates: MetadataUpdate[]\n ): Promise<void> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n // Chroma supports metadata updates via update method\n for (const update of updates) {\n await col.update({\n ids: [update.id],\n metadatas: [update.metadata],\n });\n }\n } catch (error) {\n throw new Error(\n `Failed to update metadata in Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // SEARCH OPERATIONS\n // ============================================================================\n\n async search(\n collection: string,\n queryVector: number[],\n options?: {\n topK?: number;\n filter?: UniversalFilter;\n includeMetadata?: boolean;\n includeValues?: boolean;\n }\n ): Promise<SearchResult> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n const include: any[] = ['distances' as any];\n if (options?.includeMetadata !== false) {\n include.push('metadatas' as any);\n }\n if (options?.includeValues) {\n include.push('embeddings' as any);\n }\n\n const response = await col.query({\n queryEmbeddings: [queryVector],\n nResults: options?.topK || 10,\n where: chromaFilter,\n include,\n });\n\n const records: VectorRecord[] = [];\n\n if (response.ids && response.ids[0]) {\n const resultIds = response.ids[0];\n const distances = response.distances?.[0] || [];\n const embeddings = response.embeddings?.[0] || [];\n const metadatas = response.metadatas?.[0] || [];\n\n for (let i = 0; i < resultIds.length; i++) {\n const record: VectorRecord = {\n id: resultIds[i],\n embedding: options?.includeValues ? (embeddings[i] || []) : [],\n metadata: options?.includeMetadata !== false ? (metadatas[i] || {}) : {},\n };\n\n // Convert distance to score (inverse relationship)\n if (distances[i] !== undefined) {\n record.score = 1 / (1 + distances[i]);\n }\n\n records.push(record);\n }\n }\n\n return { records };\n } catch (error) {\n throw new Error(\n `Failed to search Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // FILTER TRANSLATION\n // ============================================================================\n\n translateFilter(filter: UniversalFilter): any {\n // Handle compound AND filter\n if ('and' in filter) {\n const conditions = filter.and;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $and: translated };\n }\n\n // Handle compound OR filter\n if ('or' in filter) {\n const conditions = filter.or;\n const translated = conditions.map((c) => this.translateFilter(c));\n\n return { $or: translated };\n }\n\n // Handle basic filter condition\n const { field, op, value } = filter as any;\n\n // Operator mapping to Chroma's MongoDB-like syntax\n const operatorMap: Record<string, string> = {\n eq: '$eq',\n ne: '$ne',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n in: '$in',\n nin: '$nin',\n };\n\n const chromaOp = operatorMap[op];\n if (!chromaOp) {\n throw new Error(\n `Unsupported filter operator: ${op}`,\n { cause: { filter } }\n );\n }\n\n return {\n [field]: {\n [chromaOp]: value,\n },\n };\n }\n\n // ============================================================================\n // ITERATION\n // ============================================================================\n\n async *iterate(\n collection: string,\n options?: {\n batchSize?: number;\n filter?: UniversalFilter;\n }\n ): AsyncIterableIterator<VectorRecord[]> {\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n try {\n const col = await this.getCollection(collection);\n const batchSize = options?.batchSize || 100;\n const chromaFilter = options?.filter\n ? this.translateFilter(options.filter)\n : undefined;\n\n // Chroma uses offset/limit pagination\n let offset = 0;\n let hasMore = true;\n\n while (hasMore) {\n const response = await col.get({\n where: chromaFilter,\n limit: batchSize,\n offset,\n include: ['embeddings' as any, 'metadatas' as any],\n });\n\n if (response.ids && response.ids.length > 0) {\n const records: VectorRecord[] = [];\n\n for (let i = 0; i < response.ids.length; i++) {\n records.push({\n id: response.ids[i],\n embedding: response.embeddings?.[i] || [],\n metadata: response.metadatas?.[i] || {},\n });\n }\n\n yield records;\n\n // Check if there are more results\n hasMore = response.ids.length === batchSize;\n offset += batchSize;\n } else {\n hasMore = false;\n }\n }\n } catch (error) {\n throw new Error(\n `Failed to iterate Chroma collection ${collection}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error }\n );\n }\n }\n\n // ============================================================================\n // CAPABILITY FLAGS\n // ============================================================================\n\n supportsMetadataUpdate(): boolean {\n return true; // Chroma supports metadata updates\n }\n\n supportsFiltering(): boolean {\n return true; // Chroma supports metadata filtering\n }\n\n supportsBatchOperations(): boolean {\n return true; // Chroma supports batch operations\n }\n\n // ============================================================================\n // HELPER METHODS\n // ============================================================================\n\n private async getCollection(name: string): Promise<Collection> {\n if (this.collectionCache.has(name)) {\n return this.collectionCache.get(name)!;\n }\n\n if (!this.client) {\n throw new Error('Not connected. Call connect() first.');\n }\n\n const collection = await this.client.getCollection({ name, embeddingFunction: undefined as any });\n this.collectionCache.set(name, collection);\n return collection;\n }\n\n private mapDistanceMetric(metric: DistanceMetric): string {\n const metricMap: Record<DistanceMetric, string> = {\n cosine: 'cosine',\n euclidean: 'l2',\n dotProduct: 'ip', // Inner product\n };\n\n return metricMap[metric] || 'cosine';\n }\n\n private unmapDistanceMetric(chromaMetric: string): DistanceMetric {\n const metricMap: Record<string, DistanceMetric> = {\n cosine: 'cosine',\n l2: 'euclidean',\n ip: 'dotProduct',\n };\n\n return metricMap[chromaMetric] || 'cosine';\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@vectororm/adapter-chroma",
3
+ "version": "0.1.0",
4
+ "description": "ChromaDB adapter for Glyph VectorORM",
5
+ "author": "Aviram Roisman",
6
+ "license": "Apache-2.0",
7
+ "homepage": "https://github.com/aviramroi/VectorORM",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/aviramroi/VectorORM.git",
11
+ "directory": "packages/adapter-chroma"
12
+ },
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "require": "./dist/index.js",
24
+ "import": "./dist/index.mjs"
25
+ }
26
+ },
27
+ "files": ["dist", "README.md"],
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "test": "vitest run",
34
+ "test:watch": "vitest",
35
+ "test:integration": "vitest run --config vitest.integration.config.ts"
36
+ },
37
+ "dependencies": {
38
+ "@vectororm/core": "*",
39
+ "chromadb": "^1.8.1"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^20.10.0",
43
+ "tsup": "^8.0.0",
44
+ "typescript": "^5.3.3",
45
+ "vitest": "^1.0.0"
46
+ },
47
+ "peerDependencies": {
48
+ "@vectororm/core": "^0.1.0"
49
+ },
50
+ "keywords": [
51
+ "glyph",
52
+ "vectororm",
53
+ "chroma",
54
+ "chromadb",
55
+ "vector-database",
56
+ "adapter"
57
+ ]
58
+ }