@taladb/web 0.8.3 → 0.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taladb/web",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "description": "TalaDB WASM bindings — document queries and vector search in the browser",
5
5
  "main": "pkg/taladb_web.js",
6
6
  "types": "pkg/taladb_web.d.ts",
@@ -19,7 +19,7 @@
19
19
  "repository": {
20
20
  "type": "git",
21
21
  "url": "https://github.com/thinkgrid-labs/taladb.git",
22
- "directory": "packages/taladb-web"
22
+ "directory": "packages/bindings/web"
23
23
  },
24
24
  "homepage": "https://thinkgrid-labs.github.io/taladb/guide/web",
25
25
  "bugs": {
package/pkg/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "thinkgrid-labs"
6
6
  ],
7
7
  "description": "TalaDB browser WASM bindings (wasm-bindgen + OPFS) and Cloudflare Workers",
8
- "version": "0.8.3",
8
+ "version": "0.9.0",
9
9
  "license": "MIT",
10
10
  "files": [
11
11
  "taladb_web_bg.wasm",
@@ -5,10 +5,19 @@ export class CollectionWasm {
5
5
  private constructor();
6
6
  free(): void;
7
7
  [Symbol.dispose](): void;
8
+ /**
9
+ * Run a MongoDB-style aggregation pipeline (`$match`, `$group`, `$sort`,
10
+ * `$skip`, `$limit`, `$project`). Returns the resulting documents.
11
+ */
12
+ aggregate(pipeline: any): any;
8
13
  /**
9
14
  * Count documents matching the filter.
10
15
  */
11
16
  count(filter: any): number;
17
+ /**
18
+ * Create a compound index. `fields_json` is a JSON array of field names.
19
+ */
20
+ createCompoundIndex(fields_json: string): void;
12
21
  /**
13
22
  * Create a secondary index on a field.
14
23
  */
@@ -31,6 +40,10 @@ export class CollectionWasm {
31
40
  * Delete the first matching document. Returns true if deleted.
32
41
  */
33
42
  deleteOne(filter: any): boolean;
43
+ /**
44
+ * Drop a compound index by its ordered field list (`fields_json`).
45
+ */
46
+ dropCompoundIndex(fields_json: string): void;
34
47
  /**
35
48
  * Drop a secondary index.
36
49
  */
@@ -86,6 +99,12 @@ export class TalaDBWasm {
86
99
  * Get a collection handle by name.
87
100
  */
88
101
  collection(name: string): CollectionWasm;
102
+ /**
103
+ * Export changes to `collections` after `sinceMs` (exclusive) as a JSON
104
+ * changeset string, for bidirectional sync. `sinceMs` is a millisecond
105
+ * epoch timestamp (the persisted sync cursor).
106
+ */
107
+ exportChanges(since_ms: number, collections: string[]): string;
89
108
  /**
90
109
  * Serialize the entire in-memory database to bytes.
91
110
  *
@@ -94,6 +113,16 @@ export class TalaDBWasm {
94
113
  * `openWithSnapshot` to restore all data.
95
114
  */
96
115
  exportSnapshot(): Uint8Array;
116
+ /**
117
+ * Merge a JSON changeset string (from a remote peer) into the local
118
+ * database via Last-Write-Wins. Returns the number of documents changed.
119
+ */
120
+ importChanges(changeset_json: string): number;
121
+ /**
122
+ * User collection names (reserved `_`-prefixed collections excluded).
123
+ * Backs the sync orchestration's "sync all collections" default.
124
+ */
125
+ listCollectionNames(): string[];
97
126
  /**
98
127
  * Open an in-memory database (suitable for tests and environments without OPFS).
99
128
  */
@@ -119,6 +148,10 @@ export class WorkerDB {
119
148
  private constructor();
120
149
  free(): void;
121
150
  [Symbol.dispose](): void;
151
+ /**
152
+ * Run an aggregation pipeline. Returns a JSON array of result documents.
153
+ */
154
+ aggregate(collection: string, pipeline_json: string): string;
122
155
  /**
123
156
  * Compact the underlying OPFS / redb storage file, reclaiming space freed
124
157
  * by deletes and updates.
@@ -149,6 +182,10 @@ export class WorkerDB {
149
182
  * Count matching documents.
150
183
  */
151
184
  count(collection: string, filter_json: string): number;
185
+ /**
186
+ * Create a compound index. `fields_json` is a JSON array of field names.
187
+ */
188
+ createCompoundIndex(collection: string, fields_json: string): void;
152
189
  createFtsIndex(collection: string, field: string): void;
153
190
  createIndex(collection: string, field: string): void;
154
191
  /**
@@ -168,6 +205,10 @@ export class WorkerDB {
168
205
  * Delete the first matching document. Returns `true` / `false`.
169
206
  */
170
207
  deleteOne(collection: string, filter_json: string): boolean;
208
+ /**
209
+ * Drop a compound index by its ordered field list (`fields_json`).
210
+ */
211
+ dropCompoundIndex(collection: string, fields_json: string): void;
171
212
  dropFtsIndex(collection: string, field: string): void;
172
213
  dropIndex(collection: string, field: string): void;
173
214
  /**
@@ -252,7 +293,7 @@ export class WorkerDB {
252
293
  * const db = WorkerDB.openWithConfigAndOpfs(handle, JSON.stringify(config));
253
294
  * ```
254
295
  */
255
- static openWithConfigAndOpfs(sync_handle: FileSystemSyncAccessHandle, config_json?: string | null): WorkerDB;
296
+ static openWithConfigAndOpfs(sync_handle: FileSystemSyncAccessHandle, config_json?: string | null, passphrase?: string | null, salt?: Uint8Array | null): WorkerDB;
256
297
  /**
257
298
  * Open a database from an optional snapshot with HTTP push sync config.
258
299
  *
@@ -287,6 +328,8 @@ export class WorkerDB {
287
328
  * ```
288
329
  */
289
330
  static openWithSnapshot(data?: Uint8Array | null): WorkerDB;
331
+ syncPending(): bigint;
332
+ syncStatus(): string;
290
333
  /**
291
334
  * Update all matching documents. Returns the count updated.
292
335
  */
@@ -358,14 +401,17 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
358
401
  export interface InitOutput {
359
402
  readonly memory: WebAssembly.Memory;
360
403
  readonly __wbg_workerdb_free: (a: number, b: number) => void;
404
+ readonly workerdb_aggregate: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
361
405
  readonly workerdb_compact: (a: number) => [number, number];
362
406
  readonly workerdb_compactTombstones: (a: number, b: number, c: number, d: number) => [number, number, number];
363
407
  readonly workerdb_count: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
408
+ readonly workerdb_createCompoundIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
364
409
  readonly workerdb_createFtsIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
365
410
  readonly workerdb_createIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
366
411
  readonly workerdb_createVectorIndex: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number) => [number, number];
367
412
  readonly workerdb_deleteMany: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
368
413
  readonly workerdb_deleteOne: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
414
+ readonly workerdb_dropCompoundIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
369
415
  readonly workerdb_dropFtsIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
370
416
  readonly workerdb_dropIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
371
417
  readonly workerdb_dropVectorIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
@@ -380,20 +426,25 @@ export interface InitOutput {
380
426
  readonly workerdb_listCollections: (a: number) => [number, number, number, number];
381
427
  readonly workerdb_listIndexes: (a: number, b: number, c: number) => [number, number, number, number];
382
428
  readonly workerdb_openInMemory: () => [number, number, number];
383
- readonly workerdb_openWithConfigAndOpfs: (a: any, b: number, c: number) => [number, number, number];
429
+ readonly workerdb_openWithConfigAndOpfs: (a: any, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
384
430
  readonly workerdb_openWithConfigAndSnapshot: (a: number, b: number, c: number, d: number) => [number, number, number];
385
431
  readonly workerdb_openWithOpfs: (a: any) => [number, number, number];
386
432
  readonly workerdb_openWithSnapshot: (a: number, b: number) => [number, number, number];
433
+ readonly workerdb_syncPending: (a: number) => bigint;
434
+ readonly workerdb_syncStatus: (a: number) => [number, number];
387
435
  readonly workerdb_updateMany: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
388
436
  readonly workerdb_updateOne: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
389
437
  readonly workerdb_upgradeVectorIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
390
438
  readonly __wbg_collectionwasm_free: (a: number, b: number) => void;
391
439
  readonly __wbg_taladbwasm_free: (a: number, b: number) => void;
440
+ readonly collectionwasm_aggregate: (a: number, b: any) => [number, number, number];
392
441
  readonly collectionwasm_count: (a: number, b: any) => [number, number, number];
442
+ readonly collectionwasm_createCompoundIndex: (a: number, b: number, c: number) => [number, number];
393
443
  readonly collectionwasm_createIndex: (a: number, b: number, c: number) => [number, number];
394
444
  readonly collectionwasm_createVectorIndex: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number];
395
445
  readonly collectionwasm_deleteMany: (a: number, b: any) => [number, number, number];
396
446
  readonly collectionwasm_deleteOne: (a: number, b: any) => [number, number, number];
447
+ readonly collectionwasm_dropCompoundIndex: (a: number, b: number, c: number) => [number, number];
397
448
  readonly collectionwasm_dropIndex: (a: number, b: number, c: number) => [number, number];
398
449
  readonly collectionwasm_dropVectorIndex: (a: number, b: number, c: number) => [number, number];
399
450
  readonly collectionwasm_find: (a: number, b: any) => [number, number, number];
@@ -405,24 +456,27 @@ export interface InitOutput {
405
456
  readonly collectionwasm_updateOne: (a: number, b: any, c: any) => [number, number, number];
406
457
  readonly collectionwasm_upgradeVectorIndex: (a: number, b: number, c: number) => [number, number];
407
458
  readonly taladbwasm_collection: (a: number, b: number, c: number) => [number, number, number];
459
+ readonly taladbwasm_exportChanges: (a: number, b: number, c: number, d: number) => [number, number, number, number];
408
460
  readonly taladbwasm_exportSnapshot: (a: number) => [number, number, number, number];
461
+ readonly taladbwasm_importChanges: (a: number, b: number, c: number) => [number, number, number];
462
+ readonly taladbwasm_listCollectionNames: (a: number) => [number, number, number, number];
409
463
  readonly taladbwasm_openInMemory: () => [number, number, number];
410
464
  readonly taladbwasm_openWithSnapshot: (a: number, b: number) => [number, number, number];
411
465
  readonly init: () => void;
466
+ readonly opfs_open_backend: (a: number, b: number) => any;
412
467
  readonly is_opfs_available: () => any;
413
468
  readonly opfs_delete_snapshot: (a: number, b: number) => any;
414
469
  readonly opfs_flush_snapshot: (a: number, b: number, c: number, d: number) => any;
415
470
  readonly opfs_load_snapshot: (a: number, b: number) => any;
416
471
  readonly idb_load_snapshot: (a: number, b: number) => any;
417
472
  readonly idb_save_snapshot: (a: number, b: number, c: number, d: number) => any;
418
- readonly opfs_open_backend: (a: number, b: number) => any;
419
- readonly wasm_bindgen__closure__destroy__h019ad81c65a5ac2e: (a: number, b: number) => void;
420
- readonly wasm_bindgen__closure__destroy__h53c506fd33a34156: (a: number, b: number) => void;
421
- readonly wasm_bindgen__closure__destroy__hc05d4761059c0df5: (a: number, b: number) => void;
422
- readonly wasm_bindgen__convert__closures_____invoke__hc8d470a46e185f12: (a: number, b: number, c: any) => [number, number];
423
- readonly wasm_bindgen__convert__closures_____invoke__h19185396894e5dfb: (a: number, b: number, c: any, d: any) => void;
424
- readonly wasm_bindgen__convert__closures_____invoke__h7b2d358a66567a58: (a: number, b: number, c: any) => void;
425
- readonly wasm_bindgen__convert__closures_____invoke__h88d126a9c69f3dfa: (a: number, b: number) => void;
473
+ readonly wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
474
+ readonly wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_60ce93de3f474933___JsValue____Output___core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___: (a: number, b: number) => void;
475
+ readonly wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_60ce93de3f474933___JsValue____Output_______: (a: number, b: number) => void;
476
+ readonly wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___true_: (a: number, b: number, c: any) => [number, number];
477
+ readonly wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
478
+ readonly wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue______true_: (a: number, b: number, c: any) => void;
479
+ readonly wasm_bindgen_60ce93de3f474933___convert__closures_____invoke_______true_: (a: number, b: number) => void;
426
480
  readonly __wbindgen_malloc: (a: number, b: number) => number;
427
481
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
428
482
  readonly __wbindgen_exn_store: (a: number) => void;
@@ -430,6 +484,7 @@ export interface InitOutput {
430
484
  readonly __wbindgen_externrefs: WebAssembly.Table;
431
485
  readonly __wbindgen_free: (a: number, b: number, c: number) => void;
432
486
  readonly __externref_table_dealloc: (a: number) => void;
487
+ readonly __externref_drop_slice: (a: number, b: number) => void;
433
488
  readonly __wbindgen_start: () => void;
434
489
  }
435
490
 
package/pkg/taladb_web.js CHANGED
@@ -18,6 +18,19 @@ export class CollectionWasm {
18
18
  const ptr = this.__destroy_into_raw();
19
19
  wasm.__wbg_collectionwasm_free(ptr, 0);
20
20
  }
21
+ /**
22
+ * Run a MongoDB-style aggregation pipeline (`$match`, `$group`, `$sort`,
23
+ * `$skip`, `$limit`, `$project`). Returns the resulting documents.
24
+ * @param {any} pipeline
25
+ * @returns {any}
26
+ */
27
+ aggregate(pipeline) {
28
+ const ret = wasm.collectionwasm_aggregate(this.__wbg_ptr, pipeline);
29
+ if (ret[2]) {
30
+ throw takeFromExternrefTable0(ret[1]);
31
+ }
32
+ return takeFromExternrefTable0(ret[0]);
33
+ }
21
34
  /**
22
35
  * Count documents matching the filter.
23
36
  * @param {any} filter
@@ -30,6 +43,18 @@ export class CollectionWasm {
30
43
  }
31
44
  return ret[0] >>> 0;
32
45
  }
46
+ /**
47
+ * Create a compound index. `fields_json` is a JSON array of field names.
48
+ * @param {string} fields_json
49
+ */
50
+ createCompoundIndex(fields_json) {
51
+ const ptr0 = passStringToWasm0(fields_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
52
+ const len0 = WASM_VECTOR_LEN;
53
+ const ret = wasm.collectionwasm_createCompoundIndex(this.__wbg_ptr, ptr0, len0);
54
+ if (ret[1]) {
55
+ throw takeFromExternrefTable0(ret[0]);
56
+ }
57
+ }
33
58
  /**
34
59
  * Create a secondary index on a field.
35
60
  * @param {string} field
@@ -93,6 +118,18 @@ export class CollectionWasm {
93
118
  }
94
119
  return ret[0] !== 0;
95
120
  }
121
+ /**
122
+ * Drop a compound index by its ordered field list (`fields_json`).
123
+ * @param {string} fields_json
124
+ */
125
+ dropCompoundIndex(fields_json) {
126
+ const ptr0 = passStringToWasm0(fields_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
127
+ const len0 = WASM_VECTOR_LEN;
128
+ const ret = wasm.collectionwasm_dropCompoundIndex(this.__wbg_ptr, ptr0, len0);
129
+ if (ret[1]) {
130
+ throw takeFromExternrefTable0(ret[0]);
131
+ }
132
+ }
96
133
  /**
97
134
  * Drop a secondary index.
98
135
  * @param {string} field
@@ -273,6 +310,34 @@ export class TalaDBWasm {
273
310
  }
274
311
  return CollectionWasm.__wrap(ret[0]);
275
312
  }
313
+ /**
314
+ * Export changes to `collections` after `sinceMs` (exclusive) as a JSON
315
+ * changeset string, for bidirectional sync. `sinceMs` is a millisecond
316
+ * epoch timestamp (the persisted sync cursor).
317
+ * @param {number} since_ms
318
+ * @param {string[]} collections
319
+ * @returns {string}
320
+ */
321
+ exportChanges(since_ms, collections) {
322
+ let deferred3_0;
323
+ let deferred3_1;
324
+ try {
325
+ const ptr0 = passArrayJsValueToWasm0(collections, wasm.__wbindgen_malloc);
326
+ const len0 = WASM_VECTOR_LEN;
327
+ const ret = wasm.taladbwasm_exportChanges(this.__wbg_ptr, since_ms, ptr0, len0);
328
+ var ptr2 = ret[0];
329
+ var len2 = ret[1];
330
+ if (ret[3]) {
331
+ ptr2 = 0; len2 = 0;
332
+ throw takeFromExternrefTable0(ret[2]);
333
+ }
334
+ deferred3_0 = ptr2;
335
+ deferred3_1 = len2;
336
+ return getStringFromWasm0(ptr2, len2);
337
+ } finally {
338
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
339
+ }
340
+ }
276
341
  /**
277
342
  * Serialize the entire in-memory database to bytes.
278
343
  *
@@ -290,6 +355,35 @@ export class TalaDBWasm {
290
355
  wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
291
356
  return v1;
292
357
  }
358
+ /**
359
+ * Merge a JSON changeset string (from a remote peer) into the local
360
+ * database via Last-Write-Wins. Returns the number of documents changed.
361
+ * @param {string} changeset_json
362
+ * @returns {number}
363
+ */
364
+ importChanges(changeset_json) {
365
+ const ptr0 = passStringToWasm0(changeset_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
366
+ const len0 = WASM_VECTOR_LEN;
367
+ const ret = wasm.taladbwasm_importChanges(this.__wbg_ptr, ptr0, len0);
368
+ if (ret[2]) {
369
+ throw takeFromExternrefTable0(ret[1]);
370
+ }
371
+ return ret[0] >>> 0;
372
+ }
373
+ /**
374
+ * User collection names (reserved `_`-prefixed collections excluded).
375
+ * Backs the sync orchestration's "sync all collections" default.
376
+ * @returns {string[]}
377
+ */
378
+ listCollectionNames() {
379
+ const ret = wasm.taladbwasm_listCollectionNames(this.__wbg_ptr);
380
+ if (ret[3]) {
381
+ throw takeFromExternrefTable0(ret[2]);
382
+ }
383
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]).slice();
384
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
385
+ return v1;
386
+ }
293
387
  /**
294
388
  * Open an in-memory database (suitable for tests and environments without OPFS).
295
389
  * @returns {TalaDBWasm}
@@ -347,6 +441,34 @@ export class WorkerDB {
347
441
  const ptr = this.__destroy_into_raw();
348
442
  wasm.__wbg_workerdb_free(ptr, 0);
349
443
  }
444
+ /**
445
+ * Run an aggregation pipeline. Returns a JSON array of result documents.
446
+ * @param {string} collection
447
+ * @param {string} pipeline_json
448
+ * @returns {string}
449
+ */
450
+ aggregate(collection, pipeline_json) {
451
+ let deferred4_0;
452
+ let deferred4_1;
453
+ try {
454
+ const ptr0 = passStringToWasm0(collection, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
455
+ const len0 = WASM_VECTOR_LEN;
456
+ const ptr1 = passStringToWasm0(pipeline_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
457
+ const len1 = WASM_VECTOR_LEN;
458
+ const ret = wasm.workerdb_aggregate(this.__wbg_ptr, ptr0, len0, ptr1, len1);
459
+ var ptr3 = ret[0];
460
+ var len3 = ret[1];
461
+ if (ret[3]) {
462
+ ptr3 = 0; len3 = 0;
463
+ throw takeFromExternrefTable0(ret[2]);
464
+ }
465
+ deferred4_0 = ptr3;
466
+ deferred4_1 = len3;
467
+ return getStringFromWasm0(ptr3, len3);
468
+ } finally {
469
+ wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
470
+ }
471
+ }
350
472
  /**
351
473
  * Compact the underlying OPFS / redb storage file, reclaiming space freed
352
474
  * by deletes and updates.
@@ -406,6 +528,21 @@ export class WorkerDB {
406
528
  }
407
529
  return ret[0] >>> 0;
408
530
  }
531
+ /**
532
+ * Create a compound index. `fields_json` is a JSON array of field names.
533
+ * @param {string} collection
534
+ * @param {string} fields_json
535
+ */
536
+ createCompoundIndex(collection, fields_json) {
537
+ const ptr0 = passStringToWasm0(collection, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
538
+ const len0 = WASM_VECTOR_LEN;
539
+ const ptr1 = passStringToWasm0(fields_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
540
+ const len1 = WASM_VECTOR_LEN;
541
+ const ret = wasm.workerdb_createCompoundIndex(this.__wbg_ptr, ptr0, len0, ptr1, len1);
542
+ if (ret[1]) {
543
+ throw takeFromExternrefTable0(ret[0]);
544
+ }
545
+ }
409
546
  /**
410
547
  * @param {string} collection
411
548
  * @param {string} field
@@ -497,6 +634,21 @@ export class WorkerDB {
497
634
  }
498
635
  return ret[0] !== 0;
499
636
  }
637
+ /**
638
+ * Drop a compound index by its ordered field list (`fields_json`).
639
+ * @param {string} collection
640
+ * @param {string} fields_json
641
+ */
642
+ dropCompoundIndex(collection, fields_json) {
643
+ const ptr0 = passStringToWasm0(collection, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
644
+ const len0 = WASM_VECTOR_LEN;
645
+ const ptr1 = passStringToWasm0(fields_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
646
+ const len1 = WASM_VECTOR_LEN;
647
+ const ret = wasm.workerdb_dropCompoundIndex(this.__wbg_ptr, ptr0, len0, ptr1, len1);
648
+ if (ret[1]) {
649
+ throw takeFromExternrefTable0(ret[0]);
650
+ }
651
+ }
500
652
  /**
501
653
  * @param {string} collection
502
654
  * @param {string} field
@@ -833,12 +985,18 @@ export class WorkerDB {
833
985
  * ```
834
986
  * @param {FileSystemSyncAccessHandle} sync_handle
835
987
  * @param {string | null} [config_json]
988
+ * @param {string | null} [passphrase]
989
+ * @param {Uint8Array | null} [salt]
836
990
  * @returns {WorkerDB}
837
991
  */
838
- static openWithConfigAndOpfs(sync_handle, config_json) {
992
+ static openWithConfigAndOpfs(sync_handle, config_json, passphrase, salt) {
839
993
  var ptr0 = isLikeNone(config_json) ? 0 : passStringToWasm0(config_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
840
994
  var len0 = WASM_VECTOR_LEN;
841
- const ret = wasm.workerdb_openWithConfigAndOpfs(sync_handle, ptr0, len0);
995
+ var ptr1 = isLikeNone(passphrase) ? 0 : passStringToWasm0(passphrase, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
996
+ var len1 = WASM_VECTOR_LEN;
997
+ var ptr2 = isLikeNone(salt) ? 0 : passArray8ToWasm0(salt, wasm.__wbindgen_malloc);
998
+ var len2 = WASM_VECTOR_LEN;
999
+ const ret = wasm.workerdb_openWithConfigAndOpfs(sync_handle, ptr0, len0, ptr1, len1, ptr2, len2);
842
1000
  if (ret[2]) {
843
1001
  throw takeFromExternrefTable0(ret[1]);
844
1002
  }
@@ -909,6 +1067,28 @@ export class WorkerDB {
909
1067
  }
910
1068
  return WorkerDB.__wrap(ret[0]);
911
1069
  }
1070
+ /**
1071
+ * @returns {bigint}
1072
+ */
1073
+ syncPending() {
1074
+ const ret = wasm.workerdb_syncPending(this.__wbg_ptr);
1075
+ return BigInt.asUintN(64, ret);
1076
+ }
1077
+ /**
1078
+ * @returns {string}
1079
+ */
1080
+ syncStatus() {
1081
+ let deferred1_0;
1082
+ let deferred1_1;
1083
+ try {
1084
+ const ret = wasm.workerdb_syncStatus(this.__wbg_ptr);
1085
+ deferred1_0 = ret[0];
1086
+ deferred1_1 = ret[1];
1087
+ return getStringFromWasm0(ret[0], ret[1]);
1088
+ } finally {
1089
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
1090
+ }
1091
+ }
912
1092
  /**
913
1093
  * Update all matching documents. Returns the count updated.
914
1094
  * @param {string} collection
@@ -1207,6 +1387,10 @@ function __wbg_get_imports() {
1207
1387
  const ret = arg0.createWritable();
1208
1388
  return ret;
1209
1389
  },
1390
+ __wbg_crypto_38df2bab126b63dc: function(arg0) {
1391
+ const ret = arg0.crypto;
1392
+ return ret;
1393
+ },
1210
1394
  __wbg_done_08ce71ee07e3bd17: function(arg0) {
1211
1395
  const ret = arg0.done;
1212
1396
  return ret;
@@ -1256,6 +1440,9 @@ function __wbg_get_imports() {
1256
1440
  __wbg_getRandomValues_3f44b700395062e5: function() { return handleError(function (arg0, arg1) {
1257
1441
  globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
1258
1442
  }, arguments); },
1443
+ __wbg_getRandomValues_c44a50d8cfdaebeb: function() { return handleError(function (arg0, arg1) {
1444
+ arg0.getRandomValues(arg1);
1445
+ }, arguments); },
1259
1446
  __wbg_getSize_0a16c5e2524d34aa: function() { return handleError(function (arg0) {
1260
1447
  const ret = arg0.getSize();
1261
1448
  return ret;
@@ -1414,6 +1601,10 @@ function __wbg_get_imports() {
1414
1601
  const ret = arg0.length;
1415
1602
  return ret;
1416
1603
  },
1604
+ __wbg_msCrypto_bd5a034af96bcba6: function(arg0) {
1605
+ const ret = arg0.msCrypto;
1606
+ return ret;
1607
+ },
1417
1608
  __wbg_navigator_9cebf56f28aa719b: function(arg0) {
1418
1609
  const ret = arg0.navigator;
1419
1610
  return ret;
@@ -1453,7 +1644,7 @@ function __wbg_get_imports() {
1453
1644
  const a = state0.a;
1454
1645
  state0.a = 0;
1455
1646
  try {
1456
- return wasm_bindgen__convert__closures_____invoke__h19185396894e5dfb(a, state0.b, arg0, arg1);
1647
+ return wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined_______true_(a, state0.b, arg0, arg1);
1457
1648
  } finally {
1458
1649
  state0.a = a;
1459
1650
  }
@@ -1475,7 +1666,7 @@ function __wbg_get_imports() {
1475
1666
  const a = state0.a;
1476
1667
  state0.a = 0;
1477
1668
  try {
1478
- return wasm_bindgen__convert__closures_____invoke__h19185396894e5dfb(a, state0.b, arg0, arg1);
1669
+ return wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined_______true_(a, state0.b, arg0, arg1);
1479
1670
  } finally {
1480
1671
  state0.a = a;
1481
1672
  }
@@ -1502,6 +1693,10 @@ function __wbg_get_imports() {
1502
1693
  const ret = arg0.next;
1503
1694
  return ret;
1504
1695
  },
1696
+ __wbg_node_84ea875411254db1: function(arg0) {
1697
+ const ret = arg0.node;
1698
+ return ret;
1699
+ },
1505
1700
  __wbg_now_16f0c993d5dd6c27: function() {
1506
1701
  const ret = Date.now();
1507
1702
  return ret;
@@ -1510,6 +1705,10 @@ function __wbg_get_imports() {
1510
1705
  const ret = Array.of(arg0, arg1);
1511
1706
  return ret;
1512
1707
  },
1708
+ __wbg_process_44c7a14e11e9f69e: function(arg0) {
1709
+ const ret = arg0.process;
1710
+ return ret;
1711
+ },
1513
1712
  __wbg_prototypesetcall_d62e5099504357e6: function(arg0, arg1, arg2) {
1514
1713
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
1515
1714
  },
@@ -1524,10 +1723,17 @@ function __wbg_get_imports() {
1524
1723
  __wbg_queueMicrotask_a082d78ce798393e: function(arg0) {
1525
1724
  queueMicrotask(arg0);
1526
1725
  },
1726
+ __wbg_randomFillSync_6c25eac9869eb53c: function() { return handleError(function (arg0, arg1) {
1727
+ arg0.randomFillSync(arg1);
1728
+ }, arguments); },
1527
1729
  __wbg_removeEntry_b2a4d6d0ee2040c5: function(arg0, arg1, arg2) {
1528
1730
  const ret = arg0.removeEntry(getStringFromWasm0(arg1, arg2));
1529
1731
  return ret;
1530
1732
  },
1733
+ __wbg_require_b4edbdcf3e2a1ef0: function() { return handleError(function () {
1734
+ const ret = module.require;
1735
+ return ret;
1736
+ }, arguments); },
1531
1737
  __wbg_resolve_ae8d83246e5bcc12: function(arg0) {
1532
1738
  const ret = Promise.resolve(arg0);
1533
1739
  return ret;
@@ -1613,6 +1819,10 @@ function __wbg_get_imports() {
1613
1819
  const ret = JSON.stringify(arg0);
1614
1820
  return ret;
1615
1821
  }, arguments); },
1822
+ __wbg_subarray_a068d24e39478a8a: function(arg0, arg1, arg2) {
1823
+ const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);
1824
+ return ret;
1825
+ },
1616
1826
  __wbg_then_098abe61755d12f6: function(arg0, arg1) {
1617
1827
  const ret = arg0.then(arg1);
1618
1828
  return ret;
@@ -1635,19 +1845,23 @@ function __wbg_get_imports() {
1635
1845
  const ret = arg0.value;
1636
1846
  return ret;
1637
1847
  },
1848
+ __wbg_versions_276b2795b1c6a219: function(arg0) {
1849
+ const ret = arg0.versions;
1850
+ return ret;
1851
+ },
1638
1852
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
1639
- // Cast intrinsic for `Closure(Closure { dtor_idx: 197, function: Function { arguments: [], shim_idx: 198, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1640
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h019ad81c65a5ac2e, wasm_bindgen__convert__closures_____invoke__h88d126a9c69f3dfa);
1853
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 215, function: Function { arguments: [], shim_idx: 216, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1854
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut_____Output_______, wasm_bindgen_60ce93de3f474933___convert__closures_____invoke_______true_);
1641
1855
  return ret;
1642
1856
  },
1643
1857
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
1644
- // Cast intrinsic for `Closure(Closure { dtor_idx: 633, function: Function { arguments: [Externref], shim_idx: 634, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1645
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h53c506fd33a34156, wasm_bindgen__convert__closures_____invoke__hc8d470a46e185f12);
1858
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 692, function: Function { arguments: [Externref], shim_idx: 693, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1859
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_60ce93de3f474933___JsValue____Output___core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___, wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___true_);
1646
1860
  return ret;
1647
1861
  },
1648
1862
  __wbindgen_cast_0000000000000003: function(arg0, arg1) {
1649
- // Cast intrinsic for `Closure(Closure { dtor_idx: 89, function: Function { arguments: [Externref], shim_idx: 90, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1650
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__hc05d4761059c0df5, wasm_bindgen__convert__closures_____invoke__h7b2d358a66567a58);
1863
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 71, function: Function { arguments: [Externref], shim_idx: 72, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1864
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_60ce93de3f474933___JsValue____Output_______, wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue______true_);
1651
1865
  return ret;
1652
1866
  },
1653
1867
  __wbindgen_cast_0000000000000004: function(arg0) {
@@ -1661,16 +1875,21 @@ function __wbg_get_imports() {
1661
1875
  return ret;
1662
1876
  },
1663
1877
  __wbindgen_cast_0000000000000006: function(arg0, arg1) {
1878
+ // Cast intrinsic for `Ref(Slice(U8)) -> NamedExternref("Uint8Array")`.
1879
+ const ret = getArrayU8FromWasm0(arg0, arg1);
1880
+ return ret;
1881
+ },
1882
+ __wbindgen_cast_0000000000000007: function(arg0, arg1) {
1664
1883
  // Cast intrinsic for `Ref(String) -> Externref`.
1665
1884
  const ret = getStringFromWasm0(arg0, arg1);
1666
1885
  return ret;
1667
1886
  },
1668
- __wbindgen_cast_0000000000000007: function(arg0) {
1887
+ __wbindgen_cast_0000000000000008: function(arg0) {
1669
1888
  // Cast intrinsic for `U64 -> Externref`.
1670
1889
  const ret = BigInt.asUintN(64, arg0);
1671
1890
  return ret;
1672
1891
  },
1673
- __wbindgen_cast_0000000000000008: function(arg0, arg1) {
1892
+ __wbindgen_cast_0000000000000009: function(arg0, arg1) {
1674
1893
  var v0 = getArrayU8FromWasm0(arg0, arg1).slice();
1675
1894
  wasm.__wbindgen_free(arg0, arg1 * 1, 1);
1676
1895
  // Cast intrinsic for `Vector(U8) -> Externref`.
@@ -1693,23 +1912,23 @@ function __wbg_get_imports() {
1693
1912
  };
1694
1913
  }
1695
1914
 
1696
- function wasm_bindgen__convert__closures_____invoke__h88d126a9c69f3dfa(arg0, arg1) {
1697
- wasm.wasm_bindgen__convert__closures_____invoke__h88d126a9c69f3dfa(arg0, arg1);
1915
+ function wasm_bindgen_60ce93de3f474933___convert__closures_____invoke_______true_(arg0, arg1) {
1916
+ wasm.wasm_bindgen_60ce93de3f474933___convert__closures_____invoke_______true_(arg0, arg1);
1698
1917
  }
1699
1918
 
1700
- function wasm_bindgen__convert__closures_____invoke__h7b2d358a66567a58(arg0, arg1, arg2) {
1701
- wasm.wasm_bindgen__convert__closures_____invoke__h7b2d358a66567a58(arg0, arg1, arg2);
1919
+ function wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue______true_(arg0, arg1, arg2) {
1920
+ wasm.wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue______true_(arg0, arg1, arg2);
1702
1921
  }
1703
1922
 
1704
- function wasm_bindgen__convert__closures_____invoke__hc8d470a46e185f12(arg0, arg1, arg2) {
1705
- const ret = wasm.wasm_bindgen__convert__closures_____invoke__hc8d470a46e185f12(arg0, arg1, arg2);
1923
+ function wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___true_(arg0, arg1, arg2) {
1924
+ const ret = wasm.wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___true_(arg0, arg1, arg2);
1706
1925
  if (ret[1]) {
1707
1926
  throw takeFromExternrefTable0(ret[0]);
1708
1927
  }
1709
1928
  }
1710
1929
 
1711
- function wasm_bindgen__convert__closures_____invoke__h19185396894e5dfb(arg0, arg1, arg2, arg3) {
1712
- wasm.wasm_bindgen__convert__closures_____invoke__h19185396894e5dfb(arg0, arg1, arg2, arg3);
1930
+ function wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined_______true_(arg0, arg1, arg2, arg3) {
1931
+ wasm.wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined_______true_(arg0, arg1, arg2, arg3);
1713
1932
  }
1714
1933
 
1715
1934
 
@@ -1805,6 +2024,17 @@ function debugString(val) {
1805
2024
  return className;
1806
2025
  }
1807
2026
 
2027
+ function getArrayJsValueFromWasm0(ptr, len) {
2028
+ ptr = ptr >>> 0;
2029
+ const mem = getDataViewMemory0();
2030
+ const result = [];
2031
+ for (let i = ptr; i < ptr + 4 * len; i += 4) {
2032
+ result.push(wasm.__wbindgen_externrefs.get(mem.getUint32(i, true)));
2033
+ }
2034
+ wasm.__externref_drop_slice(ptr, len);
2035
+ return result;
2036
+ }
2037
+
1808
2038
  function getArrayU8FromWasm0(ptr, len) {
1809
2039
  ptr = ptr >>> 0;
1810
2040
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
@@ -1894,6 +2124,16 @@ function passArrayF32ToWasm0(arg, malloc) {
1894
2124
  return ptr;
1895
2125
  }
1896
2126
 
2127
+ function passArrayJsValueToWasm0(array, malloc) {
2128
+ const ptr = malloc(array.length * 4, 4) >>> 0;
2129
+ for (let i = 0; i < array.length; i++) {
2130
+ const add = addToExternrefTable0(array[i]);
2131
+ getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
2132
+ }
2133
+ WASM_VECTOR_LEN = array.length;
2134
+ return ptr;
2135
+ }
2136
+
1897
2137
  function passStringToWasm0(arg, malloc, realloc) {
1898
2138
  if (realloc === undefined) {
1899
2139
  const buf = cachedTextEncoder.encode(arg);
Binary file
@@ -2,14 +2,17 @@
2
2
  /* eslint-disable */
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const __wbg_workerdb_free: (a: number, b: number) => void;
5
+ export const workerdb_aggregate: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
5
6
  export const workerdb_compact: (a: number) => [number, number];
6
7
  export const workerdb_compactTombstones: (a: number, b: number, c: number, d: number) => [number, number, number];
7
8
  export const workerdb_count: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
9
+ export const workerdb_createCompoundIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
8
10
  export const workerdb_createFtsIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
9
11
  export const workerdb_createIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
10
12
  export const workerdb_createVectorIndex: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number) => [number, number];
11
13
  export const workerdb_deleteMany: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
12
14
  export const workerdb_deleteOne: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
15
+ export const workerdb_dropCompoundIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
13
16
  export const workerdb_dropFtsIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
14
17
  export const workerdb_dropIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
15
18
  export const workerdb_dropVectorIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
@@ -24,20 +27,25 @@ export const workerdb_insertMany: (a: number, b: number, c: number, d: number, e
24
27
  export const workerdb_listCollections: (a: number) => [number, number, number, number];
25
28
  export const workerdb_listIndexes: (a: number, b: number, c: number) => [number, number, number, number];
26
29
  export const workerdb_openInMemory: () => [number, number, number];
27
- export const workerdb_openWithConfigAndOpfs: (a: any, b: number, c: number) => [number, number, number];
30
+ export const workerdb_openWithConfigAndOpfs: (a: any, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
28
31
  export const workerdb_openWithConfigAndSnapshot: (a: number, b: number, c: number, d: number) => [number, number, number];
29
32
  export const workerdb_openWithOpfs: (a: any) => [number, number, number];
30
33
  export const workerdb_openWithSnapshot: (a: number, b: number) => [number, number, number];
34
+ export const workerdb_syncPending: (a: number) => bigint;
35
+ export const workerdb_syncStatus: (a: number) => [number, number];
31
36
  export const workerdb_updateMany: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
32
37
  export const workerdb_updateOne: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
33
38
  export const workerdb_upgradeVectorIndex: (a: number, b: number, c: number, d: number, e: number) => [number, number];
34
39
  export const __wbg_collectionwasm_free: (a: number, b: number) => void;
35
40
  export const __wbg_taladbwasm_free: (a: number, b: number) => void;
41
+ export const collectionwasm_aggregate: (a: number, b: any) => [number, number, number];
36
42
  export const collectionwasm_count: (a: number, b: any) => [number, number, number];
43
+ export const collectionwasm_createCompoundIndex: (a: number, b: number, c: number) => [number, number];
37
44
  export const collectionwasm_createIndex: (a: number, b: number, c: number) => [number, number];
38
45
  export const collectionwasm_createVectorIndex: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number];
39
46
  export const collectionwasm_deleteMany: (a: number, b: any) => [number, number, number];
40
47
  export const collectionwasm_deleteOne: (a: number, b: any) => [number, number, number];
48
+ export const collectionwasm_dropCompoundIndex: (a: number, b: number, c: number) => [number, number];
41
49
  export const collectionwasm_dropIndex: (a: number, b: number, c: number) => [number, number];
42
50
  export const collectionwasm_dropVectorIndex: (a: number, b: number, c: number) => [number, number];
43
51
  export const collectionwasm_find: (a: number, b: any) => [number, number, number];
@@ -49,24 +57,27 @@ export const collectionwasm_updateMany: (a: number, b: any, c: any) => [number,
49
57
  export const collectionwasm_updateOne: (a: number, b: any, c: any) => [number, number, number];
50
58
  export const collectionwasm_upgradeVectorIndex: (a: number, b: number, c: number) => [number, number];
51
59
  export const taladbwasm_collection: (a: number, b: number, c: number) => [number, number, number];
60
+ export const taladbwasm_exportChanges: (a: number, b: number, c: number, d: number) => [number, number, number, number];
52
61
  export const taladbwasm_exportSnapshot: (a: number) => [number, number, number, number];
62
+ export const taladbwasm_importChanges: (a: number, b: number, c: number) => [number, number, number];
63
+ export const taladbwasm_listCollectionNames: (a: number) => [number, number, number, number];
53
64
  export const taladbwasm_openInMemory: () => [number, number, number];
54
65
  export const taladbwasm_openWithSnapshot: (a: number, b: number) => [number, number, number];
55
66
  export const init: () => void;
67
+ export const opfs_open_backend: (a: number, b: number) => any;
56
68
  export const is_opfs_available: () => any;
57
69
  export const opfs_delete_snapshot: (a: number, b: number) => any;
58
70
  export const opfs_flush_snapshot: (a: number, b: number, c: number, d: number) => any;
59
71
  export const opfs_load_snapshot: (a: number, b: number) => any;
60
72
  export const idb_load_snapshot: (a: number, b: number) => any;
61
73
  export const idb_save_snapshot: (a: number, b: number, c: number, d: number) => any;
62
- export const opfs_open_backend: (a: number, b: number) => any;
63
- export const wasm_bindgen__closure__destroy__h019ad81c65a5ac2e: (a: number, b: number) => void;
64
- export const wasm_bindgen__closure__destroy__h53c506fd33a34156: (a: number, b: number) => void;
65
- export const wasm_bindgen__closure__destroy__hc05d4761059c0df5: (a: number, b: number) => void;
66
- export const wasm_bindgen__convert__closures_____invoke__hc8d470a46e185f12: (a: number, b: number, c: any) => [number, number];
67
- export const wasm_bindgen__convert__closures_____invoke__h19185396894e5dfb: (a: number, b: number, c: any, d: any) => void;
68
- export const wasm_bindgen__convert__closures_____invoke__h7b2d358a66567a58: (a: number, b: number, c: any) => void;
69
- export const wasm_bindgen__convert__closures_____invoke__h88d126a9c69f3dfa: (a: number, b: number) => void;
74
+ export const wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut_____Output_______: (a: number, b: number) => void;
75
+ export const wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_60ce93de3f474933___JsValue____Output___core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___: (a: number, b: number) => void;
76
+ export const wasm_bindgen_60ce93de3f474933___closure__destroy___dyn_core_7d5f0a2ba6a62c33___ops__function__FnMut__wasm_bindgen_60ce93de3f474933___JsValue____Output_______: (a: number, b: number) => void;
77
+ export const wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_60ce93de3f474933___JsError___true_: (a: number, b: number, c: any) => [number, number];
78
+ export const wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined___js_sys_517e1093b71f55ec___Function_fn_wasm_bindgen_60ce93de3f474933___JsValue_____wasm_bindgen_60ce93de3f474933___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
79
+ export const wasm_bindgen_60ce93de3f474933___convert__closures_____invoke___wasm_bindgen_60ce93de3f474933___JsValue______true_: (a: number, b: number, c: any) => void;
80
+ export const wasm_bindgen_60ce93de3f474933___convert__closures_____invoke_______true_: (a: number, b: number) => void;
70
81
  export const __wbindgen_malloc: (a: number, b: number) => number;
71
82
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
72
83
  export const __wbindgen_exn_store: (a: number) => void;
@@ -74,4 +85,5 @@ export const __externref_table_alloc: () => number;
74
85
  export const __wbindgen_externrefs: WebAssembly.Table;
75
86
  export const __wbindgen_free: (a: number, b: number, c: number) => void;
76
87
  export const __externref_table_dealloc: (a: number) => void;
88
+ export const __externref_drop_slice: (a: number, b: number) => void;
77
89
  export const __wbindgen_start: () => void;
@@ -39,6 +39,7 @@
39
39
  * deleteOne { collection, filterJson }
40
40
  * deleteMany { collection, filterJson }
41
41
  * count { collection, filterJson }
42
+ * aggregate { collection, pipelineJson } → JSON array of result docs
42
43
  * createIndex { collection, field }
43
44
  * dropIndex { collection, field }
44
45
  * createFtsIndex { collection, field }
@@ -161,14 +162,26 @@ let broadcastChannel = null;
161
162
  */
162
163
  let idbFallback = false;
163
164
 
165
+ /** Whether this worker is allowed to publish the authoritative IDB snapshot. */
166
+ let snapshotWriter = false;
167
+
168
+ /**
169
+ * True when the database is opened with a passphrase (encrypted at rest in the
170
+ * OPFS file). Encrypted databases NEVER write a snapshot to IndexedDB — an
171
+ * exported snapshot is decrypted plaintext, so persisting it would defeat
172
+ * encryption. Encrypted mode therefore requires exclusive OPFS and is
173
+ * single-tab: the multi-tab IDB-snapshot fallback is refused, not silently
174
+ * downgraded to plaintext.
175
+ * @type {boolean}
176
+ */
177
+ let encrypted = false;
178
+
164
179
  /**
165
180
  * Timestamp (ms) of the last changeset we exported and broadcast to the
166
181
  * primary tab. Used as `sinceMs` for the next export so we only send the
167
182
  * delta, not the entire database on every write.
168
183
  * @type {number}
169
184
  */
170
- let lastSecondaryPushMs = 0;
171
-
172
185
  // ---------------------------------------------------------------------------
173
186
  // IndexedDB helpers (used only when OPFS is unavailable)
174
187
  // ---------------------------------------------------------------------------
@@ -259,10 +272,11 @@ async function flushSnapshot() {
259
272
  clearTimeout(snapshotTimer);
260
273
  snapshotTimer = null;
261
274
  lastSnapshotMs = Date.now();
262
- if (db && activeDbName) {
275
+ if (db && activeDbName && snapshotWriter) {
263
276
  try {
264
277
  const bytes = db.exportSnapshot();
265
278
  await idbSaveSnapshot(activeDbName, bytes);
279
+ broadcastChannel?.postMessage('taladb:snapshot-ready');
266
280
  } catch { /* best-effort — ignore failures */ }
267
281
  }
268
282
  }
@@ -299,11 +313,13 @@ function pushChangesetToPrimary() {
299
313
  // Collect all collection names from the current in-memory state.
300
314
  // exportChangeset accepts a JSON array of collection names.
301
315
  const collections = db.listCollections();
302
- const changeset = db.exportChangeset(collections, lastSecondaryPushMs);
316
+ // Wall-clock timestamps are not safe incremental cursors: a write can be
317
+ // stamped before an export but commit after its snapshot. Replay is
318
+ // idempotent under LWW and cannot skip such a write.
319
+ const changeset = db.exportChangeset(collections, 0);
303
320
  // Only broadcast if there is actually something to send.
304
321
  const parsed = JSON.parse(changeset);
305
322
  if (parsed.length === 0) return;
306
- lastSecondaryPushMs = Date.now();
307
323
  broadcastChannel.postMessage({ type: 'taladb:secondary-write', token: SESSION_TOKEN, changeset });
308
324
  log(`Broadcast ${parsed.length} change(s) to primary tab`);
309
325
  } catch (err) {
@@ -322,7 +338,7 @@ function onWriteCommitted() {
322
338
  pushChangesetToPrimary();
323
339
  // Debounced IDB flush — keeps other tabs' fallback instances in sync via
324
340
  // BroadcastChannel + snapshotDirty reload without writing to IDB on every op.
325
- scheduleSnapshot();
341
+ if (snapshotWriter) scheduleSnapshot();
326
342
  }
327
343
 
328
344
  // ---------------------------------------------------------------------------
@@ -365,7 +381,7 @@ async function dispatch(op, args) {
365
381
  }
366
382
 
367
383
  if (op === 'init') {
368
- const { dbName, configJson } = args;
384
+ const { dbName, configJson, passphrase } = args;
369
385
 
370
386
  if (activeDbName !== null && activeDbName !== dbName) {
371
387
  throw new Error(
@@ -377,7 +393,7 @@ async function dispatch(op, args) {
377
393
  if (!initPromises.has(dbName)) {
378
394
  activeDbName = dbName;
379
395
  activeConfigJson = configJson ?? null;
380
- initPromises.set(dbName, doInit(dbName, configJson ?? null));
396
+ initPromises.set(dbName, doInit(dbName, configJson ?? null, passphrase ?? null));
381
397
  }
382
398
  await initPromises.get(dbName);
383
399
  return null;
@@ -431,6 +447,9 @@ async function dispatch(op, args) {
431
447
  case 'count':
432
448
  return db.count(args.collection, args.filterJson ?? 'null');
433
449
 
450
+ case 'aggregate':
451
+ return db.aggregate(args.collection, args.pipelineJson ?? '[]');
452
+
434
453
  case 'createIndex':
435
454
  db.createIndex(args.collection, args.field);
436
455
  return null;
@@ -439,6 +458,14 @@ async function dispatch(op, args) {
439
458
  db.dropIndex(args.collection, args.field);
440
459
  return null;
441
460
 
461
+ case 'createCompoundIndex':
462
+ db.createCompoundIndex(args.collection, args.fieldsJson);
463
+ return null;
464
+
465
+ case 'dropCompoundIndex':
466
+ db.dropCompoundIndex(args.collection, args.fieldsJson);
467
+ return null;
468
+
442
469
  case 'createFtsIndex':
443
470
  db.createFtsIndex(args.collection, args.field);
444
471
  return null;
@@ -487,6 +514,17 @@ async function dispatch(op, args) {
487
514
  db.compact();
488
515
  return null;
489
516
 
517
+ case 'syncStatus':
518
+ return db.syncStatus();
519
+
520
+ case 'flushSync': {
521
+ const deadline = Date.now() + (args.timeoutMs ?? 5000);
522
+ while (db.syncPending() > 0 && Date.now() < deadline) {
523
+ await new Promise(resolve => setTimeout(resolve, 20));
524
+ }
525
+ return db.syncPending() === 0;
526
+ }
527
+
490
528
  case 'compactTombstones':
491
529
  // Prune tombstones older than beforeMs from a collection.
492
530
  // Returns the count of tombstones removed.
@@ -506,6 +544,13 @@ async function dispatch(op, args) {
506
544
  }
507
545
 
508
546
  case 'close':
547
+ // Give accepted HTTP push events a bounded opportunity to finish.
548
+ {
549
+ const deadline = Date.now() + 5000;
550
+ while (db.syncPending() > 0 && Date.now() < deadline) {
551
+ await new Promise(resolve => setTimeout(resolve, 20));
552
+ }
553
+ }
509
554
  // Flush any pending debounced snapshot before releasing the lock so
510
555
  // no writes are lost when the tab closes or navigates away.
511
556
  await flushSnapshot();
@@ -514,6 +559,7 @@ async function dispatch(op, args) {
514
559
  broadcastChannel?.close();
515
560
  broadcastChannel = null;
516
561
  idbFallback = false;
562
+ snapshotWriter = false;
517
563
  db = null;
518
564
  return null;
519
565
 
@@ -522,26 +568,58 @@ async function dispatch(op, args) {
522
568
  }
523
569
  }
524
570
 
571
+ /**
572
+ * Load the 16-byte key-derivation salt from an OPFS sidecar file, or create it
573
+ * on first open. The salt is not secret (it defends against precomputed-hash
574
+ * attacks) but must be stable across opens, so it lives beside the DB file.
575
+ * @returns {Promise<Uint8Array>} the 16-byte salt
576
+ */
577
+ async function loadOrCreateSalt(root, saltFileName) {
578
+ const fh = await root.getFileHandle(saltFileName, { create: true });
579
+ const h = await fh.createSyncAccessHandle();
580
+ try {
581
+ const size = h.getSize();
582
+ if (size === 16) {
583
+ const salt = new Uint8Array(16);
584
+ h.read(salt, { at: 0 });
585
+ return salt;
586
+ }
587
+ if (size === 0) {
588
+ const salt = new Uint8Array(16);
589
+ self.crypto.getRandomValues(salt);
590
+ h.write(salt, { at: 0 });
591
+ h.flush();
592
+ return salt;
593
+ }
594
+ throw new Error(`invalid TalaDB salt file (${size} bytes, expected 16)`);
595
+ } finally {
596
+ h.close();
597
+ }
598
+ }
599
+
525
600
  // ---------------------------------------------------------------------------
526
601
  // Initialisation — load WASM, acquire lock, open OPFS file
527
602
  // ---------------------------------------------------------------------------
528
603
 
529
- async function doInit(dbName, configJson) {
604
+ async function doInit(dbName, configJson, passphrase = null) {
530
605
  const wasm = await import(/* @vite-ignore */ '../pkg/taladb_web.js');
531
606
  await wasm.default();
532
607
 
533
608
  // Hoist to module scope so snapshot reloads in dispatch() can use it.
534
609
  WorkerDB = wasm.WorkerDB;
535
610
 
611
+ encrypted = typeof passphrase === 'string' && passphrase.length > 0;
612
+
536
613
  // Open the BroadcastChannel now that we know the db name.
537
614
  if (typeof BroadcastChannel !== 'undefined') {
538
615
  broadcastChannel = new BroadcastChannel(`taladb:${dbName}`);
539
616
  broadcastChannel.onmessage = async (e) => {
540
617
  if (e.data === 'taladb:changed' && idbFallback) {
541
- // Fallback tab: primary tab wrote — reload snapshot before next read.
542
- snapshotDirty = true;
543
- } else if (e.data === 'taladb:request-snapshot' && !idbFallback && db && activeDbName) {
618
+ // Wait for snapshot-ready: changed is emitted before the primary's
619
+ // asynchronous IDB transaction has committed.
620
+ } else if (e.data === 'taladb:request-snapshot' && !idbFallback && !encrypted && db && activeDbName) {
544
621
  // Primary (OPFS) tab: a new tab asked for a snapshot — export and save it.
622
+ // Never for encrypted DBs: an exported snapshot is decrypted plaintext.
545
623
  try {
546
624
  const bytes = db.exportSnapshot();
547
625
  await idbSaveSnapshot(activeDbName, bytes);
@@ -553,8 +631,15 @@ async function doInit(dbName, configJson) {
553
631
  const resolve = pendingSnapshotResolve;
554
632
  pendingSnapshotResolve = null;
555
633
  resolve();
556
- } else if (e.data?.type === 'taladb:secondary-write' && typeof e.data.token === 'string' && e.data.token.length > 0 && !idbFallback && db) {
557
- // Primary (OPFS) tab: a secondary tab made a write — merge it in via LWW.
634
+ } else if (e.data === 'taladb:snapshot-ready' && idbFallback) {
635
+ snapshotDirty = true;
636
+ } else if (e.data?.type === 'taladb:secondary-write' && typeof e.data.token === 'string' && e.data.token.length > 0 && db && !encrypted) {
637
+ // `!encrypted`: encrypted databases are single-tab, so there are no
638
+ // legitimate secondary-tab writes — accepting them would let any
639
+ // same-origin script inject documents into an encrypted DB without
640
+ // knowing the passphrase.
641
+ // Merge peer writes in every mode. This also makes multiple tabs
642
+ // converge when OPFS is entirely unavailable and every tab uses IDB.
558
643
  // The token requirement rejects unauthenticated injection attempts that
559
644
  // omit the SESSION_TOKEN field (not a guarantee against same-origin attackers
560
645
  // who observe the token, but defence-in-depth against naive injection).
@@ -579,17 +664,27 @@ async function doInit(dbName, configJson) {
579
664
  if (configJson) return WorkerDB.openWithConfigAndSnapshot(snapshot, configJson);
580
665
  return WorkerDB.openWithSnapshot(snapshot);
581
666
  }
667
+ // Salt for key derivation, loaded/created in an OPFS sidecar (encrypted mode
668
+ // only). Passed to the WASM open so the derived key is stable across opens.
669
+ let salt = null;
582
670
  function openWithOpfs(syncHandle) {
583
- if (configJson) return WorkerDB.openWithConfigAndOpfs(syncHandle, configJson);
584
- return WorkerDB.openWithOpfs(syncHandle);
671
+ // openWithConfigAndOpfs(handle, configJson, passphrase?, salt?)
672
+ return WorkerDB.openWithConfigAndOpfs(syncHandle, configJson ?? null, passphrase, salt);
585
673
  }
586
674
 
587
675
  const opfsAvailable = await checkOpfs();
588
676
  if (!opfsAvailable) {
677
+ if (encrypted) {
678
+ throw new Error(
679
+ 'TalaDB encryption requires OPFS, which is unavailable in this browser context. ' +
680
+ 'Refusing to open — the in-memory/IndexedDB fallback cannot encrypt at rest.'
681
+ );
682
+ }
589
683
  warn('OPFS unavailable — falling back to IndexedDB-backed in-memory');
590
684
  const snapshot = await idbLoadSnapshot(dbName);
591
685
  db = openWithSnapshot(snapshot);
592
686
  idbFallback = true;
687
+ snapshotWriter = true;
593
688
  if (snapshot) {
594
689
  log(`Restored from IndexedDB snapshot (${snapshot.byteLength} bytes)`);
595
690
  } else {
@@ -602,11 +697,26 @@ async function doInit(dbName, configJson) {
602
697
  const fileName = `taladb_${dbName.replaceAll(/[/\\:]/g, '_')}.redb`;
603
698
  const fileHandle = await root.getFileHandle(fileName, { create: true });
604
699
 
700
+ // Encrypted mode: the 16-byte key-derivation salt lives in an OPFS sidecar
701
+ // file next to the DB. It is loaded/created only AFTER this tab has won the
702
+ // exclusive lock (or determined no locking applies), so two tabs racing to
703
+ // open never collide on the salt file's exclusive access handle.
704
+
605
705
  if (!('locks' in navigator)) {
606
706
  // Web Locks not available — open directly (single-tab safe only).
607
707
  warn('Web Locks unavailable — multi-tab write safety disabled');
708
+ if (encrypted) salt = await loadOrCreateSalt(root, `${fileName}.salt`);
608
709
  const syncHandle = await fileHandle.createSyncAccessHandle();
609
- db = openWithOpfs(syncHandle);
710
+ try {
711
+ db = openWithOpfs(syncHandle);
712
+ } catch (e) {
713
+ // A failed open (e.g. wrong passphrase) must release the exclusive OPFS
714
+ // access handle, or every retry fails with "Access Handles cannot be
715
+ // created" until the page reloads.
716
+ try { syncHandle.close(); } catch { /* best-effort */ }
717
+ throw e;
718
+ }
719
+ snapshotWriter = !encrypted; // encrypted DBs never write a plaintext IDB snapshot
610
720
  log(`Opened "${fileName}" via OPFS`);
611
721
  return;
612
722
  }
@@ -621,7 +731,18 @@ async function doInit(dbName, configJson) {
621
731
  await new Promise((resolve, reject) => {
622
732
  navigator.locks.request(lockName, { ifAvailable: true }, async (lock) => {
623
733
  if (lock === null) {
624
- // Lock is held by another tab — use IDB snapshot so this tab loads immediately.
734
+ // Lock is held by another tab.
735
+ if (encrypted) {
736
+ // The IDB-snapshot fallback stores decrypted plaintext, so it's
737
+ // refused for encrypted databases — they're single-tab. Reject
738
+ // rather than downgrade.
739
+ reject(new Error(
740
+ 'This encrypted TalaDB database is already open in another tab. ' +
741
+ 'Encrypted browser databases are single-tab (the multi-tab fallback would store plaintext).'
742
+ ));
743
+ return;
744
+ }
745
+ // Unencrypted: use IDB snapshot so this tab loads immediately.
625
746
  warn('OPFS lock held by another tab — falling back to IndexedDB snapshot (live-sync via BroadcastChannel)');
626
747
  let snapshot = await idbLoadSnapshot(dbName);
627
748
 
@@ -638,6 +759,7 @@ async function doInit(dbName, configJson) {
638
759
 
639
760
  db = openWithSnapshot(snapshot ?? null);
640
761
  idbFallback = true;
762
+ snapshotWriter = false;
641
763
  if (snapshot) {
642
764
  log(`Restored from IDB snapshot (${snapshot.byteLength} bytes)`);
643
765
  } else {
@@ -648,9 +770,12 @@ async function doInit(dbName, configJson) {
648
770
  }
649
771
 
650
772
  // Acquired the lock — use OPFS.
773
+ let syncHandle = null;
651
774
  try {
652
- const syncHandle = await fileHandle.createSyncAccessHandle();
775
+ if (encrypted) salt = await loadOrCreateSalt(root, `${fileName}.salt`);
776
+ syncHandle = await fileHandle.createSyncAccessHandle();
653
777
  db = openWithOpfs(syncHandle);
778
+ snapshotWriter = !encrypted; // encrypted DBs never write a plaintext IDB snapshot
654
779
  log(`Opened "${fileName}" via OPFS (Web Locks)`);
655
780
  resolve(); // signal doInit complete — caller can proceed
656
781
 
@@ -661,6 +786,13 @@ async function doInit(dbName, configJson) {
661
786
  syncHandle.close();
662
787
  db = null;
663
788
  } catch (e) {
789
+ // A failed open (e.g. wrong passphrase) must release the exclusive
790
+ // OPFS access handle, or every retry fails with "Access Handles
791
+ // cannot be created" until the page reloads. Returning from this
792
+ // callback also releases the Web Lock.
793
+ if (syncHandle) {
794
+ try { syncHandle.close(); } catch { /* best-effort */ }
795
+ }
664
796
  reject(e);
665
797
  }
666
798
  });