@wiscale/velesdb-sdk 1.11.0 → 1.13.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 CHANGED
@@ -2,9 +2,32 @@
2
2
 
3
3
  Official TypeScript SDK for [VelesDB](https://github.com/cyberlife-coder/VelesDB) -- the local-first vector database for AI and RAG. Sub-millisecond semantic search in Browser and Node.js.
4
4
 
5
- **v1.11.0** | Node.js >= 18 | Browser (WASM) | MIT License
5
+ **v1.13.0** | Node.js >= 18 | Browser (WASM) | MIT License
6
6
 
7
- ## What's New in v1.11.0
7
+ ## What's New in v1.13.0
8
+
9
+ - **WASM VelesQL executor** -- full browser-side VelesQL execution: SELECT/INSERT/UPDATE/DELETE/DDL + aggregations (COUNT/SUM/AVG/MIN/MAX) + GROUP BY/HAVING/UNION/INTERSECT/EXCEPT/JOIN/FUSION/MATCH 1-2 hops + NOT De Morgan distribution
10
+ - **TS SDK coverage raised to 94%** -- 423 tests, per-file thresholds codified in `vitest.config.ts`
11
+ - **SIFT1M standardized ANN benchmark** -- fvecs/ivecs loader + Criterion ef sweep on the INRIA TEXMEX dataset, feature-gated behind `--features bench-sift1m`
12
+ - **Security hardening** -- `validateCollectionName()` helper on TS SDK prevents VelesQL injection in `trainPq`
13
+ - **API consistency** -- `streamInsert` now serializes `payload: null` explicitly (matches `streamUpsertPoints`)
14
+
15
+ ### Previous (v1.12.0)
16
+
17
+ - **Cross-collection MATCH queries** -- `@collection` annotation on MATCH node patterns enables cross-collection graph queries
18
+ - **MATCH via `/query` endpoint** -- MATCH queries can now be executed via `Database::execute_query`
19
+ - **BFS dedup** -- CSR and EdgeStore BFS no longer produce duplicate results for diamond graphs
20
+ - **`rrf_k` propagation** -- now properly propagated to `hybrid_search_with_filter`
21
+ - **`ComponentScores` optimization** -- changed to `&'static str` for zero-allocation score tagging
22
+
23
+ ### Previous (v1.11.1)
24
+
25
+ - **Graph API parity** -- 7 new REST endpoints for complete graph operations (delete edge, edge count, list nodes, node edges, node payload, parallel BFS, graph search)
26
+ - **Bitmap pre-filter** -- adaptive strategy selection for filtered search
27
+ - **CSR graph traversal v2** -- lock-free adjacency with edge IDs and labels
28
+ - **Bulk insert v2** -- DirectVectorWriter + AsyncIndexBuilder pipeline
29
+
30
+ ### Previous (v1.11.0)
8
31
 
9
32
  - **15 new VelesQL statements** -- SHOW COLLECTIONS, DESCRIBE, EXPLAIN, CREATE/DROP INDEX, ANALYZE, TRUNCATE, ALTER COLLECTION, FLUSH, multi-row INSERT, UPSERT, SELECT EDGES, INSERT NODE
10
33
  - **203 BDD E2E tests** -- comprehensive end-to-end test coverage for all VelesQL features
@@ -59,15 +82,15 @@ await db.createCollection('documents', {
59
82
  metric: 'cosine'
60
83
  });
61
84
 
62
- // 3. Insert vectors with metadata
63
- await db.insert('documents', {
85
+ // 3. Upsert vectors with metadata
86
+ await db.upsert('documents', {
64
87
  id: 'doc-1',
65
88
  vector: new Float32Array(768).fill(0.1),
66
89
  payload: { title: 'Hello World', category: 'greeting' }
67
90
  });
68
91
 
69
- // 4. Batch insert for better throughput
70
- await db.insertBatch('documents', [
92
+ // 4. Batch upsert for better throughput
93
+ await db.upsertBatch('documents', [
71
94
  { id: 'doc-2', vector: new Float32Array(768).fill(0.2), payload: { title: 'Second doc' } },
72
95
  { id: 'doc-3', vector: new Float32Array(768).fill(0.3), payload: { title: 'Third doc' } },
73
96
  ]);
@@ -98,12 +121,17 @@ await db.init();
98
121
 
99
122
  // Same API as WASM backend
100
123
  await db.createCollection('products', { dimension: 1536 });
101
- await db.insert('products', { id: 1, vector: embedding });
124
+ await db.upsert('products', { id: 1, vector: embedding });
102
125
  const results = await db.search('products', queryVector, { k: 10 });
103
126
  ```
104
127
 
105
128
  > **REST backend note:** Document IDs must be numeric integers in the range `0..Number.MAX_SAFE_INTEGER`. String IDs are only supported with the WASM backend.
106
129
 
130
+ > **Versioned routes:** The REST backend uses `/v1/` as the canonical route prefix
131
+ > (e.g. `POST /v1/collections/{name}/search`). Legacy routes without the prefix
132
+ > are accepted for backward compatibility but are deprecated and will be removed
133
+ > in a future major version. Always target `/v1/` in custom HTTP clients.
134
+
107
135
  ## API Reference
108
136
 
109
137
  ### Client
@@ -194,14 +222,14 @@ List all collections. Returns an array of `Collection` objects.
194
222
 
195
223
  ---
196
224
 
197
- ### Insert and Retrieve
225
+ ### Upsert and Retrieve
198
226
 
199
- #### `db.insert(collection, document)`
227
+ #### `db.upsert(collection, document)`
200
228
 
201
- Insert a single vector document.
229
+ Upsert (insert or replace) a single vector document.
202
230
 
203
231
  ```typescript
204
- await db.insert('docs', {
232
+ await db.upsert('docs', {
205
233
  id: 'unique-id',
206
234
  vector: [0.1, 0.2, 0.3], // number[] or Float32Array
207
235
  payload: { key: 'value' }, // optional metadata
@@ -209,12 +237,12 @@ await db.insert('docs', {
209
237
  });
210
238
  ```
211
239
 
212
- #### `db.insertBatch(collection, documents)`
240
+ #### `db.upsertBatch(collection, documents)`
213
241
 
214
- Insert multiple vectors in a single call. More efficient than repeated `insert()`.
242
+ Upsert multiple vectors in a single call. More efficient than repeated `upsert()`.
215
243
 
216
244
  ```typescript
217
- await db.insertBatch('docs', [
245
+ await db.upsertBatch('docs', [
218
246
  { id: 'a', vector: vecA, payload: { title: 'First' } },
219
247
  { id: 'b', vector: vecB, payload: { title: 'Second' } },
220
248
  ]);
@@ -282,6 +310,40 @@ const hits = await db.searchIds('docs', queryVector, { k: 100 });
282
310
  // Returns: Array<{ id: number, score: number }>
283
311
  ```
284
312
 
313
+ #### `db.scroll(collection, request)`
314
+
315
+ Iterate over all points in a collection in stable, paginated batches without a
316
+ query vector. Useful for export pipelines, re-embedding, and full-collection
317
+ inspection. Pagination is cursor-based — pass the `nextCursor` from each
318
+ `ScrollResponse` until it is `null`.
319
+
320
+ ```typescript
321
+ import { ScrollRequest, ScrollResponse } from '@wiscale/velesdb-sdk';
322
+
323
+ let cursor: string | number | null = null;
324
+ let hasMore = true;
325
+ while (hasMore) {
326
+ const req: ScrollRequest = { batchSize: 100 };
327
+ if (cursor !== null) {
328
+ req.cursor = cursor;
329
+ }
330
+
331
+ const page: ScrollResponse = await db.scroll('docs', req);
332
+
333
+ for (const point of page.points) {
334
+ console.log(point.id, point.payload);
335
+ }
336
+ cursor = page.nextCursor;
337
+ hasMore = cursor !== null;
338
+ }
339
+ ```
340
+
341
+ | Field (`ScrollRequest`) | Type | Default | Description |
342
+ |-------------------------|------|---------|-------------|
343
+ | `cursor` | `string \| number` | - | Cursor from previous `ScrollResponse.nextCursor` |
344
+ | `batchSize` | `number` | `100` | Points per page |
345
+ | `filter` | `object` | - | Optional payload filter expression |
346
+
285
347
  #### `db.textSearch(collection, query, options?)`
286
348
 
287
349
  Full-text search using BM25 scoring.
@@ -310,7 +372,7 @@ Multi-query fusion search for RAG pipelines using Multiple Query Generation (MQG
310
372
  | Option | Type | Default | Description |
311
373
  |--------|------|---------|-------------|
312
374
  | `k` | `number` | `10` | Number of results |
313
- | `fusion` | `'rrf' \| 'average' \| 'maximum' \| 'weighted'` | `'rrf'` | Fusion strategy |
375
+ | `fusion` | `'rrf' \| 'average' \| 'maximum' \| 'weighted' \| 'relative_score'` | `'rrf'` | Fusion strategy |
314
376
  | `fusionParams` | `object` | `{ k: 60 }` | Strategy-specific parameters |
315
377
  | `filter` | `object` | - | Payload filter expression |
316
378
 
@@ -328,9 +390,16 @@ const results = await db.multiQuerySearch('docs', [emb1, emb2], {
328
390
  fusion: 'weighted',
329
391
  fusionParams: { avgWeight: 0.6, maxWeight: 0.3, hitWeight: 0.1 }
330
392
  });
393
+
394
+ // Relative Score Fusion — linear blend of dense and sparse scores
395
+ const results = await db.multiQuerySearch('docs', [emb1, emb2], {
396
+ k: 10,
397
+ fusion: 'relative_score',
398
+ fusionParams: { denseWeight: 0.7, sparseWeight: 0.3 }
399
+ });
331
400
  ```
332
401
 
333
- > **Note:** WASM supports `rrf`, `average`, `maximum`. The `weighted` strategy is REST-only.
402
+ > **Note:** WASM supports `rrf`, `average`, `maximum`. The `weighted` and `relative_score` strategies are REST-only.
334
403
 
335
404
  ---
336
405
 
@@ -532,6 +601,23 @@ const degree = await db.getNodeDegree('social', 100);
532
601
  console.log(`In: ${degree.inDegree}, Out: ${degree.outDegree}`);
533
602
  ```
534
603
 
604
+ #### `db.traverseParallel(collection, request)`
605
+
606
+ Multi-source parallel BFS traversal with deduplication. Starts BFS from multiple source nodes simultaneously.
607
+
608
+ ```typescript
609
+ const result = await db.traverseParallel('social', {
610
+ sources: [100, 200, 300],
611
+ maxDepth: 3,
612
+ limit: 50,
613
+ relTypes: ['FOLLOWS']
614
+ });
615
+
616
+ for (const node of result.results) {
617
+ console.log(`Node ${node.targetId} at depth ${node.depth}`);
618
+ }
619
+ ```
620
+
535
621
  ---
536
622
 
537
623
  ### Property Indexes
@@ -724,7 +810,7 @@ import {
724
810
 
725
811
  ## Performance Tips
726
812
 
727
- 1. **Use `insertBatch()`** instead of repeated `insert()` calls
813
+ 1. **Use `upsertBatch()`** instead of repeated `upsert()` calls
728
814
  2. **Reuse `Float32Array`** buffers for query vectors when possible
729
815
  3. **Use WASM backend** for browser apps (zero network latency)
730
816
  4. **Use `searchIds()`** when you only need IDs and scores (skips payload transfer)