@wiscale/velesdb-wasm 1.12.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
@@ -8,7 +8,6 @@ WebAssembly build of [VelesDB](https://github.com/cyberlife-coder/VelesDB) - vec
8
8
  ## Features
9
9
 
10
10
  - **In-browser vector search** - No server required
11
- - **SIMD optimized** - Uses WASM SIMD128 for fast distance calculations
12
11
  - **Multiple metrics** - Cosine, Euclidean, Dot Product, Hamming, Jaccard
13
12
  - **Memory optimization** - SQ8 (4x) and Binary (32x) quantization
14
13
  - **Knowledge Graph** - In-memory graph store with BFS/DFS traversal
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "Julien Lange <contact@wiscale.fr>"
6
6
  ],
7
7
  "description": "VelesDB for WebAssembly - Vector search in the browser",
8
- "version": "1.12.0",
8
+ "version": "1.13.0",
9
9
  "license": "MIT",
10
10
  "repository": {
11
11
  "type": "git",
package/velesdb_wasm.d.ts CHANGED
@@ -282,17 +282,20 @@ export class GraphStore {
282
282
  }
283
283
 
284
284
  /**
285
- * Configuration for Web Worker traversal decisions.
285
+ * Thresholds used by [`should_use_worker`] to recommend Web Worker offload.
286
+ *
287
+ * This is a data-only configuration object. It does not allocate or start
288
+ * a Worker — the caller remains responsible for Worker lifecycle.
286
289
  */
287
290
  export class GraphWorkerConfig {
288
291
  free(): void;
289
292
  [Symbol.dispose](): void;
290
293
  /**
291
- * Creates a configuration optimized for large graphs.
294
+ * Returns thresholds tuned for large graphs.
292
295
  */
293
296
  static for_large_graphs(): GraphWorkerConfig;
294
297
  /**
295
- * Creates a configuration optimized for responsive UI.
298
+ * Returns thresholds tuned for UI responsiveness on smaller graphs.
296
299
  */
297
300
  static for_responsive_ui(): GraphWorkerConfig;
298
301
  /**
@@ -300,21 +303,19 @@ export class GraphWorkerConfig {
300
303
  */
301
304
  constructor();
302
305
  /**
303
- * Minimum depth to trigger worker offload.
306
+ * Minimum traversal depth at which offload is recommended.
304
307
  */
305
308
  depth_threshold: number;
306
309
  /**
307
- * Minimum node count to trigger worker offload.
310
+ * Minimum node count at which offload is recommended.
308
311
  */
309
312
  node_threshold: number;
310
313
  /**
311
- * Progress callback interval in milliseconds.
314
+ * Suggested progress callback interval in milliseconds for the
315
+ * caller's own worker implementation. This crate does not emit
316
+ * progress events on its own.
312
317
  */
313
318
  progress_interval_ms: number;
314
- /**
315
- * Whether to use `SharedArrayBuffer` for result transfer (if available).
316
- */
317
- use_shared_buffer: boolean;
318
319
  }
319
320
 
320
321
  /**
@@ -333,7 +334,17 @@ export class ParsedQuery {
333
334
  */
334
335
  readonly collectionName: string | undefined;
335
336
  /**
336
- * Get the list of selected columns as JSON array.
337
+ * Get the list of selected columns one entry per SELECT-list item.
338
+ *
339
+ * Returns a JSON array with every item in the SELECT list, in grammar
340
+ * order: regular columns, aggregate calls, `similarity()` expressions,
341
+ * qualified wildcards (`alias.*`), and window functions. `SELECT *`
342
+ * returns `["*"]`.
343
+ *
344
+ * Note (v1.13.0 contract completion): versions prior to v1.13.0
345
+ * silently omitted `similarity()` expressions and qualified wildcards
346
+ * from this list for mixed SELECT statements. The full list is now
347
+ * returned. Callers that hard-coded the shorter length must update.
337
348
  */
338
349
  readonly columns: any;
339
350
  /**
@@ -448,6 +459,99 @@ export class ParsedQuery {
448
459
  readonly tableName: string | undefined;
449
460
  }
450
461
 
462
+ /**
463
+ * Result of executing a VelesQL query via
464
+ * [`WasmDatabase::execute_query`](crate::WasmDatabase).
465
+ *
466
+ * Getters expose the payload to JavaScript:
467
+ * - [`kind`](Self::kind) — statement class (`"rows"`, `"mutation"`, ...)
468
+ * - [`row_count`](Self::row_count) — number of rows in the result
469
+ * - [`message`](Self::message) — human-readable status message
470
+ * - [`row`](Self::row) / [`rows_json`](Self::rows_json) — row accessors
471
+ *
472
+ * # Row count semantics (Devin Review Finding F13)
473
+ *
474
+ * For row-returning statements (`SELECT`, `SHOW`, `DESCRIBE`, `SELECT
475
+ * EDGES`, `MATCH`) `row_count()` is `rows.len()` and `rows_json()`
476
+ * materialises every row.
477
+ *
478
+ * For row-affecting statements (`INSERT`, `UPSERT`, `UPDATE`, `DELETE`,
479
+ * graph mutations) `row_count()` returns an explicit `mutation_count`
480
+ * field and `rows_json()` is the empty array. Previously the executor
481
+ * allocated N placeholder rows (`{"id":0,"score":0.0}`) so that
482
+ * `rows.len()` matched the affected-row count — O(n) allocation for
483
+ * zero information content, plus a misleading JSON payload.
484
+ */
485
+ export class QueryResult {
486
+ private constructor();
487
+ free(): void;
488
+ [Symbol.dispose](): void;
489
+ /**
490
+ * Row at the given index, or `undefined` when out of range.
491
+ *
492
+ * Transfers ownership to JavaScript — do not reuse the same index.
493
+ */
494
+ row(index: number): QueryResultRow | undefined;
495
+ /**
496
+ * Statement class, as a stable string.
497
+ *
498
+ * One of: `"rows"`, `"mutation"`, `"deletion"`, `"ddl"`, `"train"`,
499
+ * `"admin"`. Callers can branch on this to decide how to interpret
500
+ * [`rows_json`](Self::rows_json).
501
+ */
502
+ readonly kind: string;
503
+ /**
504
+ * Human-readable status message (for display / logging).
505
+ */
506
+ readonly message: string;
507
+ /**
508
+ * Number of rows affected or returned (`0` for DDL / admin / empty).
509
+ *
510
+ * For mutation statements the value comes from the explicit
511
+ * `mutation_count` field (set by `from_mutation`). For everything
512
+ * else it equals `rows.len()`. See the struct-level docs for the
513
+ * rationale behind the dual accounting (Finding F13).
514
+ */
515
+ readonly rowCount: number;
516
+ /**
517
+ * All rows as a single JSON array string.
518
+ *
519
+ * Each element is the row's `dataJson` object. Prefer this over
520
+ * iterating with [`row`](Self::row) when the caller wants a single
521
+ * `JSON.parse` call per query.
522
+ */
523
+ readonly rowsJson: string;
524
+ }
525
+
526
+ /**
527
+ * A single row returned by [`WasmDatabase::execute_query`](crate::WasmDatabase).
528
+ *
529
+ * The full row (id, score, and all payload fields merged at top level) is
530
+ * serialized as a JSON object string in [`QueryResultRow::data_json`]. This
531
+ * matches the Mobile bindings contract and lets the JavaScript caller do a
532
+ * single `JSON.parse()` per row.
533
+ */
534
+ export class QueryResultRow {
535
+ private constructor();
536
+ free(): void;
537
+ [Symbol.dispose](): void;
538
+ /**
539
+ * Full row content as a JSON object string.
540
+ *
541
+ * Always contains at least `id` and `score`; all payload fields are
542
+ * merged at the top level (excluding shadowing of `id`/`score`).
543
+ */
544
+ readonly dataJson: string;
545
+ /**
546
+ * Point ID (0 for non-point results such as `SHOW COLLECTIONS`).
547
+ */
548
+ readonly id: bigint;
549
+ /**
550
+ * Similarity / relevance score (0.0 when no vector search ran).
551
+ */
552
+ readonly score: number;
553
+ }
554
+
451
555
  /**
452
556
  * Semantic Memory for AI agents in WASM.
453
557
  *
@@ -631,7 +735,16 @@ export class VectorStore {
631
735
  */
632
736
  batch_search(vectors: Float32Array, num_vectors: number, k: number): any;
633
737
  /**
634
- * Clears all vectors from the store.
738
+ * Clears all vectors, payloads, and auxiliary indexes from the
739
+ * store in place.
740
+ *
741
+ * Preserves `dimension`, `metric`, and `storage_mode` so the store
742
+ * can be re-populated without reallocation. Any sparse index is
743
+ * dropped: it would otherwise reference rows that no longer exist.
744
+ *
745
+ * Used by `TRUNCATE` (Devin Review Finding F12) so that outstanding
746
+ * `WasmCollectionHandle`s holding an `Rc` to this store observe the
747
+ * wipe atomically instead of pointing to a stale clone.
635
748
  */
636
749
  clear(): void;
637
750
  /**
@@ -735,6 +848,21 @@ export class VectorStore {
735
848
  * Searches with metadata filtering. Returns [{id, score, payload}].
736
849
  */
737
850
  search_with_filter(query: Float32Array, k: number, filter: any): any;
851
+ /**
852
+ * k-NN search with a named quality mode (API parity with Server/Python/Mobile).
853
+ *
854
+ * Accepts the same quality strings as the Python and Server SDKs:
855
+ * `"fast"`, `"balanced"`, `"accurate"`, `"perfect"`, `"autotune"`,
856
+ * `"custom:<ef>"`, `"adaptive:<min_ef>:<max_ef>"`.
857
+ *
858
+ * **WASM note**: The current WASM VectorStore uses brute-force O(n)
859
+ * search (no HNSW graph), so all quality modes produce identical results.
860
+ * The quality parameter is parsed and validated for API parity and
861
+ * forward-compatibility with future HNSW-backed WASM stores.
862
+ *
863
+ * Returns `[[id, score], ...]` sorted by relevance.
864
+ */
865
+ search_with_quality(query: Float32Array, k: number, quality: string): any;
738
866
  /**
739
867
  * Similarity search with threshold. Operators: >, >=, <, <=, =, !=.
740
868
  */
@@ -817,6 +945,179 @@ export class VelesQL {
817
945
  static parse(query: string): ParsedQuery;
818
946
  }
819
947
 
948
+ /**
949
+ * A handle to a [`VectorStore`] managed by a [`WasmDatabase`].
950
+ *
951
+ * Operations on this handle mutate the shared collection. Multiple handles
952
+ * to the same collection are valid (single-threaded WASM — no data races).
953
+ *
954
+ * # Lifetime across DDL (Devin Review Finding F12)
955
+ *
956
+ * | Operation | Effect on outstanding handles |
957
+ * |------------|-----------------------------------------------------------|
958
+ * | `TRUNCATE` | Handle keeps pointing to the same (now-emptied) store. |
959
+ * | `DROP` | Handle retains its `Rc` to the OLD store, detached from |
960
+ * | | the database. A later `CREATE` with the same name creates |
961
+ * | | a NEW store that the old handle does not see. |
962
+ * | `CREATE` | Fresh handles obtained via `get_collection` are required |
963
+ * | | to observe the new store when reusing a dropped name. |
964
+ */
965
+ export class WasmCollectionHandle {
966
+ private constructor();
967
+ free(): void;
968
+ [Symbol.dispose](): void;
969
+ /**
970
+ * Inserts a vector with the given ID.
971
+ *
972
+ * # Errors
973
+ * Returns an error if the vector dimension does not match the collection.
974
+ */
975
+ insert(id: bigint, vector: Float32Array): void;
976
+ /**
977
+ * Removes a vector by ID. Returns `true` if found.
978
+ */
979
+ remove(id: bigint): boolean;
980
+ /**
981
+ * k-NN search. Returns `[[id, score], ...]`.
982
+ *
983
+ * # Errors
984
+ * Returns an error if the query dimension does not match the collection.
985
+ */
986
+ search(query: Float32Array, k: number): any;
987
+ /**
988
+ * Returns the vector dimensionality.
989
+ */
990
+ readonly dimension: number;
991
+ /**
992
+ * Returns `true` if the collection has no vectors.
993
+ */
994
+ readonly is_empty: boolean;
995
+ /**
996
+ * Returns the number of vectors in the collection.
997
+ */
998
+ readonly len: number;
999
+ }
1000
+
1001
+ /**
1002
+ * An in-memory database that manages named [`VectorStore`] collections.
1003
+ *
1004
+ * # JavaScript usage
1005
+ *
1006
+ * ```javascript
1007
+ * const db = new WasmDatabase();
1008
+ * db.create_collection("docs", 768, "cosine");
1009
+ * const coll = db.get_collection("docs");
1010
+ * coll.insert(1n, new Float32Array([...]));
1011
+ * const results = coll.search(new Float32Array([...]), 10);
1012
+ * db.delete_collection("docs");
1013
+ * ```
1014
+ */
1015
+ export class WasmDatabase {
1016
+ free(): void;
1017
+ [Symbol.dispose](): void;
1018
+ /**
1019
+ * Creates a metadata-only collection (no vectors, only payloads).
1020
+ *
1021
+ * A metadata-only collection accepts `INSERT`/`UPDATE`/`DELETE` via
1022
+ * `execute_query()` without requiring a `vector` column, making it the
1023
+ * ideal target for reference data, lookup tables, or auxiliary metadata.
1024
+ *
1025
+ * # Errors
1026
+ * Returns an error if the collection already exists.
1027
+ */
1028
+ createMetadataCollection(name: string): void;
1029
+ /**
1030
+ * Creates a named collection.
1031
+ *
1032
+ * # Arguments
1033
+ * * `name` — unique collection name
1034
+ * * `dimension` — vector dimensionality (e.g. 768)
1035
+ * * `metric` — distance metric: `"cosine"`, `"euclidean"`, `"dot"`, etc.
1036
+ *
1037
+ * # Errors
1038
+ * Returns an error if the collection already exists or the metric is
1039
+ * invalid.
1040
+ */
1041
+ create_collection(name: string, dimension: number, metric: string): void;
1042
+ /**
1043
+ * Deletes a named collection and frees its memory.
1044
+ *
1045
+ * # Handle semantics
1046
+ *
1047
+ * Any [`WasmCollectionHandle`] previously obtained via
1048
+ * [`get_collection`](Self::get_collection) keeps its own `Rc` to the
1049
+ * backing store — mechanically the data is NOT freed on the spot.
1050
+ * The handle continues to reference the *old* store, detached from
1051
+ * the database. A subsequent `CREATE COLLECTION` with the same name
1052
+ * allocates a **new** store, distinct from the old handle's data.
1053
+ *
1054
+ * Callers that want handles to observe later mutations should re-
1055
+ * obtain a fresh handle after any CREATE. Note that `TRUNCATE`
1056
+ * clears in place (see Devin Review Finding F12), so outstanding
1057
+ * handles DO see the wipe — only DROP detaches.
1058
+ *
1059
+ * # Errors
1060
+ * Returns an error if the collection does not exist.
1061
+ */
1062
+ delete_collection(name: string): void;
1063
+ /**
1064
+ * Executes a VelesQL statement against this database.
1065
+ *
1066
+ * Supports SELECT, INSERT / UPSERT, UPDATE, DELETE, DDL (CREATE / DROP /
1067
+ * TRUNCATE COLLECTION), introspection (SHOW COLLECTIONS, DESCRIBE
1068
+ * COLLECTION), and admin (FLUSH as no-op). Unsupported surfaces such as
1069
+ * MATCH, TRAIN QUANTIZER, FUSION clauses, compound queries and graph
1070
+ * DML return a descriptive error instead of crashing. See the
1071
+ * [`velesql_exec`](crate::velesql_exec) module rustdoc for the full
1072
+ * statement matrix.
1073
+ *
1074
+ * # Parameters
1075
+ * * `sql` — VelesQL query string.
1076
+ * * `params_json` — Optional JSON object with query parameters (keys
1077
+ * are bare names; use `$name` syntax in SQL). Pass `null` or `"{}"`
1078
+ * when no parameters are needed.
1079
+ *
1080
+ * # Example (JavaScript)
1081
+ * ```javascript
1082
+ * const db = new WasmDatabase();
1083
+ * db.createMetadataCollection("docs");
1084
+ * const r = db.executeQuery(
1085
+ * "INSERT INTO docs (id, title) VALUES (1, 'hello')",
1086
+ * null
1087
+ * );
1088
+ * console.log(r.kind, r.rowCount, r.rowsJson);
1089
+ * ```
1090
+ *
1091
+ * # Errors
1092
+ * Returns a `JsValue` error string when parsing fails, parameters are
1093
+ * invalid, the target collection does not exist, or the statement uses
1094
+ * a feature that WASM does not support.
1095
+ */
1096
+ executeQuery(sql: string, params_json?: string | null): QueryResult;
1097
+ /**
1098
+ * Returns a mutable handle to an existing collection.
1099
+ *
1100
+ * The returned [`WasmCollectionHandle`] shares state with the database —
1101
+ * inserts and deletions through the handle are visible in the database.
1102
+ *
1103
+ * # Errors
1104
+ * Returns an error if the collection does not exist.
1105
+ */
1106
+ get_collection(name: string): WasmCollectionHandle;
1107
+ /**
1108
+ * Lists all collection names as a JavaScript `Array<string>`.
1109
+ */
1110
+ list_collections(): any;
1111
+ /**
1112
+ * Creates an empty database with no collections.
1113
+ */
1114
+ constructor();
1115
+ /**
1116
+ * Returns the number of managed collections.
1117
+ */
1118
+ readonly collection_count: number;
1119
+ }
1120
+
820
1121
  /**
821
1122
  * Estimates the number of nodes that will be visited during traversal.
822
1123
  *
@@ -853,23 +1154,28 @@ export interface InitOutput {
853
1154
  readonly __wbg_get_graphworkerconfig_depth_threshold: (a: number) => number;
854
1155
  readonly __wbg_get_graphworkerconfig_node_threshold: (a: number) => number;
855
1156
  readonly __wbg_get_graphworkerconfig_progress_interval_ms: (a: number) => number;
856
- readonly __wbg_get_graphworkerconfig_use_shared_buffer: (a: number) => number;
857
1157
  readonly __wbg_get_traversalprogress_is_cancelled: (a: number) => number;
1158
+ readonly __wbg_get_traversalprogress_is_complete: (a: number) => number;
858
1159
  readonly __wbg_graphedge_free: (a: number, b: number) => void;
859
1160
  readonly __wbg_graphnode_free: (a: number, b: number) => void;
860
1161
  readonly __wbg_graphpersistence_free: (a: number, b: number) => void;
861
1162
  readonly __wbg_graphstore_free: (a: number, b: number) => void;
862
1163
  readonly __wbg_graphworkerconfig_free: (a: number, b: number) => void;
863
1164
  readonly __wbg_parsedquery_free: (a: number, b: number) => void;
1165
+ readonly __wbg_queryresult_free: (a: number, b: number) => void;
1166
+ readonly __wbg_queryresultrow_free: (a: number, b: number) => void;
864
1167
  readonly __wbg_semanticmemory_free: (a: number, b: number) => void;
865
1168
  readonly __wbg_set_graphworkerconfig_depth_threshold: (a: number, b: number) => void;
866
1169
  readonly __wbg_set_graphworkerconfig_node_threshold: (a: number, b: number) => void;
867
1170
  readonly __wbg_set_graphworkerconfig_progress_interval_ms: (a: number, b: number) => void;
868
- readonly __wbg_set_graphworkerconfig_use_shared_buffer: (a: number, b: number) => void;
869
1171
  readonly __wbg_set_traversalprogress_is_cancelled: (a: number, b: number) => void;
1172
+ readonly __wbg_set_traversalprogress_is_complete: (a: number, b: number) => void;
870
1173
  readonly __wbg_sparseindex_free: (a: number, b: number) => void;
1174
+ readonly __wbg_traversalprogress_free: (a: number, b: number) => void;
871
1175
  readonly __wbg_vectorstore_free: (a: number, b: number) => void;
872
1176
  readonly __wbg_velesql_free: (a: number, b: number) => void;
1177
+ readonly __wbg_wasmcollectionhandle_free: (a: number, b: number) => void;
1178
+ readonly __wbg_wasmdatabase_free: (a: number, b: number) => void;
873
1179
  readonly estimate_traversal_size: (a: number, b: number, c: number) => number;
874
1180
  readonly graphedge_id: (a: number) => bigint;
875
1181
  readonly graphedge_label: (a: number, b: number) => void;
@@ -950,6 +1256,14 @@ export interface InitOutput {
950
1256
  readonly parsedquery_matchReturnItems: (a: number) => number;
951
1257
  readonly parsedquery_offset: (a: number, b: number) => void;
952
1258
  readonly parsedquery_orderBy: (a: number) => number;
1259
+ readonly queryresult_kind: (a: number, b: number) => void;
1260
+ readonly queryresult_message: (a: number, b: number) => void;
1261
+ readonly queryresult_row: (a: number, b: number) => number;
1262
+ readonly queryresult_rowCount: (a: number) => number;
1263
+ readonly queryresult_rowsJson: (a: number, b: number) => void;
1264
+ readonly queryresultrow_dataJson: (a: number, b: number) => void;
1265
+ readonly queryresultrow_id: (a: number) => bigint;
1266
+ readonly queryresultrow_score: (a: number) => number;
953
1267
  readonly semanticmemory_clear: (a: number) => void;
954
1268
  readonly semanticmemory_dimension: (a: number) => number;
955
1269
  readonly semanticmemory_is_empty: (a: number) => number;
@@ -992,6 +1306,7 @@ export interface InitOutput {
992
1306
  readonly vectorstore_save: (a: number, b: number, c: number) => number;
993
1307
  readonly vectorstore_search: (a: number, b: number, c: number, d: number, e: number) => void;
994
1308
  readonly vectorstore_search_with_filter: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1309
+ readonly vectorstore_search_with_quality: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
995
1310
  readonly vectorstore_similarity_search: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
996
1311
  readonly vectorstore_sparse_insert: (a: number, b: number, c: bigint, d: number, e: number, f: number, g: number) => void;
997
1312
  readonly vectorstore_sparse_search: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
@@ -1000,7 +1315,19 @@ export interface InitOutput {
1000
1315
  readonly vectorstore_with_capacity: (a: number, b: number, c: number, d: number, e: number) => void;
1001
1316
  readonly velesql_isValid: (a: number, b: number) => number;
1002
1317
  readonly velesql_parse: (a: number, b: number, c: number) => void;
1003
- readonly __wbg_set_traversalprogress_is_complete: (a: number, b: number) => void;
1318
+ readonly wasmcollectionhandle_dimension: (a: number) => number;
1319
+ readonly wasmcollectionhandle_insert: (a: number, b: number, c: bigint, d: number, e: number) => void;
1320
+ readonly wasmcollectionhandle_is_empty: (a: number) => number;
1321
+ readonly wasmcollectionhandle_len: (a: number) => number;
1322
+ readonly wasmcollectionhandle_remove: (a: number, b: bigint) => number;
1323
+ readonly wasmcollectionhandle_search: (a: number, b: number, c: number, d: number, e: number) => void;
1324
+ readonly wasmdatabase_createMetadataCollection: (a: number, b: number, c: number, d: number) => void;
1325
+ readonly wasmdatabase_create_collection: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
1326
+ readonly wasmdatabase_delete_collection: (a: number, b: number, c: number, d: number) => void;
1327
+ readonly wasmdatabase_executeQuery: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
1328
+ readonly wasmdatabase_get_collection: (a: number, b: number, c: number, d: number) => void;
1329
+ readonly wasmdatabase_list_collections: (a: number) => number;
1330
+ readonly wasmdatabase_new: () => number;
1004
1331
  readonly __wbg_set_traversalprogress_current_depth: (a: number, b: number) => void;
1005
1332
  readonly __wbg_set_traversalprogress_estimated_total: (a: number, b: number) => void;
1006
1333
  readonly __wbg_set_traversalprogress_visited_count: (a: number, b: number) => void;
@@ -1008,14 +1335,13 @@ export interface InitOutput {
1008
1335
  readonly __wbg_get_traversalprogress_estimated_total: (a: number) => number;
1009
1336
  readonly __wbg_get_traversalprogress_visited_count: (a: number) => number;
1010
1337
  readonly graphnode_id: (a: number) => bigint;
1338
+ readonly wasmdatabase_collection_count: (a: number) => number;
1011
1339
  readonly parsedquery_tableName: (a: number, b: number) => void;
1012
- readonly __wbg_get_traversalprogress_is_complete: (a: number) => number;
1013
- readonly __wbg_traversalprogress_free: (a: number, b: number) => void;
1014
- readonly __wasm_bindgen_func_elem_1234: (a: number, b: number) => void;
1015
- readonly __wasm_bindgen_func_elem_287: (a: number, b: number) => void;
1016
- readonly __wasm_bindgen_func_elem_1235: (a: number, b: number, c: number, d: number) => void;
1017
- readonly __wasm_bindgen_func_elem_1477: (a: number, b: number, c: number, d: number) => void;
1018
- readonly __wasm_bindgen_func_elem_288: (a: number, b: number, c: number) => void;
1340
+ readonly __wasm_bindgen_func_elem_1653: (a: number, b: number) => void;
1341
+ readonly __wasm_bindgen_func_elem_396: (a: number, b: number) => void;
1342
+ readonly __wasm_bindgen_func_elem_1654: (a: number, b: number, c: number, d: number) => void;
1343
+ readonly __wasm_bindgen_func_elem_1896: (a: number, b: number, c: number, d: number) => void;
1344
+ readonly __wasm_bindgen_func_elem_397: (a: number, b: number, c: number) => void;
1019
1345
  readonly __wbindgen_export: (a: number, b: number) => number;
1020
1346
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
1021
1347
  readonly __wbindgen_export3: (a: number) => void;
package/velesdb_wasm.js CHANGED
@@ -757,7 +757,10 @@ export class GraphStore {
757
757
  if (Symbol.dispose) GraphStore.prototype[Symbol.dispose] = GraphStore.prototype.free;
758
758
 
759
759
  /**
760
- * Configuration for Web Worker traversal decisions.
760
+ * Thresholds used by [`should_use_worker`] to recommend Web Worker offload.
761
+ *
762
+ * This is a data-only configuration object. It does not allocate or start
763
+ * a Worker — the caller remains responsible for Worker lifecycle.
761
764
  */
762
765
  export class GraphWorkerConfig {
763
766
  static __wrap(ptr) {
@@ -778,7 +781,7 @@ export class GraphWorkerConfig {
778
781
  wasm.__wbg_graphworkerconfig_free(ptr, 0);
779
782
  }
780
783
  /**
781
- * Minimum depth to trigger worker offload.
784
+ * Minimum traversal depth at which offload is recommended.
782
785
  * @returns {number}
783
786
  */
784
787
  get depth_threshold() {
@@ -786,7 +789,7 @@ export class GraphWorkerConfig {
786
789
  return ret >>> 0;
787
790
  }
788
791
  /**
789
- * Minimum node count to trigger worker offload.
792
+ * Minimum node count at which offload is recommended.
790
793
  * @returns {number}
791
794
  */
792
795
  get node_threshold() {
@@ -794,7 +797,9 @@ export class GraphWorkerConfig {
794
797
  return ret >>> 0;
795
798
  }
796
799
  /**
797
- * Progress callback interval in milliseconds.
800
+ * Suggested progress callback interval in milliseconds for the
801
+ * caller's own worker implementation. This crate does not emit
802
+ * progress events on its own.
798
803
  * @returns {number}
799
804
  */
800
805
  get progress_interval_ms() {
@@ -802,15 +807,7 @@ export class GraphWorkerConfig {
802
807
  return ret >>> 0;
803
808
  }
804
809
  /**
805
- * Whether to use `SharedArrayBuffer` for result transfer (if available).
806
- * @returns {boolean}
807
- */
808
- get use_shared_buffer() {
809
- const ret = wasm.__wbg_get_graphworkerconfig_use_shared_buffer(this.__wbg_ptr);
810
- return ret !== 0;
811
- }
812
- /**
813
- * Creates a configuration optimized for large graphs.
810
+ * Returns thresholds tuned for large graphs.
814
811
  * @returns {GraphWorkerConfig}
815
812
  */
816
813
  static for_large_graphs() {
@@ -818,7 +815,7 @@ export class GraphWorkerConfig {
818
815
  return GraphWorkerConfig.__wrap(ret);
819
816
  }
820
817
  /**
821
- * Creates a configuration optimized for responsive UI.
818
+ * Returns thresholds tuned for UI responsiveness on smaller graphs.
822
819
  * @returns {GraphWorkerConfig}
823
820
  */
824
821
  static for_responsive_ui() {
@@ -835,33 +832,28 @@ export class GraphWorkerConfig {
835
832
  return this;
836
833
  }
837
834
  /**
838
- * Minimum depth to trigger worker offload.
835
+ * Minimum traversal depth at which offload is recommended.
839
836
  * @param {number} arg0
840
837
  */
841
838
  set depth_threshold(arg0) {
842
839
  wasm.__wbg_set_graphworkerconfig_depth_threshold(this.__wbg_ptr, arg0);
843
840
  }
844
841
  /**
845
- * Minimum node count to trigger worker offload.
842
+ * Minimum node count at which offload is recommended.
846
843
  * @param {number} arg0
847
844
  */
848
845
  set node_threshold(arg0) {
849
846
  wasm.__wbg_set_graphworkerconfig_node_threshold(this.__wbg_ptr, arg0);
850
847
  }
851
848
  /**
852
- * Progress callback interval in milliseconds.
849
+ * Suggested progress callback interval in milliseconds for the
850
+ * caller's own worker implementation. This crate does not emit
851
+ * progress events on its own.
853
852
  * @param {number} arg0
854
853
  */
855
854
  set progress_interval_ms(arg0) {
856
855
  wasm.__wbg_set_graphworkerconfig_progress_interval_ms(this.__wbg_ptr, arg0);
857
856
  }
858
- /**
859
- * Whether to use `SharedArrayBuffer` for result transfer (if available).
860
- * @param {boolean} arg0
861
- */
862
- set use_shared_buffer(arg0) {
863
- wasm.__wbg_set_graphworkerconfig_use_shared_buffer(this.__wbg_ptr, arg0);
864
- }
865
857
  }
866
858
  if (Symbol.dispose) GraphWorkerConfig.prototype[Symbol.dispose] = GraphWorkerConfig.prototype.free;
867
859
 
@@ -911,7 +903,17 @@ export class ParsedQuery {
911
903
  }
912
904
  }
913
905
  /**
914
- * Get the list of selected columns as JSON array.
906
+ * Get the list of selected columns one entry per SELECT-list item.
907
+ *
908
+ * Returns a JSON array with every item in the SELECT list, in grammar
909
+ * order: regular columns, aggregate calls, `similarity()` expressions,
910
+ * qualified wildcards (`alias.*`), and window functions. `SELECT *`
911
+ * returns `["*"]`.
912
+ *
913
+ * Note (v1.13.0 contract completion): versions prior to v1.13.0
914
+ * silently omitted `similarity()` expressions and qualified wildcards
915
+ * from this list for mixed SELECT statements. The full list is now
916
+ * returned. Callers that hard-coded the shorter length must update.
915
917
  * @returns {any}
916
918
  */
917
919
  get columns() {
@@ -1172,6 +1174,210 @@ export class ParsedQuery {
1172
1174
  }
1173
1175
  if (Symbol.dispose) ParsedQuery.prototype[Symbol.dispose] = ParsedQuery.prototype.free;
1174
1176
 
1177
+ /**
1178
+ * Result of executing a VelesQL query via
1179
+ * [`WasmDatabase::execute_query`](crate::WasmDatabase).
1180
+ *
1181
+ * Getters expose the payload to JavaScript:
1182
+ * - [`kind`](Self::kind) — statement class (`"rows"`, `"mutation"`, ...)
1183
+ * - [`row_count`](Self::row_count) — number of rows in the result
1184
+ * - [`message`](Self::message) — human-readable status message
1185
+ * - [`row`](Self::row) / [`rows_json`](Self::rows_json) — row accessors
1186
+ *
1187
+ * # Row count semantics (Devin Review Finding F13)
1188
+ *
1189
+ * For row-returning statements (`SELECT`, `SHOW`, `DESCRIBE`, `SELECT
1190
+ * EDGES`, `MATCH`) `row_count()` is `rows.len()` and `rows_json()`
1191
+ * materialises every row.
1192
+ *
1193
+ * For row-affecting statements (`INSERT`, `UPSERT`, `UPDATE`, `DELETE`,
1194
+ * graph mutations) `row_count()` returns an explicit `mutation_count`
1195
+ * field and `rows_json()` is the empty array. Previously the executor
1196
+ * allocated N placeholder rows (`{"id":0,"score":0.0}`) so that
1197
+ * `rows.len()` matched the affected-row count — O(n) allocation for
1198
+ * zero information content, plus a misleading JSON payload.
1199
+ */
1200
+ export class QueryResult {
1201
+ static __wrap(ptr) {
1202
+ ptr = ptr >>> 0;
1203
+ const obj = Object.create(QueryResult.prototype);
1204
+ obj.__wbg_ptr = ptr;
1205
+ QueryResultFinalization.register(obj, obj.__wbg_ptr, obj);
1206
+ return obj;
1207
+ }
1208
+ __destroy_into_raw() {
1209
+ const ptr = this.__wbg_ptr;
1210
+ this.__wbg_ptr = 0;
1211
+ QueryResultFinalization.unregister(this);
1212
+ return ptr;
1213
+ }
1214
+ free() {
1215
+ const ptr = this.__destroy_into_raw();
1216
+ wasm.__wbg_queryresult_free(ptr, 0);
1217
+ }
1218
+ /**
1219
+ * Statement class, as a stable string.
1220
+ *
1221
+ * One of: `"rows"`, `"mutation"`, `"deletion"`, `"ddl"`, `"train"`,
1222
+ * `"admin"`. Callers can branch on this to decide how to interpret
1223
+ * [`rows_json`](Self::rows_json).
1224
+ * @returns {string}
1225
+ */
1226
+ get kind() {
1227
+ let deferred1_0;
1228
+ let deferred1_1;
1229
+ try {
1230
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1231
+ wasm.queryresult_kind(retptr, this.__wbg_ptr);
1232
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1233
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1234
+ deferred1_0 = r0;
1235
+ deferred1_1 = r1;
1236
+ return getStringFromWasm0(r0, r1);
1237
+ } finally {
1238
+ wasm.__wbindgen_add_to_stack_pointer(16);
1239
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
1240
+ }
1241
+ }
1242
+ /**
1243
+ * Human-readable status message (for display / logging).
1244
+ * @returns {string}
1245
+ */
1246
+ get message() {
1247
+ let deferred1_0;
1248
+ let deferred1_1;
1249
+ try {
1250
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1251
+ wasm.queryresult_message(retptr, this.__wbg_ptr);
1252
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1253
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1254
+ deferred1_0 = r0;
1255
+ deferred1_1 = r1;
1256
+ return getStringFromWasm0(r0, r1);
1257
+ } finally {
1258
+ wasm.__wbindgen_add_to_stack_pointer(16);
1259
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
1260
+ }
1261
+ }
1262
+ /**
1263
+ * Row at the given index, or `undefined` when out of range.
1264
+ *
1265
+ * Transfers ownership to JavaScript — do not reuse the same index.
1266
+ * @param {number} index
1267
+ * @returns {QueryResultRow | undefined}
1268
+ */
1269
+ row(index) {
1270
+ const ret = wasm.queryresult_row(this.__wbg_ptr, index);
1271
+ return ret === 0 ? undefined : QueryResultRow.__wrap(ret);
1272
+ }
1273
+ /**
1274
+ * Number of rows affected or returned (`0` for DDL / admin / empty).
1275
+ *
1276
+ * For mutation statements the value comes from the explicit
1277
+ * `mutation_count` field (set by `from_mutation`). For everything
1278
+ * else it equals `rows.len()`. See the struct-level docs for the
1279
+ * rationale behind the dual accounting (Finding F13).
1280
+ * @returns {number}
1281
+ */
1282
+ get rowCount() {
1283
+ const ret = wasm.queryresult_rowCount(this.__wbg_ptr);
1284
+ return ret >>> 0;
1285
+ }
1286
+ /**
1287
+ * All rows as a single JSON array string.
1288
+ *
1289
+ * Each element is the row's `dataJson` object. Prefer this over
1290
+ * iterating with [`row`](Self::row) when the caller wants a single
1291
+ * `JSON.parse` call per query.
1292
+ * @returns {string}
1293
+ */
1294
+ get rowsJson() {
1295
+ let deferred1_0;
1296
+ let deferred1_1;
1297
+ try {
1298
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1299
+ wasm.queryresult_rowsJson(retptr, this.__wbg_ptr);
1300
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1301
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1302
+ deferred1_0 = r0;
1303
+ deferred1_1 = r1;
1304
+ return getStringFromWasm0(r0, r1);
1305
+ } finally {
1306
+ wasm.__wbindgen_add_to_stack_pointer(16);
1307
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
1308
+ }
1309
+ }
1310
+ }
1311
+ if (Symbol.dispose) QueryResult.prototype[Symbol.dispose] = QueryResult.prototype.free;
1312
+
1313
+ /**
1314
+ * A single row returned by [`WasmDatabase::execute_query`](crate::WasmDatabase).
1315
+ *
1316
+ * The full row (id, score, and all payload fields merged at top level) is
1317
+ * serialized as a JSON object string in [`QueryResultRow::data_json`]. This
1318
+ * matches the Mobile bindings contract and lets the JavaScript caller do a
1319
+ * single `JSON.parse()` per row.
1320
+ */
1321
+ export class QueryResultRow {
1322
+ static __wrap(ptr) {
1323
+ ptr = ptr >>> 0;
1324
+ const obj = Object.create(QueryResultRow.prototype);
1325
+ obj.__wbg_ptr = ptr;
1326
+ QueryResultRowFinalization.register(obj, obj.__wbg_ptr, obj);
1327
+ return obj;
1328
+ }
1329
+ __destroy_into_raw() {
1330
+ const ptr = this.__wbg_ptr;
1331
+ this.__wbg_ptr = 0;
1332
+ QueryResultRowFinalization.unregister(this);
1333
+ return ptr;
1334
+ }
1335
+ free() {
1336
+ const ptr = this.__destroy_into_raw();
1337
+ wasm.__wbg_queryresultrow_free(ptr, 0);
1338
+ }
1339
+ /**
1340
+ * Full row content as a JSON object string.
1341
+ *
1342
+ * Always contains at least `id` and `score`; all payload fields are
1343
+ * merged at the top level (excluding shadowing of `id`/`score`).
1344
+ * @returns {string}
1345
+ */
1346
+ get dataJson() {
1347
+ let deferred1_0;
1348
+ let deferred1_1;
1349
+ try {
1350
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1351
+ wasm.queryresultrow_dataJson(retptr, this.__wbg_ptr);
1352
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1353
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1354
+ deferred1_0 = r0;
1355
+ deferred1_1 = r1;
1356
+ return getStringFromWasm0(r0, r1);
1357
+ } finally {
1358
+ wasm.__wbindgen_add_to_stack_pointer(16);
1359
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
1360
+ }
1361
+ }
1362
+ /**
1363
+ * Point ID (0 for non-point results such as `SHOW COLLECTIONS`).
1364
+ * @returns {bigint}
1365
+ */
1366
+ get id() {
1367
+ const ret = wasm.queryresultrow_id(this.__wbg_ptr);
1368
+ return BigInt.asUintN(64, ret);
1369
+ }
1370
+ /**
1371
+ * Similarity / relevance score (0.0 when no vector search ran).
1372
+ * @returns {number}
1373
+ */
1374
+ get score() {
1375
+ const ret = wasm.queryresultrow_score(this.__wbg_ptr);
1376
+ return ret;
1377
+ }
1378
+ }
1379
+ if (Symbol.dispose) QueryResultRow.prototype[Symbol.dispose] = QueryResultRow.prototype.free;
1380
+
1175
1381
  /**
1176
1382
  * Semantic Memory for AI agents in WASM.
1177
1383
  *
@@ -1624,7 +1830,16 @@ export class VectorStore {
1624
1830
  }
1625
1831
  }
1626
1832
  /**
1627
- * Clears all vectors from the store.
1833
+ * Clears all vectors, payloads, and auxiliary indexes from the
1834
+ * store in place.
1835
+ *
1836
+ * Preserves `dimension`, `metric`, and `storage_mode` so the store
1837
+ * can be re-populated without reallocation. Any sparse index is
1838
+ * dropped: it would otherwise reference rows that no longer exist.
1839
+ *
1840
+ * Used by `TRUNCATE` (Devin Review Finding F12) so that outstanding
1841
+ * `WasmCollectionHandle`s holding an `Rc` to this store observe the
1842
+ * wipe atomically instead of pointing to a stale clone.
1628
1843
  */
1629
1844
  clear() {
1630
1845
  wasm.vectorstore_clear(this.__wbg_ptr);
@@ -2044,6 +2259,43 @@ export class VectorStore {
2044
2259
  wasm.__wbindgen_add_to_stack_pointer(16);
2045
2260
  }
2046
2261
  }
2262
+ /**
2263
+ * k-NN search with a named quality mode (API parity with Server/Python/Mobile).
2264
+ *
2265
+ * Accepts the same quality strings as the Python and Server SDKs:
2266
+ * `"fast"`, `"balanced"`, `"accurate"`, `"perfect"`, `"autotune"`,
2267
+ * `"custom:<ef>"`, `"adaptive:<min_ef>:<max_ef>"`.
2268
+ *
2269
+ * **WASM note**: The current WASM VectorStore uses brute-force O(n)
2270
+ * search (no HNSW graph), so all quality modes produce identical results.
2271
+ * The quality parameter is parsed and validated for API parity and
2272
+ * forward-compatibility with future HNSW-backed WASM stores.
2273
+ *
2274
+ * Returns `[[id, score], ...]` sorted by relevance.
2275
+ * @param {Float32Array} query
2276
+ * @param {number} k
2277
+ * @param {string} quality
2278
+ * @returns {any}
2279
+ */
2280
+ search_with_quality(query, k, quality) {
2281
+ try {
2282
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2283
+ const ptr0 = passArrayF32ToWasm0(query, wasm.__wbindgen_export);
2284
+ const len0 = WASM_VECTOR_LEN;
2285
+ const ptr1 = passStringToWasm0(quality, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2286
+ const len1 = WASM_VECTOR_LEN;
2287
+ wasm.vectorstore_search_with_quality(retptr, this.__wbg_ptr, ptr0, len0, k, ptr1, len1);
2288
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2289
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2290
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
2291
+ if (r2) {
2292
+ throw takeObject(r1);
2293
+ }
2294
+ return takeObject(r0);
2295
+ } finally {
2296
+ wasm.__wbindgen_add_to_stack_pointer(16);
2297
+ }
2298
+ }
2047
2299
  /**
2048
2300
  * Similarity search with threshold. Operators: >, >=, <, <=, =, !=.
2049
2301
  * @param {Float32Array} query
@@ -2266,6 +2518,356 @@ export class VelesQL {
2266
2518
  }
2267
2519
  if (Symbol.dispose) VelesQL.prototype[Symbol.dispose] = VelesQL.prototype.free;
2268
2520
 
2521
+ /**
2522
+ * A handle to a [`VectorStore`] managed by a [`WasmDatabase`].
2523
+ *
2524
+ * Operations on this handle mutate the shared collection. Multiple handles
2525
+ * to the same collection are valid (single-threaded WASM — no data races).
2526
+ *
2527
+ * # Lifetime across DDL (Devin Review Finding F12)
2528
+ *
2529
+ * | Operation | Effect on outstanding handles |
2530
+ * |------------|-----------------------------------------------------------|
2531
+ * | `TRUNCATE` | Handle keeps pointing to the same (now-emptied) store. |
2532
+ * | `DROP` | Handle retains its `Rc` to the OLD store, detached from |
2533
+ * | | the database. A later `CREATE` with the same name creates |
2534
+ * | | a NEW store that the old handle does not see. |
2535
+ * | `CREATE` | Fresh handles obtained via `get_collection` are required |
2536
+ * | | to observe the new store when reusing a dropped name. |
2537
+ */
2538
+ export class WasmCollectionHandle {
2539
+ static __wrap(ptr) {
2540
+ ptr = ptr >>> 0;
2541
+ const obj = Object.create(WasmCollectionHandle.prototype);
2542
+ obj.__wbg_ptr = ptr;
2543
+ WasmCollectionHandleFinalization.register(obj, obj.__wbg_ptr, obj);
2544
+ return obj;
2545
+ }
2546
+ __destroy_into_raw() {
2547
+ const ptr = this.__wbg_ptr;
2548
+ this.__wbg_ptr = 0;
2549
+ WasmCollectionHandleFinalization.unregister(this);
2550
+ return ptr;
2551
+ }
2552
+ free() {
2553
+ const ptr = this.__destroy_into_raw();
2554
+ wasm.__wbg_wasmcollectionhandle_free(ptr, 0);
2555
+ }
2556
+ /**
2557
+ * Returns the vector dimensionality.
2558
+ * @returns {number}
2559
+ */
2560
+ get dimension() {
2561
+ const ret = wasm.wasmcollectionhandle_dimension(this.__wbg_ptr);
2562
+ return ret >>> 0;
2563
+ }
2564
+ /**
2565
+ * Inserts a vector with the given ID.
2566
+ *
2567
+ * # Errors
2568
+ * Returns an error if the vector dimension does not match the collection.
2569
+ * @param {bigint} id
2570
+ * @param {Float32Array} vector
2571
+ */
2572
+ insert(id, vector) {
2573
+ try {
2574
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2575
+ const ptr0 = passArrayF32ToWasm0(vector, wasm.__wbindgen_export);
2576
+ const len0 = WASM_VECTOR_LEN;
2577
+ wasm.wasmcollectionhandle_insert(retptr, this.__wbg_ptr, id, ptr0, len0);
2578
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2579
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2580
+ if (r1) {
2581
+ throw takeObject(r0);
2582
+ }
2583
+ } finally {
2584
+ wasm.__wbindgen_add_to_stack_pointer(16);
2585
+ }
2586
+ }
2587
+ /**
2588
+ * Returns `true` if the collection has no vectors.
2589
+ * @returns {boolean}
2590
+ */
2591
+ get is_empty() {
2592
+ const ret = wasm.wasmcollectionhandle_is_empty(this.__wbg_ptr);
2593
+ return ret !== 0;
2594
+ }
2595
+ /**
2596
+ * Returns the number of vectors in the collection.
2597
+ * @returns {number}
2598
+ */
2599
+ get len() {
2600
+ const ret = wasm.wasmcollectionhandle_len(this.__wbg_ptr);
2601
+ return ret >>> 0;
2602
+ }
2603
+ /**
2604
+ * Removes a vector by ID. Returns `true` if found.
2605
+ * @param {bigint} id
2606
+ * @returns {boolean}
2607
+ */
2608
+ remove(id) {
2609
+ const ret = wasm.wasmcollectionhandle_remove(this.__wbg_ptr, id);
2610
+ return ret !== 0;
2611
+ }
2612
+ /**
2613
+ * k-NN search. Returns `[[id, score], ...]`.
2614
+ *
2615
+ * # Errors
2616
+ * Returns an error if the query dimension does not match the collection.
2617
+ * @param {Float32Array} query
2618
+ * @param {number} k
2619
+ * @returns {any}
2620
+ */
2621
+ search(query, k) {
2622
+ try {
2623
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2624
+ const ptr0 = passArrayF32ToWasm0(query, wasm.__wbindgen_export);
2625
+ const len0 = WASM_VECTOR_LEN;
2626
+ wasm.wasmcollectionhandle_search(retptr, this.__wbg_ptr, ptr0, len0, k);
2627
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2628
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2629
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
2630
+ if (r2) {
2631
+ throw takeObject(r1);
2632
+ }
2633
+ return takeObject(r0);
2634
+ } finally {
2635
+ wasm.__wbindgen_add_to_stack_pointer(16);
2636
+ }
2637
+ }
2638
+ }
2639
+ if (Symbol.dispose) WasmCollectionHandle.prototype[Symbol.dispose] = WasmCollectionHandle.prototype.free;
2640
+
2641
+ /**
2642
+ * An in-memory database that manages named [`VectorStore`] collections.
2643
+ *
2644
+ * # JavaScript usage
2645
+ *
2646
+ * ```javascript
2647
+ * const db = new WasmDatabase();
2648
+ * db.create_collection("docs", 768, "cosine");
2649
+ * const coll = db.get_collection("docs");
2650
+ * coll.insert(1n, new Float32Array([...]));
2651
+ * const results = coll.search(new Float32Array([...]), 10);
2652
+ * db.delete_collection("docs");
2653
+ * ```
2654
+ */
2655
+ export class WasmDatabase {
2656
+ __destroy_into_raw() {
2657
+ const ptr = this.__wbg_ptr;
2658
+ this.__wbg_ptr = 0;
2659
+ WasmDatabaseFinalization.unregister(this);
2660
+ return ptr;
2661
+ }
2662
+ free() {
2663
+ const ptr = this.__destroy_into_raw();
2664
+ wasm.__wbg_wasmdatabase_free(ptr, 0);
2665
+ }
2666
+ /**
2667
+ * Returns the number of managed collections.
2668
+ * @returns {number}
2669
+ */
2670
+ get collection_count() {
2671
+ const ret = wasm.wasmdatabase_collection_count(this.__wbg_ptr);
2672
+ return ret >>> 0;
2673
+ }
2674
+ /**
2675
+ * Creates a metadata-only collection (no vectors, only payloads).
2676
+ *
2677
+ * A metadata-only collection accepts `INSERT`/`UPDATE`/`DELETE` via
2678
+ * `execute_query()` without requiring a `vector` column, making it the
2679
+ * ideal target for reference data, lookup tables, or auxiliary metadata.
2680
+ *
2681
+ * # Errors
2682
+ * Returns an error if the collection already exists.
2683
+ * @param {string} name
2684
+ */
2685
+ createMetadataCollection(name) {
2686
+ try {
2687
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2688
+ const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2689
+ const len0 = WASM_VECTOR_LEN;
2690
+ wasm.wasmdatabase_createMetadataCollection(retptr, this.__wbg_ptr, ptr0, len0);
2691
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2692
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2693
+ if (r1) {
2694
+ throw takeObject(r0);
2695
+ }
2696
+ } finally {
2697
+ wasm.__wbindgen_add_to_stack_pointer(16);
2698
+ }
2699
+ }
2700
+ /**
2701
+ * Creates a named collection.
2702
+ *
2703
+ * # Arguments
2704
+ * * `name` — unique collection name
2705
+ * * `dimension` — vector dimensionality (e.g. 768)
2706
+ * * `metric` — distance metric: `"cosine"`, `"euclidean"`, `"dot"`, etc.
2707
+ *
2708
+ * # Errors
2709
+ * Returns an error if the collection already exists or the metric is
2710
+ * invalid.
2711
+ * @param {string} name
2712
+ * @param {number} dimension
2713
+ * @param {string} metric
2714
+ */
2715
+ create_collection(name, dimension, metric) {
2716
+ try {
2717
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2718
+ const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2719
+ const len0 = WASM_VECTOR_LEN;
2720
+ const ptr1 = passStringToWasm0(metric, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2721
+ const len1 = WASM_VECTOR_LEN;
2722
+ wasm.wasmdatabase_create_collection(retptr, this.__wbg_ptr, ptr0, len0, dimension, ptr1, len1);
2723
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2724
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2725
+ if (r1) {
2726
+ throw takeObject(r0);
2727
+ }
2728
+ } finally {
2729
+ wasm.__wbindgen_add_to_stack_pointer(16);
2730
+ }
2731
+ }
2732
+ /**
2733
+ * Deletes a named collection and frees its memory.
2734
+ *
2735
+ * # Handle semantics
2736
+ *
2737
+ * Any [`WasmCollectionHandle`] previously obtained via
2738
+ * [`get_collection`](Self::get_collection) keeps its own `Rc` to the
2739
+ * backing store — mechanically the data is NOT freed on the spot.
2740
+ * The handle continues to reference the *old* store, detached from
2741
+ * the database. A subsequent `CREATE COLLECTION` with the same name
2742
+ * allocates a **new** store, distinct from the old handle's data.
2743
+ *
2744
+ * Callers that want handles to observe later mutations should re-
2745
+ * obtain a fresh handle after any CREATE. Note that `TRUNCATE`
2746
+ * clears in place (see Devin Review Finding F12), so outstanding
2747
+ * handles DO see the wipe — only DROP detaches.
2748
+ *
2749
+ * # Errors
2750
+ * Returns an error if the collection does not exist.
2751
+ * @param {string} name
2752
+ */
2753
+ delete_collection(name) {
2754
+ try {
2755
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2756
+ const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2757
+ const len0 = WASM_VECTOR_LEN;
2758
+ wasm.wasmdatabase_delete_collection(retptr, this.__wbg_ptr, ptr0, len0);
2759
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2760
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2761
+ if (r1) {
2762
+ throw takeObject(r0);
2763
+ }
2764
+ } finally {
2765
+ wasm.__wbindgen_add_to_stack_pointer(16);
2766
+ }
2767
+ }
2768
+ /**
2769
+ * Executes a VelesQL statement against this database.
2770
+ *
2771
+ * Supports SELECT, INSERT / UPSERT, UPDATE, DELETE, DDL (CREATE / DROP /
2772
+ * TRUNCATE COLLECTION), introspection (SHOW COLLECTIONS, DESCRIBE
2773
+ * COLLECTION), and admin (FLUSH as no-op). Unsupported surfaces such as
2774
+ * MATCH, TRAIN QUANTIZER, FUSION clauses, compound queries and graph
2775
+ * DML return a descriptive error instead of crashing. See the
2776
+ * [`velesql_exec`](crate::velesql_exec) module rustdoc for the full
2777
+ * statement matrix.
2778
+ *
2779
+ * # Parameters
2780
+ * * `sql` — VelesQL query string.
2781
+ * * `params_json` — Optional JSON object with query parameters (keys
2782
+ * are bare names; use `$name` syntax in SQL). Pass `null` or `"{}"`
2783
+ * when no parameters are needed.
2784
+ *
2785
+ * # Example (JavaScript)
2786
+ * ```javascript
2787
+ * const db = new WasmDatabase();
2788
+ * db.createMetadataCollection("docs");
2789
+ * const r = db.executeQuery(
2790
+ * "INSERT INTO docs (id, title) VALUES (1, 'hello')",
2791
+ * null
2792
+ * );
2793
+ * console.log(r.kind, r.rowCount, r.rowsJson);
2794
+ * ```
2795
+ *
2796
+ * # Errors
2797
+ * Returns a `JsValue` error string when parsing fails, parameters are
2798
+ * invalid, the target collection does not exist, or the statement uses
2799
+ * a feature that WASM does not support.
2800
+ * @param {string} sql
2801
+ * @param {string | null} [params_json]
2802
+ * @returns {QueryResult}
2803
+ */
2804
+ executeQuery(sql, params_json) {
2805
+ try {
2806
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2807
+ const ptr0 = passStringToWasm0(sql, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2808
+ const len0 = WASM_VECTOR_LEN;
2809
+ var ptr1 = isLikeNone(params_json) ? 0 : passStringToWasm0(params_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2810
+ var len1 = WASM_VECTOR_LEN;
2811
+ wasm.wasmdatabase_executeQuery(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
2812
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2813
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2814
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
2815
+ if (r2) {
2816
+ throw takeObject(r1);
2817
+ }
2818
+ return QueryResult.__wrap(r0);
2819
+ } finally {
2820
+ wasm.__wbindgen_add_to_stack_pointer(16);
2821
+ }
2822
+ }
2823
+ /**
2824
+ * Returns a mutable handle to an existing collection.
2825
+ *
2826
+ * The returned [`WasmCollectionHandle`] shares state with the database —
2827
+ * inserts and deletions through the handle are visible in the database.
2828
+ *
2829
+ * # Errors
2830
+ * Returns an error if the collection does not exist.
2831
+ * @param {string} name
2832
+ * @returns {WasmCollectionHandle}
2833
+ */
2834
+ get_collection(name) {
2835
+ try {
2836
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2837
+ const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2);
2838
+ const len0 = WASM_VECTOR_LEN;
2839
+ wasm.wasmdatabase_get_collection(retptr, this.__wbg_ptr, ptr0, len0);
2840
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2841
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2842
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
2843
+ if (r2) {
2844
+ throw takeObject(r1);
2845
+ }
2846
+ return WasmCollectionHandle.__wrap(r0);
2847
+ } finally {
2848
+ wasm.__wbindgen_add_to_stack_pointer(16);
2849
+ }
2850
+ }
2851
+ /**
2852
+ * Lists all collection names as a JavaScript `Array<string>`.
2853
+ * @returns {any}
2854
+ */
2855
+ list_collections() {
2856
+ const ret = wasm.wasmdatabase_list_collections(this.__wbg_ptr);
2857
+ return takeObject(ret);
2858
+ }
2859
+ /**
2860
+ * Creates an empty database with no collections.
2861
+ */
2862
+ constructor() {
2863
+ const ret = wasm.wasmdatabase_new();
2864
+ this.__wbg_ptr = ret >>> 0;
2865
+ WasmDatabaseFinalization.register(this, this.__wbg_ptr, this);
2866
+ return this;
2867
+ }
2868
+ }
2869
+ if (Symbol.dispose) WasmDatabase.prototype[Symbol.dispose] = WasmDatabase.prototype.free;
2870
+
2269
2871
  /**
2270
2872
  * Estimates the number of nodes that will be visited during traversal.
2271
2873
  *
@@ -2599,7 +3201,7 @@ function __wbg_get_imports() {
2599
3201
  const a = state0.a;
2600
3202
  state0.a = 0;
2601
3203
  try {
2602
- return __wasm_bindgen_func_elem_1477(a, state0.b, arg0, arg1);
3204
+ return __wasm_bindgen_func_elem_1896(a, state0.b, arg0, arg1);
2603
3205
  } finally {
2604
3206
  state0.a = a;
2605
3207
  }
@@ -2621,7 +3223,7 @@ function __wbg_get_imports() {
2621
3223
  const a = state0.a;
2622
3224
  state0.a = 0;
2623
3225
  try {
2624
- return __wasm_bindgen_func_elem_1477(a, state0.b, arg0, arg1);
3226
+ return __wasm_bindgen_func_elem_1896(a, state0.b, arg0, arg1);
2625
3227
  } finally {
2626
3228
  state0.a = a;
2627
3229
  }
@@ -2754,13 +3356,13 @@ function __wbg_get_imports() {
2754
3356
  return addHeapObject(ret);
2755
3357
  },
2756
3358
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
2757
- // Cast intrinsic for `Closure(Closure { dtor_idx: 144, function: Function { arguments: [Externref], shim_idx: 145, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
2758
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_1234, __wasm_bindgen_func_elem_1235);
3359
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 332, function: Function { arguments: [Externref], shim_idx: 333, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
3360
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_1653, __wasm_bindgen_func_elem_1654);
2759
3361
  return addHeapObject(ret);
2760
3362
  },
2761
3363
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
2762
- // Cast intrinsic for `Closure(Closure { dtor_idx: 5, function: Function { arguments: [NamedExternref("Event")], shim_idx: 6, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
2763
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_287, __wasm_bindgen_func_elem_288);
3364
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 7, function: Function { arguments: [NamedExternref("Event")], shim_idx: 8, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3365
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_396, __wasm_bindgen_func_elem_397);
2764
3366
  return addHeapObject(ret);
2765
3367
  },
2766
3368
  __wbindgen_cast_0000000000000003: function(arg0) {
@@ -2797,14 +3399,14 @@ function __wbg_get_imports() {
2797
3399
  };
2798
3400
  }
2799
3401
 
2800
- function __wasm_bindgen_func_elem_288(arg0, arg1, arg2) {
2801
- wasm.__wasm_bindgen_func_elem_288(arg0, arg1, addHeapObject(arg2));
3402
+ function __wasm_bindgen_func_elem_397(arg0, arg1, arg2) {
3403
+ wasm.__wasm_bindgen_func_elem_397(arg0, arg1, addHeapObject(arg2));
2802
3404
  }
2803
3405
 
2804
- function __wasm_bindgen_func_elem_1235(arg0, arg1, arg2) {
3406
+ function __wasm_bindgen_func_elem_1654(arg0, arg1, arg2) {
2805
3407
  try {
2806
3408
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2807
- wasm.__wasm_bindgen_func_elem_1235(retptr, arg0, arg1, addHeapObject(arg2));
3409
+ wasm.__wasm_bindgen_func_elem_1654(retptr, arg0, arg1, addHeapObject(arg2));
2808
3410
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
2809
3411
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
2810
3412
  if (r1) {
@@ -2815,8 +3417,8 @@ function __wasm_bindgen_func_elem_1235(arg0, arg1, arg2) {
2815
3417
  }
2816
3418
  }
2817
3419
 
2818
- function __wasm_bindgen_func_elem_1477(arg0, arg1, arg2, arg3) {
2819
- wasm.__wasm_bindgen_func_elem_1477(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
3420
+ function __wasm_bindgen_func_elem_1896(arg0, arg1, arg2, arg3) {
3421
+ wasm.__wasm_bindgen_func_elem_1896(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
2820
3422
  }
2821
3423
 
2822
3424
 
@@ -2839,6 +3441,12 @@ const GraphWorkerConfigFinalization = (typeof FinalizationRegistry === 'undefine
2839
3441
  const ParsedQueryFinalization = (typeof FinalizationRegistry === 'undefined')
2840
3442
  ? { register: () => {}, unregister: () => {} }
2841
3443
  : new FinalizationRegistry(ptr => wasm.__wbg_parsedquery_free(ptr >>> 0, 1));
3444
+ const QueryResultFinalization = (typeof FinalizationRegistry === 'undefined')
3445
+ ? { register: () => {}, unregister: () => {} }
3446
+ : new FinalizationRegistry(ptr => wasm.__wbg_queryresult_free(ptr >>> 0, 1));
3447
+ const QueryResultRowFinalization = (typeof FinalizationRegistry === 'undefined')
3448
+ ? { register: () => {}, unregister: () => {} }
3449
+ : new FinalizationRegistry(ptr => wasm.__wbg_queryresultrow_free(ptr >>> 0, 1));
2842
3450
  const SemanticMemoryFinalization = (typeof FinalizationRegistry === 'undefined')
2843
3451
  ? { register: () => {}, unregister: () => {} }
2844
3452
  : new FinalizationRegistry(ptr => wasm.__wbg_semanticmemory_free(ptr >>> 0, 1));
@@ -2854,6 +3462,12 @@ const VectorStoreFinalization = (typeof FinalizationRegistry === 'undefined')
2854
3462
  const VelesQLFinalization = (typeof FinalizationRegistry === 'undefined')
2855
3463
  ? { register: () => {}, unregister: () => {} }
2856
3464
  : new FinalizationRegistry(ptr => wasm.__wbg_velesql_free(ptr >>> 0, 1));
3465
+ const WasmCollectionHandleFinalization = (typeof FinalizationRegistry === 'undefined')
3466
+ ? { register: () => {}, unregister: () => {} }
3467
+ : new FinalizationRegistry(ptr => wasm.__wbg_wasmcollectionhandle_free(ptr >>> 0, 1));
3468
+ const WasmDatabaseFinalization = (typeof FinalizationRegistry === 'undefined')
3469
+ ? { register: () => {}, unregister: () => {} }
3470
+ : new FinalizationRegistry(ptr => wasm.__wbg_wasmdatabase_free(ptr >>> 0, 1));
2857
3471
 
2858
3472
  function addHeapObject(obj) {
2859
3473
  if (heap_next === heap.length) heap.push(heap.length + 1);
Binary file