@bridgerust/embex 0.1.13 → 0.1.14

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.
Files changed (53) hide show
  1. package/README.md +70 -97
  2. package/bin/embex.js +0 -0
  3. package/bun.lockb +0 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +17 -0
  7. package/dist/src/index.d.ts +8 -0
  8. package/dist/src/index.d.ts.map +1 -0
  9. package/dist/src/index.js +26 -0
  10. package/dist/src/tests/integration/adapters.test.d.ts +13 -0
  11. package/dist/src/tests/integration/adapters.test.d.ts.map +1 -0
  12. package/dist/src/tests/integration/adapters.test.js +372 -0
  13. package/dist/src/tests/integration/aggregations.test.d.ts +6 -0
  14. package/dist/src/tests/integration/aggregations.test.d.ts.map +1 -0
  15. package/dist/src/tests/integration/aggregations.test.js +96 -0
  16. package/dist/src/tests/integration/api_parity.test.d.ts +6 -0
  17. package/dist/src/tests/integration/api_parity.test.d.ts.map +1 -0
  18. package/dist/src/tests/integration/api_parity.test.js +99 -0
  19. package/dist/src/tests/integration/batch.test.d.ts +2 -0
  20. package/dist/src/tests/integration/batch.test.d.ts.map +1 -0
  21. package/dist/src/tests/integration/batch.test.js +53 -0
  22. package/dist/src/tests/integration/errors.test.d.ts +6 -0
  23. package/dist/src/tests/integration/errors.test.d.ts.map +1 -0
  24. package/dist/src/tests/integration/errors.test.js +133 -0
  25. package/dist/src/tests/integration/features.test.d.ts +2 -0
  26. package/dist/src/tests/integration/features.test.d.ts.map +1 -0
  27. package/dist/src/tests/integration/features.test.js +37 -0
  28. package/dist/src/tests/integration/filters.test.d.ts +6 -0
  29. package/dist/src/tests/integration/filters.test.d.ts.map +1 -0
  30. package/dist/src/tests/integration/filters.test.js +296 -0
  31. package/dist/src/tests/integration/metadata.test.d.ts +6 -0
  32. package/dist/src/tests/integration/metadata.test.d.ts.map +1 -0
  33. package/dist/src/tests/integration/metadata.test.js +167 -0
  34. package/dist/src/tests/integration/migrations.test.d.ts +2 -0
  35. package/dist/src/tests/integration/migrations.test.d.ts.map +1 -0
  36. package/dist/src/tests/integration/migrations.test.js +55 -0
  37. package/dist/src/tests/integration/pooling.test.d.ts +6 -0
  38. package/dist/src/tests/integration/pooling.test.d.ts.map +1 -0
  39. package/dist/src/tests/integration/pooling.test.js +56 -0
  40. package/dist/src/tests/integration/search.test.d.ts +2 -0
  41. package/dist/src/tests/integration/search.test.d.ts.map +1 -0
  42. package/dist/src/tests/integration/search.test.js +37 -0
  43. package/dist/src/tests/integration/streaming.test.d.ts +2 -0
  44. package/dist/src/tests/integration/streaming.test.d.ts.map +1 -0
  45. package/dist/src/tests/integration/streaming.test.js +42 -0
  46. package/dist/src/tests/unit/basic.test.d.ts +2 -0
  47. package/dist/src/tests/unit/basic.test.d.ts.map +1 -0
  48. package/dist/src/tests/unit/basic.test.js +23 -0
  49. package/dist/src/tests/unit/errors.test.d.ts +2 -0
  50. package/dist/src/tests/unit/errors.test.d.ts.map +1 -0
  51. package/dist/src/tests/unit/errors.test.js +19 -0
  52. package/package.json +7 -6
  53. package/tsconfig.json +2 -0
package/README.md CHANGED
@@ -1,139 +1,112 @@
1
1
  # Embex (Node.js)
2
2
 
3
- **The Universal Vector Database ORM.** One API for Qdrant, Pinecone, Chroma, LanceDB, and more.
3
+ **The fastest way to add vector search to your app.**
4
4
 
5
- Embex is a high-performance, universal client for vector databases, built on a shared Rust core related to [BridgeRust](https://github.com/bridgerust/bridgerust).
5
+ Embex is a universal vector database client that lets you start with zero setup and scale to production without rewriting code.
6
6
 
7
7
  ## 🚀 Features
8
8
 
9
- - **Unified API**: Switch providers instantly. "Write once, run anywhere."
10
- - **Performance**: Powered by Rust with SIMD acceleration.
9
+ - **Start Simple**: Use LanceDB (embedded) for zero-setup local development.
10
+ - **Unified API**: Switch to Qdrant, Pinecone, or Milvus just by changing the config.
11
+ - **Performance**: Powered by a shared Rust core with SIMD acceleration.
11
12
  - **Type Safety**: Full TypeScript support.
12
13
 
13
14
  ## 📦 Installation
14
15
 
15
16
  ```bash
16
- npm install @bridgerust/embex
17
- ```
18
-
19
- ```bash
20
- yarn add @bridgerust/embex
21
- ```
22
-
23
- ```bash
24
- bun add @bridgerust/embex
17
+ npm install @bridgerust/embex lancedb @xenova/transformers
25
18
  ```
26
19
 
27
20
  ## ⚡ Quick Start
28
21
 
29
- **Try Embex in 30 seconds - No setup required!** Uses LanceDB embedded mode (no server needed).
22
+ Build semantic search in 5 minutes using **LanceDB** (embedded) and local embeddings. No API keys or Docker needed!
30
23
 
31
24
  ```typescript
32
- import { EmbexClient } from "@bridgerust/embex";
25
+ import { EmbexClient, Vector } from "@bridgerust/embex";
26
+ import { pipeline } from "@xenova/transformers";
33
27
 
34
28
  async function main() {
35
- // LanceDB embedded - zero setup, just a local path
36
- const client = await EmbexClient.newAsync("lancedb", "./data");
37
- const collection = client.collection("documents");
38
-
39
- // Create collection
40
- await collection.create(768, "cosine");
41
-
42
- // Insert data
43
- await collection.insert([
44
- {
45
- id: "1",
46
- vector: Array(768).fill(0.1),
47
- metadata: { text: "Hello World" },
48
- },
49
- ]);
50
-
51
- // Search
52
- const results = await collection.search(Array(768).fill(0.1), 5);
53
- console.log(results.results);
29
+ // 1. Setup Embedding Model
30
+ const generateEmbedding = await pipeline(
31
+ "feature-extraction",
32
+ "Xenova/all-MiniLM-L6-v2"
33
+ );
34
+ const embed = async (text: string) => {
35
+ const output = await generateEmbedding(text, {
36
+ pooling: "mean",
37
+ normalize: true,
38
+ });
39
+ return Array.from(output.data);
40
+ };
41
+
42
+ // 2. Initialize Client (uses LanceDB embedded)
43
+ const client = await EmbexClient.newAsync("lancedb://./data");
44
+
45
+ // 3. Create Collection (384 dimensions for MiniLM)
46
+ await client.createCollection("products", 384);
47
+
48
+ // 4. Insert Data
49
+ const documents = [
50
+ { id: "1", text: "Apple iPhone 15", category: "electronics" },
51
+ { id: "2", text: "Samsung Galaxy S24", category: "electronics" },
52
+ ];
53
+
54
+ const vectors: Vector[] = [];
55
+ for (const doc of documents) {
56
+ vectors.push({
57
+ id: doc.id,
58
+ vector: await embed(doc.text),
59
+ metadata: { text: doc.text },
60
+ });
61
+ }
62
+
63
+ await client.insert("products", vectors);
64
+
65
+ // 5. Search
66
+ const query = "smartphone";
67
+ const results = await client.search({
68
+ collection_name: "products",
69
+ vector: await embed(query),
70
+ limit: 1,
71
+ });
72
+
73
+ console.log(`Query: '${query}'`);
74
+ console.log(`Match: ${results[0].metadata.text}`);
54
75
  }
55
76
 
56
77
  main();
57
78
  ```
58
79
 
59
- **Run it:** `npx tsx examples/lancedb/node/quickstart.ts`
60
-
61
- ### All Provider Quick Starts
80
+ ## 🗺️ Development Production Roadmap
62
81
 
63
- Try Embex with any provider! Same API, different backend:
82
+ | Stage | Recommendation | Why? |
83
+ | :------------------ | :-------------------- | :---------------------------------- |
84
+ | **Day 1: Learning** | **LanceDB** | Embedded. Zero setup. Free. |
85
+ | **Week 2: Staging** | **Qdrant / Pinecone** | Managed cloud. Connection pooling. |
86
+ | **Month 1: Scale** | **Milvus** | Distributed. Billion-scale vectors. |
87
+ | **Anytime** | **PgVector** | You already use PostgreSQL. |
64
88
 
65
- | Provider | Setup | Quick Start |
66
- | ------------ | --------------- | ---------------------------------------------- |
67
- | **LanceDB** | None (embedded) | `npx tsx examples/lancedb/node/quickstart.ts` |
68
- | **Qdrant** | Docker server | `npx tsx examples/qdrant/node/quickstart.ts` |
69
- | **Pinecone** | API key | `npx tsx examples/pinecone/node/quickstart.ts` |
70
- | **Chroma** | Optional server | `npx tsx examples/chroma/node/quickstart.ts` |
89
+ ## ☁️ Switch Provider (Zero Code Changes)
71
90
 
72
- > 💡 **Same API everywhere!** Just change the provider name - all code stays the same. See [examples/README.md](../../../../examples/README.md) for setup instructions.
91
+ Ready for production? Just change the initialization line.
73
92
 
74
- ### 5. Filtered Search (Builder Pattern)
93
+ **From LanceDB (Dev):**
75
94
 
76
95
  ```typescript
77
- const results = await collection.buildSearch([0.1, 0.2, ...])
78
- .limit(10)
79
- .filter({
80
- course: "CS101"
81
- })
82
- .execute();
96
+ const client = await EmbexClient.newAsync("lancedb://./data");
83
97
  ```
84
98
 
85
- ## ☁️ Connecting to Cloud Providers
86
-
87
- To connect to managed services like Pinecone, Qdrant Cloud, or Zilliz (Milvus), simply provide your API key and endpoint URL.
99
+ **To Qdrant Cloud (Prod):**
88
100
 
89
101
  ```typescript
90
- import { EmbexClient } from "@bridgerust/embex";
91
-
92
- // Connect to Pinecone
93
102
  const client = new EmbexClient(
94
- "pinecone",
95
- "https://index-name.svc.pinecone.io",
96
- process.env.PINECONE_API_KEY
97
- );
98
-
99
- // Connect to Qdrant Cloud
100
- const qdrantClient = new EmbexClient(
101
103
  "qdrant",
102
- "https://xyz-example.eu-central.aws.cloud.qdrant.io:6333",
104
+ "https://your-cluster.qdrant.io",
103
105
  process.env.QDRANT_API_KEY
104
106
  );
105
107
  ```
106
108
 
107
- ### Official Documentation & API Keys
108
-
109
- Need help finding your API key? Check the official provider documentation:
110
-
111
- - **Pinecone**: [Authentication & API Keys](https://docs.pinecone.io/guides/get-started/quickstart#2-get-an-api-key)
112
- - **Qdrant**: [Cloud Authentication](https://qdrant.tech/documentation/cloud/authentication/)
113
- - **Milvus (Zilliz)**: [Manage Credentials](https://docs.zilliz.com/docs/manage-api-keys)
114
- - **Weaviate**: [Authentication](https://weaviate.io/developers/weaviate/configuration/authentication)
115
- - **Chroma**: [Auth & Client Settings](https://docs.trychroma.com/guides#authentication)
116
-
117
- ## 🔌 Supported Providers
118
-
119
- | Provider | Key | Async Init? |
120
- | -------- | ---------- | ----------- |
121
- | Qdrant | `qdrant` | No |
122
- | Chroma | `chroma` | No |
123
- | Pinecone | `pinecone` | No |
124
- | Weaviate | `weaviate` | No |
125
- | LanceDB | `lancedb` | **Yes** |
126
- | Milvus | `milvus` | **Yes** |
127
- | PgVector | `pgvector` | **Yes** |
128
-
129
- ## ⭐ Star Us
130
-
131
- If you find Embex useful, please star the repository! It helps others discover the project.
132
-
133
- [⭐ Star on GitHub](https://github.com/bridgerust/bridgerust)
134
-
135
109
  ## 🔗 Resources
136
110
 
137
- - **Main Repository**: [github.com/bridgerust/bridgerust](https://github.com/bridgerust/bridgerust)
138
- - **Issues**: [github.com/bridgerust/bridgerust/issues](https://github.com/bridgerust/bridgerust/issues)
139
- - **Documentation**: [Full Docs](https://github.com/bridgerust/bridgerust/tree/main/bindings/node/%40bridgerust/embex)
111
+ - **Full Documentation**: [bridgerust.dev/embex](https://bridgerust.dev/embex/introduction)
112
+ - **GitHub**: [bridgerust/bridgerust](https://github.com/bridgerust/bridgerust)
package/bin/embex.js CHANGED
File without changes
package/bun.lockb CHANGED
Binary file
@@ -0,0 +1,2 @@
1
+ export * from "./src";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./src"), exports);
@@ -0,0 +1,8 @@
1
+ import { Collection, EmbexClient, QueryBuilder, SearchBuilder, cli, Point } from "../native";
2
+ declare module "../native" {
3
+ interface Collection {
4
+ insertStream(points: AsyncIterable<Point>, parallel?: number): Promise<void>;
5
+ }
6
+ }
7
+ export { Collection, EmbexClient, QueryBuilder, SearchBuilder, cli, Point };
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EAEb,GAAG,EACH,KAAK,EACN,MAAM,WAAW,CAAC;AAEnB,OAAO,QAAQ,WAAW,CAAC;IACzB,UAAU,UAAU;QAClB,YAAY,CACV,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,EAC5B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC;KAClB;CACF;AAwBD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cli = exports.SearchBuilder = exports.QueryBuilder = exports.EmbexClient = exports.Collection = void 0;
4
+ const native_1 = require("../native");
5
+ Object.defineProperty(exports, "Collection", { enumerable: true, get: function () { return native_1.Collection; } });
6
+ Object.defineProperty(exports, "EmbexClient", { enumerable: true, get: function () { return native_1.EmbexClient; } });
7
+ Object.defineProperty(exports, "QueryBuilder", { enumerable: true, get: function () { return native_1.QueryBuilder; } });
8
+ Object.defineProperty(exports, "SearchBuilder", { enumerable: true, get: function () { return native_1.SearchBuilder; } });
9
+ Object.defineProperty(exports, "cli", { enumerable: true, get: function () { return
10
+ // @ts-ignore
11
+ native_1.cli; } });
12
+ // Monkey patch
13
+ native_1.Collection.prototype.insertStream = async function (points, parallel = 5) {
14
+ const BATCH_SIZE = 100;
15
+ let batch = [];
16
+ for await (const point of points) {
17
+ batch.push(point);
18
+ if (batch.length >= BATCH_SIZE) {
19
+ await this.insertBatch(batch, BATCH_SIZE, parallel);
20
+ batch = [];
21
+ }
22
+ }
23
+ if (batch.length > 0) {
24
+ await this.insertBatch(batch, BATCH_SIZE, parallel);
25
+ }
26
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Embex Integration Tests - Node.js
3
+ * Tests all adapter implementations against real database instances.
4
+ *
5
+ * Run Docker Compose first: docker-compose up -d
6
+ *
7
+ * Usage:
8
+ * cd bindings/node/@bridgerust/embex
9
+ * npm run build
10
+ * npm test tests/integration/
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=adapters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/integration/adapters.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,372 @@
1
+ "use strict";
2
+ /**
3
+ * Embex Integration Tests - Node.js
4
+ * Tests all adapter implementations against real database instances.
5
+ *
6
+ * Run Docker Compose first: docker-compose up -d
7
+ *
8
+ * Usage:
9
+ * cd bindings/node/@bridgerust/embex
10
+ * npm run build
11
+ * npm test tests/integration/
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ const vitest_1 = require("vitest");
15
+ const index_1 = require("../../index");
16
+ const crypto_1 = require("crypto");
17
+ const os_1 = require("os");
18
+ const path_1 = require("path");
19
+ const TEST_DIMENSION = 128;
20
+ const TEST_COLLECTION = "embex_integration_test_node";
21
+ function randomVector(dim = TEST_DIMENSION) {
22
+ return Array.from({ length: dim }, () => Math.random());
23
+ }
24
+ (0, vitest_1.describe)("Qdrant Adapter", () => {
25
+ let client;
26
+ let collection;
27
+ (0, vitest_1.beforeAll)(() => {
28
+ client = new index_1.EmbexClient("qdrant", "http://localhost:6334");
29
+ collection = client.collection(TEST_COLLECTION);
30
+ });
31
+ (0, vitest_1.afterAll)(async () => {
32
+ try {
33
+ await collection.deleteCollection();
34
+ }
35
+ catch (e) { }
36
+ });
37
+ (0, vitest_1.it)("should create collection", async () => {
38
+ try {
39
+ await collection.deleteCollection();
40
+ }
41
+ catch (e) { }
42
+ await collection.create(TEST_DIMENSION, "cosine");
43
+ });
44
+ (0, vitest_1.it)("should insert and search points", async () => {
45
+ try {
46
+ await collection.deleteCollection();
47
+ }
48
+ catch (e) { }
49
+ await collection.create(TEST_DIMENSION, "cosine");
50
+ const points = [
51
+ { id: (0, crypto_1.randomUUID)(), vector: randomVector(), metadata: { category: "A" } },
52
+ { id: (0, crypto_1.randomUUID)(), vector: randomVector(), metadata: { category: "B" } },
53
+ { id: (0, crypto_1.randomUUID)(), vector: randomVector(), metadata: { category: "A" } },
54
+ ];
55
+ await collection.insert(points);
56
+ const results = await collection.query(randomVector(), { limit: 2 });
57
+ (0, vitest_1.expect)(results.results.length).toBe(2);
58
+ });
59
+ (0, vitest_1.it)("should use search() method with direct parameters", async () => {
60
+ try {
61
+ await collection.deleteCollection();
62
+ }
63
+ catch (e) { }
64
+ await collection.create(TEST_DIMENSION, "cosine");
65
+ const points = [
66
+ { id: (0, crypto_1.randomUUID)(), vector: randomVector(), metadata: { category: "A" } },
67
+ { id: (0, crypto_1.randomUUID)(), vector: randomVector(), metadata: { category: "B" } },
68
+ ];
69
+ await collection.insert(points);
70
+ const results = await collection.search(randomVector(), 2, null, true, false);
71
+ (0, vitest_1.expect)(results.results.length).toBe(2);
72
+ (0, vitest_1.expect)(results.results[0].id).toBeDefined();
73
+ (0, vitest_1.expect)(results.results[0].score).toBeDefined();
74
+ });
75
+ (0, vitest_1.it)("should search with filters", async () => {
76
+ try {
77
+ await collection.deleteCollection();
78
+ }
79
+ catch (e) { }
80
+ await collection.create(TEST_DIMENSION, "cosine");
81
+ const points = [
82
+ {
83
+ id: (0, crypto_1.randomUUID)(),
84
+ vector: randomVector(),
85
+ metadata: { status: "active", score: 10 },
86
+ },
87
+ {
88
+ id: (0, crypto_1.randomUUID)(),
89
+ vector: randomVector(),
90
+ metadata: { status: "inactive", score: 20 },
91
+ },
92
+ {
93
+ id: (0, crypto_1.randomUUID)(),
94
+ vector: randomVector(),
95
+ metadata: { status: "active", score: 30 },
96
+ },
97
+ ];
98
+ await collection.insert(points);
99
+ const filter = {
100
+ op: "key",
101
+ args: ["status", { eq: "active" }],
102
+ };
103
+ const results = await collection.search(randomVector(), 10, filter, true, false);
104
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(2);
105
+ results.results.forEach((r) => {
106
+ (0, vitest_1.expect)(r.metadata?.status).toBe("active");
107
+ });
108
+ });
109
+ (0, vitest_1.it)("should use search builder pattern", async () => {
110
+ try {
111
+ await collection.deleteCollection();
112
+ }
113
+ catch (e) { }
114
+ await collection.create(TEST_DIMENSION, "cosine");
115
+ const points = [
116
+ { id: (0, crypto_1.randomUUID)(), vector: randomVector(), metadata: { type: "test" } },
117
+ ];
118
+ await collection.insert(points);
119
+ const builder = collection.buildSearch(randomVector());
120
+ const results = await builder
121
+ .limit(5)
122
+ .includeMetadata(true)
123
+ .includeVector(false)
124
+ .execute();
125
+ (0, vitest_1.expect)(results.results).toBeDefined();
126
+ (0, vitest_1.expect)(Array.isArray(results.results)).toBe(true);
127
+ });
128
+ (0, vitest_1.it)("should insert batch with parallel option", async () => {
129
+ try {
130
+ await collection.deleteCollection();
131
+ }
132
+ catch (e) { }
133
+ await collection.create(TEST_DIMENSION, "cosine");
134
+ const points = Array.from({ length: 50 }, () => ({
135
+ id: (0, crypto_1.randomUUID)(),
136
+ vector: randomVector(),
137
+ metadata: { batch: "test" },
138
+ }));
139
+ await collection.insertBatch(points, 10, 3);
140
+ const results = await collection.query(randomVector(), { limit: 50 });
141
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(50);
142
+ });
143
+ (0, vitest_1.it)("should delete points", async () => {
144
+ try {
145
+ await collection.deleteCollection();
146
+ }
147
+ catch (e) { }
148
+ await collection.create(TEST_DIMENSION, "cosine");
149
+ const delId = (0, crypto_1.randomUUID)();
150
+ await collection.insert([
151
+ { id: delId, vector: randomVector(), metadata: {} },
152
+ ]);
153
+ await collection.delete([delId]);
154
+ const results = await collection.query(randomVector(), { limit: 10 });
155
+ const ids = results.results.map((r) => r.id);
156
+ (0, vitest_1.expect)(ids).not.toContain(delId);
157
+ });
158
+ });
159
+ (0, vitest_1.describe)("Chroma Adapter", () => {
160
+ let client;
161
+ let collection;
162
+ (0, vitest_1.beforeAll)(() => {
163
+ client = new index_1.EmbexClient("chroma", "http://localhost:8000");
164
+ collection = client.collection(TEST_COLLECTION);
165
+ });
166
+ (0, vitest_1.afterAll)(async () => {
167
+ try {
168
+ await collection.deleteCollection();
169
+ }
170
+ catch (e) { }
171
+ });
172
+ (0, vitest_1.it)("should perform CRUD operations", async () => {
173
+ try {
174
+ await collection.deleteCollection();
175
+ }
176
+ catch (e) { }
177
+ await collection.create(TEST_DIMENSION, "cosine");
178
+ const points = [
179
+ { id: "c1", vector: randomVector(), metadata: { type: "test" } },
180
+ { id: "c2", vector: randomVector(), metadata: { type: "test" } },
181
+ ];
182
+ await collection.insert(points);
183
+ const results = await collection.query(randomVector(), { limit: 2 });
184
+ (0, vitest_1.expect)(results.results.length).toBe(2);
185
+ });
186
+ (0, vitest_1.it)("should use search() method", async () => {
187
+ try {
188
+ await collection.deleteCollection();
189
+ }
190
+ catch (e) { }
191
+ await collection.create(TEST_DIMENSION, "cosine");
192
+ const points = [
193
+ { id: "c3", vector: randomVector(), metadata: { type: "search" } },
194
+ ];
195
+ await collection.insert(points);
196
+ const results = await collection.search(randomVector(), 1);
197
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
198
+ });
199
+ (0, vitest_1.it)("should create collection with auto dimension inference", async () => {
200
+ try {
201
+ await collection.deleteCollection();
202
+ }
203
+ catch (e) { }
204
+ await collection.createAuto(undefined, "cosine");
205
+ const points = [
206
+ { id: "c4", vector: randomVector(), metadata: { type: "auto" } },
207
+ { id: "c5", vector: randomVector(), metadata: { type: "auto" } },
208
+ ];
209
+ await collection.insert(points);
210
+ const results = await collection.query(randomVector(), { limit: 2 });
211
+ (0, vitest_1.expect)(results.results.length).toBe(2);
212
+ await collection.deleteCollection();
213
+ });
214
+ });
215
+ (0, vitest_1.describe)("Weaviate Adapter", () => {
216
+ let client;
217
+ let collection;
218
+ (0, vitest_1.beforeAll)(() => {
219
+ client = new index_1.EmbexClient("weaviate", "http://localhost:8080");
220
+ collection = client.collection("EmbexNodeTest");
221
+ });
222
+ (0, vitest_1.afterAll)(async () => {
223
+ try {
224
+ await collection.deleteCollection();
225
+ }
226
+ catch (e) { }
227
+ });
228
+ (0, vitest_1.it)("should perform CRUD operations", async () => {
229
+ try {
230
+ await collection.deleteCollection();
231
+ }
232
+ catch (e) { }
233
+ await collection.create(TEST_DIMENSION, "cosine");
234
+ const points = [
235
+ { id: "w1", vector: randomVector(), metadata: { name: "test1" } },
236
+ { id: "w2", vector: randomVector(), metadata: { name: "test2" } },
237
+ ];
238
+ await collection.insert(points);
239
+ const results = await collection.query(randomVector(), { limit: 2 });
240
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
241
+ });
242
+ });
243
+ (0, vitest_1.describe)("Milvus Adapter", () => {
244
+ let client;
245
+ let collection;
246
+ (0, vitest_1.beforeAll)(async () => {
247
+ // Milvus requires async initialization
248
+ client = await index_1.EmbexClient.newAsync("milvus", "http://localhost:19530");
249
+ collection = client.collection(TEST_COLLECTION);
250
+ });
251
+ (0, vitest_1.afterAll)(async () => {
252
+ try {
253
+ await collection.deleteCollection();
254
+ }
255
+ catch (e) { }
256
+ });
257
+ (0, vitest_1.it)("should perform CRUD operations", async () => {
258
+ try {
259
+ await collection.deleteCollection();
260
+ }
261
+ catch (e) { }
262
+ await collection.create(TEST_DIMENSION, "cosine");
263
+ const points = [
264
+ { id: "m1", vector: randomVector(), metadata: {} },
265
+ { id: "m2", vector: randomVector(), metadata: {} },
266
+ ];
267
+ await collection.insert(points);
268
+ const results = await collection.query(randomVector(), { limit: 2 });
269
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
270
+ });
271
+ (0, vitest_1.it)("should use search() method", async () => {
272
+ try {
273
+ await collection.deleteCollection();
274
+ }
275
+ catch (e) { }
276
+ await collection.create(TEST_DIMENSION, "cosine");
277
+ const points = [
278
+ { id: "m3", vector: randomVector(), metadata: { test: "milvus" } },
279
+ ];
280
+ await collection.insert(points);
281
+ const results = await collection.search(randomVector(), 1);
282
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
283
+ });
284
+ });
285
+ (0, vitest_1.describe)("pgvector Adapter", () => {
286
+ let client;
287
+ let collection;
288
+ (0, vitest_1.beforeAll)(async () => {
289
+ // pgvector requires async initialization
290
+ client = await index_1.EmbexClient.newAsync("pgvector", "postgresql://embex:embex_test@localhost:5432/embex_test");
291
+ collection = client.collection(TEST_COLLECTION);
292
+ });
293
+ (0, vitest_1.afterAll)(async () => {
294
+ try {
295
+ await collection.deleteCollection();
296
+ }
297
+ catch (e) { }
298
+ });
299
+ (0, vitest_1.it)("should perform CRUD operations", async () => {
300
+ try {
301
+ await collection.deleteCollection();
302
+ }
303
+ catch (e) { }
304
+ await collection.create(TEST_DIMENSION, "cosine");
305
+ const points = [
306
+ { id: "pg1", vector: randomVector(), metadata: { info: "test" } },
307
+ { id: "pg2", vector: randomVector(), metadata: { info: "test" } },
308
+ ];
309
+ await collection.insert(points);
310
+ const results = await collection.query(randomVector(), { limit: 2 });
311
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
312
+ });
313
+ (0, vitest_1.it)("should use search() method with filters", async () => {
314
+ try {
315
+ await collection.deleteCollection();
316
+ }
317
+ catch (e) { }
318
+ await collection.create(TEST_DIMENSION, "cosine");
319
+ const points = [
320
+ { id: "pg3", vector: randomVector(), metadata: { status: "active" } },
321
+ ];
322
+ await collection.insert(points);
323
+ const filter = {
324
+ op: "key",
325
+ args: ["status", { eq: "active" }],
326
+ };
327
+ const results = await collection.search(randomVector(), 5, filter, true, false);
328
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
329
+ });
330
+ });
331
+ (0, vitest_1.describe)("LanceDB Adapter", () => {
332
+ let client;
333
+ let collection;
334
+ const dbPath = (0, path_1.join)((0, os_1.tmpdir)(), `lancedb_node_test_${Date.now()}`);
335
+ (0, vitest_1.beforeAll)(async () => {
336
+ client = await index_1.EmbexClient.newAsync("lancedb", dbPath);
337
+ collection = client.collection(TEST_COLLECTION);
338
+ });
339
+ (0, vitest_1.afterAll)(async () => {
340
+ try {
341
+ await collection.deleteCollection();
342
+ }
343
+ catch (e) { }
344
+ });
345
+ (0, vitest_1.it)("should perform CRUD operations", async () => {
346
+ try {
347
+ await collection.deleteCollection();
348
+ }
349
+ catch (e) { }
350
+ await collection.create(TEST_DIMENSION, "cosine");
351
+ const points = [
352
+ { id: "l1", vector: randomVector(), metadata: { name: "lance1" } },
353
+ { id: "l2", vector: randomVector(), metadata: { name: "lance2" } },
354
+ ];
355
+ await collection.insert(points);
356
+ const results = await collection.query(randomVector(), { limit: 2 });
357
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
358
+ });
359
+ (0, vitest_1.it)("should use search() method", async () => {
360
+ try {
361
+ await collection.deleteCollection();
362
+ }
363
+ catch (e) { }
364
+ await collection.create(TEST_DIMENSION, "cosine");
365
+ const points = [
366
+ { id: "l3", vector: randomVector(), metadata: { name: "lance3" } },
367
+ ];
368
+ await collection.insert(points);
369
+ const results = await collection.search(randomVector(), 1, null, true, false);
370
+ (0, vitest_1.expect)(results.results.length).toBeGreaterThanOrEqual(1);
371
+ });
372
+ });