@moyodb/sdk 1.4.0 → 1.5.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.
Files changed (36) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/browser-worker-p7uX85l-.js +4 -0
  3. package/dist/assets/browser-worker-p7uX85l-.js.map +1 -0
  4. package/dist/assets/shared-worker-BALTqEUe.js +2 -0
  5. package/dist/assets/shared-worker-BALTqEUe.js.map +1 -0
  6. package/dist/chunks/{indexing-B0duqlUs.js → indexing-DdpU69Fd.js} +302 -69
  7. package/dist/chunks/{indexing-B0duqlUs.js.map → indexing-DdpU69Fd.js.map} +1 -1
  8. package/dist/codec.d.ts.map +1 -1
  9. package/dist/compression.d.ts.map +1 -1
  10. package/dist/engine/README.md +2 -2
  11. package/dist/engine/moyodb_engine.d.ts +2 -2
  12. package/dist/engine/moyodb_engine.js +22 -22
  13. package/dist/engine/moyodb_engine_bg.wasm +0 -0
  14. package/dist/engine/moyodb_engine_bg.wasm.d.ts +2 -2
  15. package/dist/engine/package.json +1 -1
  16. package/dist/engine/snippets/{moyodb-engine-1d53039816cbc2f7 → moyodb-engine-1f8134232168280b}/js/opfs_shim.js +8 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/indexing.d.ts +7 -0
  19. package/dist/indexing.d.ts.map +1 -1
  20. package/dist/moyodb-sdk.js +1329 -931
  21. package/dist/moyodb-sdk.js.map +1 -1
  22. package/dist/node-engine.js +382 -47
  23. package/dist/node-engine.js.map +1 -1
  24. package/dist/node.js +332 -44
  25. package/dist/node.js.map +1 -1
  26. package/dist/registry.d.ts.map +1 -1
  27. package/dist/subscriptions.d.ts.map +1 -1
  28. package/dist/worker-client.d.ts.map +1 -1
  29. package/dist/worker-server.d.ts.map +1 -1
  30. package/dist/worker.d.ts +10 -3
  31. package/dist/worker.d.ts.map +1 -1
  32. package/package.json +2 -1
  33. package/dist/assets/browser-worker-Bj2ErRvC.js +0 -4
  34. package/dist/assets/browser-worker-Bj2ErRvC.js.map +0 -1
  35. package/dist/assets/shared-worker-CMeTcusa.js +0 -2
  36. package/dist/assets/shared-worker-CMeTcusa.js.map +0 -1
package/dist/node.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as StoreExistsError, A as prefixRange, B as DatabaseClosedError, C as compoundKey, Ct as isWorkerProtocolReadyEnvelope, D as indexKey, Dt as isWorkerProtocolResponseBatchMessage, E as encodeIndexScalar, F as utf8Encode, G as InvalidRangeError, Gt as isRecord$1, H as InjectedFailureError, Ht as workerProtocolError, I as ChangeFeedCompactedError, J as ReadonlyTransactionError, K as KeyTooLargeError, L as ConstraintError, M as splitCompoundKey, N as u64Key, Nt as prepareWorkerCommandPayload, O as jsonDecode, Ot as isWorkerProtocolResponseMessage, P as utf8Decode, Q as StorageError, R as CorruptionError, S as toPublicIndexDefinitions, T as encodeCompoundKeyParts, U as InternalError, Ut as clampTimerDelayMs, V as IndexNotFoundError, W as InvalidOpenOptionsError, Wt as compareStringsByCodeUnit, X as ReservedStoreNameError, Y as RecoveryRequiredError, Z as SerializationError, _ as indexRangeToPhysicalRange, a as createIndexKeyExtractor, at as UnsupportedPlatformError, b as normalizeIndexDefinitions, c as decodeIndexedDocument, ct as WriteTransactionAlreadyOpenError, d as encodeIndexMetadataValue, et as StoreNameTooLongError, f as extractLogicalIndexKey, ft as WORKER_PROTOCOL_REQUEST, g as indexKeyExactRange, gt as captureWorkerPayload, h as indexDefinitionIdentity, i as compareNormalizedIndexDefinitions, it as UniqueIndexConstraintError, j as prefixSuccessor, k as jsonEncode, l as encodeIndexEntryKey, lt as normalizeError, m as findIndexDefinition, n as assertPublicStoreName, nt as TransactionClosedError, o as decodeIndexEntryKey, ot as ValueTooLargeError, p as extractLogicalIndexKeyFromDocument, pt as WORKER_PROTOCOL_REQUEST_BATCH, q as MoyoDbError, r as cloneNormalizedIndexDefinitions, rt as TransactionConflictError, s as decodeIndexMetadataValue, st as VersionError, t as INDEX_METADATA_STORE, tt as StoreNotFoundError, u as encodeIndexMetadataKey, v as indexesForStore, vt as decodeWorkerResponsePayload, w as compoundKeyRange, wt as isWorkerProtocolReadyMessage, x as serializeNormalizedIndexDefinitions, y as isInternalStoreName, yt as deserializeWorkerError, z as DatabaseBusyError } from "./chunks/indexing-B0duqlUs.js";
1
+ import { $ as SerializationError, A as jsonDecode, At as isWorkerProtocolResponseMessage, B as CorruptionError, C as serializeNormalizedIndexDefinitions, D as encodeCompoundKeyParts, E as compoundKeyRange, Et as isWorkerProtocolReadyMessage, F as u64Key, Ft as prepareWorkerCommandPayload, G as InternalError, Gt as clampTimerDelayMs, H as DatabaseClosedError, I as utf8Decode, J as KeyTooLargeError, K as InvalidOpenOptionsError, Kt as compareStringsByCodeUnit, L as utf8Encode, M as prefixRange, N as prefixSuccessor, O as encodeIndexScalar, P as splitCompoundKey, Q as ReservedStoreNameError, R as ChangeFeedCompactedError, S as normalizeIndexDefinitions, T as compoundKey, Tt as isWorkerProtocolReadyEnvelope, U as IndexNotFoundError, V as DatabaseBusyError, W as InjectedFailureError, Wt as workerProtocolError, X as ReadonlyTransactionError, Y as MoyoDbError, Z as RecoveryRequiredError, _ as indexDefinitionIdentity, a as cloneNormalizedIndexDefinitions, at as TransactionConflictError, b as indexesForStore, bt as decodeWorkerResponsePayload, c as decodeIndexEntryKey, ct as ValueTooLargeError, d as encodeIndexEntryKey, dt as normalizeError, et as StorageError, f as encodeIndexMetadataKey, g as findIndexDefinition, h as extractLogicalIndexKeyFromDocument, ht as WORKER_PROTOCOL_REQUEST_BATCH, i as assertValidScanRange, it as TransactionClosedError, j as jsonEncode, k as indexKey, kt as isWorkerProtocolResponseBatchMessage, l as decodeIndexMetadataValue, lt as VersionError, m as extractLogicalIndexKey, mt as WORKER_PROTOCOL_REQUEST, n as MAX_ENGINE_SCAN_LIMIT, nt as StoreNameTooLongError, o as compareNormalizedIndexDefinitions, ot as UniqueIndexConstraintError, p as encodeIndexMetadataValue, q as InvalidRangeError, qt as isRecord$1, r as assertPublicStoreName, rt as StoreNotFoundError, s as createIndexKeyExtractor, st as UnsupportedPlatformError, t as INDEX_METADATA_STORE, tt as StoreExistsError, u as decodeIndexedDocument, ut as WriteTransactionAlreadyOpenError, v as indexKeyExactRange, vt as captureWorkerPayload, w as toPublicIndexDefinitions, x as isInternalStoreName, xt as deserializeWorkerError, y as indexRangeToPhysicalRange, z as ConstraintError } from "./chunks/indexing-DdpU69Fd.js";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
3
  import { realpath } from "node:fs/promises";
4
4
  import { dirname, join, resolve } from "node:path";
@@ -277,7 +277,7 @@ var WorkerProtocolClient = class {
277
277
  }, this.requestTimeoutMs) : null;
278
278
  this.pending.set(id, {
279
279
  command: responseCommand,
280
- resolve: (value) => resolve(value),
280
+ resolve,
281
281
  reject,
282
282
  timeout
283
283
  });
@@ -291,9 +291,21 @@ var WorkerProtocolClient = class {
291
291
  });
292
292
  }
293
293
  queueRequest(message, transfer) {
294
- const captured = captureWorkerPayload(message, transfer);
295
294
  if (!this.pending.has(message.id)) return;
296
- if (this.queuedRequests.length > 0 && this.queuedBytes + captured.byteLength > 1048576) this.flushRequests();
295
+ const byteLength = payloadBytes(message);
296
+ if (this.queuedRequests.length > 0 && this.queuedBytes + byteLength > 1048576) this.flushRequests();
297
+ if (this.queuedRequests.length + 1 >= 128 || this.queuedBytes + byteLength >= 1048576) {
298
+ this.queuedRequests.push({
299
+ message,
300
+ transfer,
301
+ byteLength
302
+ });
303
+ this.queuedBytes += byteLength;
304
+ this.flushRequests();
305
+ return;
306
+ }
307
+ const captured = snapshotQueuedPayload(message, transfer);
308
+ if (!this.pending.has(message.id)) return;
297
309
  this.queuedRequests.push({
298
310
  message: captured.value,
299
311
  transfer: captured.transfer,
@@ -307,7 +319,6 @@ var WorkerProtocolClient = class {
307
319
  this.flushRequests();
308
320
  });
309
321
  }
310
- if (this.queuedRequests.length >= 128 || this.queuedBytes >= 1048576) this.flushRequests();
311
322
  }
312
323
  flushRequests() {
313
324
  const queued = this.queuedRequests;
@@ -417,6 +428,203 @@ var WorkerProtocolClient = class {
417
428
  if (notifyFatal) this.fatalHandler?.(reason);
418
429
  }
419
430
  };
431
+ var STANDARD_VIEW_CONSTRUCTORS = /* @__PURE__ */ new Set([
432
+ DataView,
433
+ Uint8Array,
434
+ Uint8ClampedArray,
435
+ Uint16Array,
436
+ Uint32Array,
437
+ Int8Array,
438
+ Int16Array,
439
+ Int32Array,
440
+ Float32Array,
441
+ Float64Array,
442
+ BigInt64Array,
443
+ BigUint64Array
444
+ ]);
445
+ /**
446
+ * Freeze a queued payload so the later postMessage is its only structured clone.
447
+ * Listed buffers move now. Other ArrayBuffers are copied. SharedArrayBuffers stay shared.
448
+ */
449
+ function snapshotQueuedPayload(value, transfer) {
450
+ const moving = /* @__PURE__ */ new Set();
451
+ for (const item of transfer) {
452
+ if (!(item instanceof ArrayBuffer) || isResizableBuffer(item)) return captureWorkerPayload(value, transfer);
453
+ moving.add(item);
454
+ }
455
+ const geometries = /* @__PURE__ */ new Map();
456
+ if (!isPlainPayload(value, geometries, /* @__PURE__ */ new WeakSet())) return captureWorkerPayload(value, transfer);
457
+ const relocated = /* @__PURE__ */ new Map();
458
+ for (const buffer of moving) relocated.set(buffer, moveArrayBuffer(buffer));
459
+ const owned = [];
460
+ const seen = /* @__PURE__ */ new WeakMap();
461
+ const cloneValue = (item) => {
462
+ if (item === null || typeof item !== "object") return item;
463
+ const existing = seen.get(item);
464
+ if (existing !== void 0) return existing;
465
+ if (typeof SharedArrayBuffer !== "undefined" && item instanceof SharedArrayBuffer) {
466
+ seen.set(item, item);
467
+ return item;
468
+ }
469
+ if (item instanceof ArrayBuffer) {
470
+ const next = relocated.get(item) ?? item.slice(0);
471
+ seen.set(item, next);
472
+ owned.push(next);
473
+ return next;
474
+ }
475
+ if (ArrayBuffer.isView(item)) {
476
+ const geometry = geometries.get(item);
477
+ if (!geometry) throw workerProtocolError("WorkerProtocolError", "worker payload could not be queued");
478
+ const buffer = item.buffer;
479
+ const out = retargetView(item, typeof SharedArrayBuffer !== "undefined" && buffer instanceof SharedArrayBuffer ? buffer : cloneValue(buffer), geometry);
480
+ seen.set(item, out);
481
+ return out;
482
+ }
483
+ if (Array.isArray(item)) {
484
+ const out = new Array(item.length);
485
+ seen.set(item, out);
486
+ for (let index = 0; index < item.length; index += 1) if (index in item) out[index] = cloneValue(item[index]);
487
+ return out;
488
+ }
489
+ const out = Object.getPrototypeOf(item) === null ? Object.create(null) : {};
490
+ seen.set(item, out);
491
+ const record = item;
492
+ for (const key in record) if (Object.prototype.hasOwnProperty.call(record, key)) out[key] = cloneValue(record[key]);
493
+ return out;
494
+ };
495
+ const cloned = cloneValue(value);
496
+ return {
497
+ value: cloned,
498
+ transfer: owned,
499
+ byteLength: payloadBytes(cloned)
500
+ };
501
+ }
502
+ function payloadBytes(value) {
503
+ let byteLength = 0;
504
+ const seen = /* @__PURE__ */ new WeakSet();
505
+ const visit = (item) => {
506
+ if (!Number.isFinite(byteLength)) return;
507
+ if (typeof item === "string") {
508
+ byteLength += 8 + item.length * 2;
509
+ return;
510
+ }
511
+ if (item === null || typeof item !== "object") {
512
+ byteLength += 8;
513
+ return;
514
+ }
515
+ if (seen.has(item)) return;
516
+ seen.add(item);
517
+ byteLength += 8;
518
+ if (item instanceof ArrayBuffer) byteLength += item.byteLength;
519
+ else if (typeof SharedArrayBuffer !== "undefined" && item instanceof SharedArrayBuffer) byteLength += item.byteLength;
520
+ else if (ArrayBuffer.isView(item)) visit(item.buffer);
521
+ else if (Array.isArray(item)) {
522
+ if (Object.getPrototypeOf(item) !== Array.prototype || hasExtraKeys(item)) {
523
+ byteLength = Number.POSITIVE_INFINITY;
524
+ return;
525
+ }
526
+ for (let index = 0; index < item.length; index += 1) {
527
+ const descriptor = Object.getOwnPropertyDescriptor(item, String(index));
528
+ if (descriptor && !("value" in descriptor)) {
529
+ byteLength = Number.POSITIVE_INFINITY;
530
+ return;
531
+ }
532
+ visit(descriptor?.value);
533
+ }
534
+ } else if (item instanceof Map) for (const [key, child] of item) {
535
+ visit(key);
536
+ visit(child);
537
+ }
538
+ else if (item instanceof Set) for (const child of item) visit(child);
539
+ else {
540
+ const record = item;
541
+ for (const key in record) if (Object.prototype.hasOwnProperty.call(record, key)) {
542
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
543
+ if (key === "__proto__" || !descriptor || !("value" in descriptor)) {
544
+ byteLength = Number.POSITIVE_INFINITY;
545
+ return;
546
+ }
547
+ byteLength += 8 + key.length * 2;
548
+ visit(descriptor.value);
549
+ }
550
+ }
551
+ };
552
+ visit(value);
553
+ return byteLength;
554
+ }
555
+ function isPlainPayload(value, geometries, seen) {
556
+ if (typeof value === "function" || typeof value === "symbol") return false;
557
+ if (value === null || typeof value !== "object") return true;
558
+ if (seen.has(value)) return true;
559
+ seen.add(value);
560
+ if (typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer) return !isResizableBuffer(value);
561
+ if (value instanceof ArrayBuffer) return !isResizableBuffer(value);
562
+ if (ArrayBuffer.isView(value)) {
563
+ if (!isStandardView(value)) return false;
564
+ const buffer = value.buffer;
565
+ if (typeof SharedArrayBuffer !== "undefined" && buffer instanceof SharedArrayBuffer) {
566
+ if (isResizableBuffer(buffer)) return false;
567
+ geometries.set(value, viewGeometry(value));
568
+ return true;
569
+ }
570
+ if (!(buffer instanceof ArrayBuffer) || isResizableBuffer(buffer)) return false;
571
+ geometries.set(value, viewGeometry(value));
572
+ return true;
573
+ }
574
+ if (value instanceof Map || value instanceof Set || value instanceof Date || value instanceof RegExp) return false;
575
+ if (Array.isArray(value)) {
576
+ if (hasExtraKeys(value) || hasEnumerableSymbols(value)) return false;
577
+ for (const child of value) if (!isPlainPayload(child, geometries, seen)) return false;
578
+ return true;
579
+ }
580
+ const proto = Object.getPrototypeOf(value);
581
+ if (proto !== Object.prototype && proto !== null) return false;
582
+ if (hasEnumerableSymbols(value)) return false;
583
+ const record = value;
584
+ for (const key in record) if (Object.prototype.hasOwnProperty.call(record, key) && !isPlainPayload(record[key], geometries, seen)) return false;
585
+ return true;
586
+ }
587
+ function hasExtraKeys(value) {
588
+ const record = value;
589
+ for (const key in record) {
590
+ if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
591
+ const index = Number(key);
592
+ if (!Number.isInteger(index) || index < 0 || index >= value.length || String(index) !== key) return true;
593
+ }
594
+ return false;
595
+ }
596
+ function hasEnumerableSymbols(value) {
597
+ for (const symbol of Object.getOwnPropertySymbols(value)) if (Object.prototype.propertyIsEnumerable.call(value, symbol)) return true;
598
+ return false;
599
+ }
600
+ function isStandardView(view) {
601
+ return STANDARD_VIEW_CONSTRUCTORS.has(view.constructor);
602
+ }
603
+ function viewGeometry(view) {
604
+ if (view instanceof DataView) return {
605
+ offset: view.byteOffset,
606
+ length: view.byteLength,
607
+ dataView: true
608
+ };
609
+ return {
610
+ offset: view.byteOffset,
611
+ length: view.length,
612
+ dataView: false
613
+ };
614
+ }
615
+ function retargetView(view, buffer, geometry) {
616
+ if (geometry.dataView) return new DataView(buffer, geometry.offset, geometry.length);
617
+ const Typed = view.constructor;
618
+ return new Typed(buffer, geometry.offset, geometry.length);
619
+ }
620
+ function moveArrayBuffer(buffer) {
621
+ const movable = buffer;
622
+ if (typeof movable.transfer === "function") return movable.transfer();
623
+ return structuredClone(buffer, { transfer: [buffer] });
624
+ }
625
+ function isResizableBuffer(buffer) {
626
+ return buffer.resizable === true;
627
+ }
420
628
  //#endregion
421
629
  //#region src/registry.ts
422
630
  var VALID_FAILPOINTS = /* @__PURE__ */ new Set([
@@ -493,10 +701,15 @@ function normalizeOptions(options = {}) {
493
701
  function sameChangeFeed(left, right) {
494
702
  return left?.enabled === right?.enabled && left?.retainTxids === right?.retainTxids;
495
703
  }
704
+ function liveOptionsMismatch(dbName, current, next) {
705
+ if (current.workerMode !== next.workerMode) return `database ${dbName} is already open with workerMode=${current.workerMode}`;
706
+ if (current.cachePages !== next.cachePages) return `database ${dbName} is already open in this tab with cachePages=${current.cachePages}; requested cachePages=${next.cachePages}`;
707
+ if (next.changeFeed !== null && !sameChangeFeed(current.changeFeed, next.changeFeed)) return `database ${dbName} is already open in this tab with a different changeFeed policy`;
708
+ return null;
709
+ }
496
710
  function assertCompatibleOptions(dbName, current, next) {
497
- if (current.workerMode !== next.workerMode) throw new InvalidOpenOptionsError(`database ${dbName} is already open with workerMode=${current.workerMode}`);
498
- if (current.cachePages !== next.cachePages) throw new InvalidOpenOptionsError(`database ${dbName} is already open in this tab with cachePages=${current.cachePages}; requested cachePages=${next.cachePages}`);
499
- if (next.changeFeed !== null && !sameChangeFeed(current.changeFeed, next.changeFeed)) throw new InvalidOpenOptionsError(`database ${dbName} is already open in this tab with a different changeFeed policy`);
711
+ const mismatch = liveOptionsMismatch(dbName, current, next);
712
+ if (mismatch !== null) throw new InvalidOpenOptionsError(mismatch);
500
713
  }
501
714
  function emitListeners(listeners) {
502
715
  for (const listener of Array.from(listeners)) listener();
@@ -597,6 +810,45 @@ function hasKeyPrefix(key, prefix) {
597
810
  for (let index = 0; index < prefix.byteLength; index += 1) if (key[index] !== prefix[index]) return false;
598
811
  return true;
599
812
  }
813
+ function matchesPrefix(change, prefix) {
814
+ return change.kind === "clear" || change.kind === "drop" || hasKeyPrefix(change.key, prefix);
815
+ }
816
+ function includesStoreLevelChange(changes) {
817
+ for (let index = 0; index < changes.length; index += 1) {
818
+ const kind = changes[index].kind;
819
+ if (kind === "clear" || kind === "drop") return true;
820
+ }
821
+ return false;
822
+ }
823
+ function prefixBytesOverlap(left, right) {
824
+ const limit = Math.min(left.byteLength, right.byteLength);
825
+ for (let index = 0; index < limit; index += 1) if (left[index] !== right[index]) return false;
826
+ return true;
827
+ }
828
+ function sharedChanges(changes, prefix) {
829
+ if (prefix === null) return changes;
830
+ let selected = null;
831
+ for (let index = 0; index < changes.length; index += 1) {
832
+ const change = changes[index];
833
+ if (matchesPrefix(change, prefix)) {
834
+ if (selected !== null) selected.push(change);
835
+ continue;
836
+ }
837
+ if (selected === null) selected = changes.slice(0, index);
838
+ }
839
+ if (selected === null) return changes.length === 0 ? null : changes;
840
+ return selected.length === 0 ? null : selected;
841
+ }
842
+ function viewsIntersect(leftPrefix, rightPrefix, hasStoreLevel) {
843
+ if (leftPrefix === null || rightPrefix === null) return true;
844
+ if (prefixBytesOverlap(leftPrefix, rightPrefix)) return true;
845
+ return hasStoreLevel();
846
+ }
847
+ function laterViewIntersects(deliveries, index, hasStoreLevel) {
848
+ const prefix = deliveries[index].entry.keyPrefix;
849
+ for (let later = index + 1; later < deliveries.length; later += 1) if (viewsIntersect(prefix, deliveries[later].entry.keyPrefix, hasStoreLevel)) return true;
850
+ return false;
851
+ }
600
852
  function normalizeSubscriptionSpec(arg1, arg2, arg3) {
601
853
  if (typeof arg1 === "function") {
602
854
  if (arg2 !== void 0 || arg3 !== void 0) throw new TypeError("subscribe(callback) accepts exactly one callback argument");
@@ -673,23 +925,39 @@ var SubscriptionHub = class {
673
925
  #handleMessage(payload) {
674
926
  if (!isCommitAppliedEvent(payload) || payload.dbName !== this.#dbName || this.#entries.size === 0) return;
675
927
  const entries = Array.from(this.#entries);
676
- for (const storeEvent of payload.stores) for (const entry of entries) {
677
- if (!entry.active) continue;
678
- if (entry.store !== null && entry.store !== storeEvent.store) continue;
679
- let changes;
680
- const keyPrefix = entry.keyPrefix;
681
- if (keyPrefix === null) changes = cloneChanges(storeEvent.changes);
682
- else {
683
- changes = cloneChanges(storeEvent.changes.filter((change) => change.kind === "clear" || change.kind === "drop" || hasKeyPrefix(change.key, keyPrefix)));
684
- if (changes.length === 0) continue;
685
- }
686
- try {
687
- entry.callback(storeEvent.store, changes, payload.txid);
688
- } catch (error) {
689
- queueMicrotask(() => {
690
- throw error;
928
+ for (const storeEvent of payload.stores) {
929
+ const deliveries = [];
930
+ for (const entry of entries) {
931
+ if (!entry.active) continue;
932
+ if (entry.store !== null && entry.store !== storeEvent.store) continue;
933
+ const changes = sharedChanges(storeEvent.changes, entry.keyPrefix);
934
+ if (changes === null) continue;
935
+ deliveries.push({
936
+ entry,
937
+ changes
691
938
  });
692
939
  }
940
+ if (deliveries.length > 1) {
941
+ let storeLevel;
942
+ const hasStoreLevel = () => {
943
+ if (storeLevel === void 0) storeLevel = includesStoreLevelChange(storeEvent.changes);
944
+ return storeLevel;
945
+ };
946
+ for (let index = 0; index < deliveries.length; index += 1) {
947
+ if (!laterViewIntersects(deliveries, index, hasStoreLevel)) continue;
948
+ deliveries[index].changes = cloneChanges(deliveries[index].changes);
949
+ }
950
+ }
951
+ for (const delivery of deliveries) {
952
+ if (!delivery.entry.active) continue;
953
+ try {
954
+ delivery.entry.callback(storeEvent.store, delivery.changes, payload.txid);
955
+ } catch (error) {
956
+ queueMicrotask(() => {
957
+ throw error;
958
+ });
959
+ }
960
+ }
693
961
  }
694
962
  }
695
963
  };
@@ -2200,6 +2468,9 @@ function compareBytes(left, right) {
2200
2468
  var INDEX_SCAN_PAGE_ROWS = 256;
2201
2469
  var SCAN_PAGE_ROWS = 256;
2202
2470
  var SCAN_PAGE_BYTES = 8389662;
2471
+ /** Reused when a put has no ttl, or a scan range is omitted. Do not mutate. */
2472
+ var EMPTY_RANGE = Object.freeze({});
2473
+ var EMPTY_PUT_OPTIONS = Object.freeze({});
2203
2474
  async function callProxy(fn) {
2204
2475
  try {
2205
2476
  return await fn();
@@ -2239,12 +2510,12 @@ var TransactionImpl = class {
2239
2510
  assertPublicStoreName(store);
2240
2511
  return callProxy(() => this.#entry.proxy.has(this.#txId, store, key));
2241
2512
  }
2242
- async put(store, key, value, options = {}) {
2513
+ async put(store, key, value, options) {
2243
2514
  this.#ensureOpen();
2244
2515
  assertPublicStoreName(store);
2245
2516
  return callProxy(() => this.#entry.proxy.put(this.#txId, store, key, value, normalizePutOptions(options)));
2246
2517
  }
2247
- async putMany(store, entries, options = {}) {
2518
+ async putMany(store, entries, options) {
2248
2519
  this.#ensureOpen();
2249
2520
  assertPublicStoreName(store);
2250
2521
  return callProxy(() => this.#entry.proxy.putMany(this.#txId, store, entries, normalizePutOptions(options)));
@@ -2264,10 +2535,12 @@ var TransactionImpl = class {
2264
2535
  assertPublicStoreName(store);
2265
2536
  return callProxy(() => this.#entry.proxy.applyBatch(this.#txId, store, ops));
2266
2537
  }
2267
- async scan(store, range = {}) {
2538
+ async scan(store, range) {
2268
2539
  this.#ensureOpen();
2269
2540
  assertPublicStoreName(store);
2270
- return callProxy(() => this.#entry.proxy.scan(this.#txId, store, range));
2541
+ const bounds = range ?? EMPTY_RANGE;
2542
+ assertValidScanRange(bounds);
2543
+ return callProxy(() => this.#entry.proxy.scan(this.#txId, store, bounds));
2271
2544
  }
2272
2545
  async scanPage(store, range = {}, options = {}) {
2273
2546
  this.#ensureOpen();
@@ -2300,19 +2573,31 @@ var TransactionImpl = class {
2300
2573
  assertPublicStoreName(store);
2301
2574
  return callProxy(() => this.#entry.proxy.getByIndex(this.#txId, store, indexName, key));
2302
2575
  }
2303
- async *scanByIndex(store, indexName, range = {}, options = {}) {
2576
+ async *scanByIndex(store, indexName, range = EMPTY_RANGE, options = {}) {
2304
2577
  this.#ensureOpen();
2305
2578
  assertPublicStoreName(store);
2306
2579
  const { maxRows: pageRows, maxBytes } = normalizeScanPageOptions(options);
2580
+ const bounds = range;
2581
+ assertValidScanRange(bounds);
2307
2582
  let remaining = range.limit ?? Number.POSITIVE_INFINITY;
2308
2583
  let cursor = null;
2584
+ const proxy = this.#entry.proxy;
2585
+ const txId = this.#txId;
2309
2586
  while (remaining > 0) {
2310
2587
  this.#ensureOpen();
2311
2588
  const pageLimit = Math.min(remaining, pageRows, INDEX_SCAN_PAGE_ROWS);
2312
- const resumeAfter = cursor;
2313
- const page = await callProxy(() => this.#entry.proxy.scanByIndexPage(this.#txId, store, indexName, range, resumeAfter, pageLimit, maxBytes));
2314
- for (const row of page.rows) yield [row.key, row.value];
2315
- remaining -= page.rows.length;
2589
+ let page;
2590
+ try {
2591
+ page = await proxy.scanByIndexPage(txId, store, indexName, bounds, cursor, pageLimit, maxBytes);
2592
+ } catch (error) {
2593
+ throw normalizeError(error);
2594
+ }
2595
+ const rows = page.rows;
2596
+ for (let index = 0; index < rows.length; index += 1) {
2597
+ const row = rows[index];
2598
+ yield [row.key, row.value];
2599
+ }
2600
+ remaining -= rows.length;
2316
2601
  if (page.cursor === null) return;
2317
2602
  cursor = page.cursor;
2318
2603
  }
@@ -2490,7 +2775,7 @@ var DBImpl = class {
2490
2775
  assertPublicStoreName(store);
2491
2776
  return this.#autocommit("readonly", "has", [store, key]);
2492
2777
  }
2493
- async put(store, key, value, options = {}) {
2778
+ async put(store, key, value, options) {
2494
2779
  assertPublicStoreName(store);
2495
2780
  await this.#autocommit("readwrite", "put", [
2496
2781
  store,
@@ -2503,9 +2788,9 @@ var DBImpl = class {
2503
2788
  assertPublicStoreName(store);
2504
2789
  return this.#autocommit("readwrite", "delete", [store, key]);
2505
2790
  }
2506
- async scan(store, range = {}) {
2791
+ async scan(store, range) {
2507
2792
  assertPublicStoreName(store);
2508
- return this.#autocommit("readonly", "scan", [store, range]);
2793
+ return this.#autocommit("readonly", "scan", [store, range ?? EMPTY_RANGE]);
2509
2794
  }
2510
2795
  async scanPage(store, range = {}, options = {}) {
2511
2796
  this.#ensureOpen();
@@ -2695,10 +2980,10 @@ var MigrationTransactionImpl = class {
2695
2980
  async has(store, key) {
2696
2981
  return this.#inner.has(store, key);
2697
2982
  }
2698
- async put(store, key, value, options = {}) {
2983
+ async put(store, key, value, options) {
2699
2984
  await this.#inner.put(store, key, value, options);
2700
2985
  }
2701
- async putMany(store, entries, options = {}) {
2986
+ async putMany(store, entries, options) {
2702
2987
  await this.#inner.putMany(store, entries, options);
2703
2988
  }
2704
2989
  async delete(store, key) {
@@ -2710,7 +2995,7 @@ var MigrationTransactionImpl = class {
2710
2995
  async applyBatch(store, ops) {
2711
2996
  await this.#inner.applyBatch(store, ops);
2712
2997
  }
2713
- async scan(store, range = {}) {
2998
+ async scan(store, range) {
2714
2999
  return this.#inner.scan(store, range);
2715
3000
  }
2716
3001
  scanPage(store, range = {}, options = {}) {
@@ -2788,13 +3073,13 @@ var MigrationDbImpl = class {
2788
3073
  async has(store, key) {
2789
3074
  return this.#transaction.has(store, key);
2790
3075
  }
2791
- async put(store, key, value, options = {}) {
3076
+ async put(store, key, value, options) {
2792
3077
  await this.#transaction.put(store, key, value, options);
2793
3078
  }
2794
3079
  async delete(store, key) {
2795
3080
  return this.#transaction.delete(store, key);
2796
3081
  }
2797
- async scan(store, range = {}) {
3082
+ async scan(store, range) {
2798
3083
  return this.#transaction.scan(store, range);
2799
3084
  }
2800
3085
  scanPage(store, range = {}, options = {}) {
@@ -2929,9 +3214,12 @@ function normalizeSchemaVersion(value) {
2929
3214
  return normalizeOptionalNonNegativeSafeInteger(value, "version must be a non-negative safe integer", invalidOpenOptionsError);
2930
3215
  }
2931
3216
  function normalizePutOptions(options) {
2932
- const { ttl } = normalizeOptionsObject(options, "put options must be an object");
2933
- const normalizedTtl = normalizeOptionalNonNegativeSafeInteger(ttl, "ttl must be a non-negative safe integer");
2934
- return normalizedTtl === void 0 ? {} : { ttl: normalizedTtl };
3217
+ if (options === void 0) return EMPTY_PUT_OPTIONS;
3218
+ if (options === null || typeof options !== "object" || Array.isArray(options)) throw new TypeError("put options must be an object");
3219
+ const ttl = options.ttl;
3220
+ if (ttl === void 0) return EMPTY_PUT_OPTIONS;
3221
+ if (typeof ttl !== "number" || !Number.isSafeInteger(ttl) || ttl < 0) throw new TypeError("ttl must be a non-negative safe integer");
3222
+ return { ttl };
2935
3223
  }
2936
3224
  function normalizeCompressionOptions(options, message, allowSnappy) {
2937
3225
  const { compression } = normalizeOptionsObject(options, message);
@@ -3424,6 +3712,6 @@ async function unsafeDebugCrashNodeWorker(name, options) {
3424
3712
  });
3425
3713
  }
3426
3714
  //#endregion
3427
- export { ChangeFeedCompactedError, ConstraintError, CorruptionError, DatabaseBusyError, DatabaseClosedError, INDEX_METADATA_STORE, IndexNotFoundError, InjectedFailureError, InternalError, InvalidOpenOptionsError, InvalidRangeError, KeyTooLargeError, MoyoDbError, ReadonlyTransactionError, RecordIndex, RecordStore, RecoveryRequiredError, ReservedStoreNameError, SerializationError, SqlSchemaError, SqlSyntaxError, SqlTypeError, StorageError, StoreExistsError, StoreNameTooLongError, StoreNotFoundError, TransactionClosedError, TransactionConflictError, UniqueIndexConstraintError, UnsupportedPlatformError, ValueTooLargeError, VersionError, WriteTransactionAlreadyOpenError, assertPublicStoreName, cloneNormalizedIndexDefinitions, compareNormalizedIndexDefinitions, compoundKey, compoundKeyCodec, compoundKeyRange, createIndexKeyExtractor, createRecordStore, createSqlClient, decodeIndexEntryKey, decodeIndexMetadataValue, decodeIndexedDocument, deleteNodeDB, encodeCompoundKeyParts, encodeIndexEntryKey, encodeIndexMetadataKey, encodeIndexMetadataValue, encodeIndexScalar, extractLogicalIndexKey, extractLogicalIndexKeyFromDocument, findIndexDefinition, indexDefinitionIdentity, indexKey, indexKeyExactRange, indexRangeToPhysicalRange, indexesForStore, isInternalStoreName, jsonDecode, jsonEncode, jsonRecordCodec, keyCodecs, normalizeError, normalizeIndexDefinitions, openNodeDB, openRecordStore, prefixRange, prefixSuccessor, scalarKeyCodec, serializeNormalizedIndexDefinitions, splitCompoundKey, toPublicIndexDefinitions, u64Key, unsafeDebugCrashNodeWorker, utf8Decode, utf8Encode, withRecordTransaction };
3715
+ export { ChangeFeedCompactedError, ConstraintError, CorruptionError, DatabaseBusyError, DatabaseClosedError, INDEX_METADATA_STORE, IndexNotFoundError, InjectedFailureError, InternalError, InvalidOpenOptionsError, InvalidRangeError, KeyTooLargeError, MAX_ENGINE_SCAN_LIMIT, MoyoDbError, ReadonlyTransactionError, RecordIndex, RecordStore, RecoveryRequiredError, ReservedStoreNameError, SerializationError, SqlSchemaError, SqlSyntaxError, SqlTypeError, StorageError, StoreExistsError, StoreNameTooLongError, StoreNotFoundError, TransactionClosedError, TransactionConflictError, UniqueIndexConstraintError, UnsupportedPlatformError, ValueTooLargeError, VersionError, WriteTransactionAlreadyOpenError, assertPublicStoreName, assertValidScanRange, cloneNormalizedIndexDefinitions, compareNormalizedIndexDefinitions, compoundKey, compoundKeyCodec, compoundKeyRange, createIndexKeyExtractor, createRecordStore, createSqlClient, decodeIndexEntryKey, decodeIndexMetadataValue, decodeIndexedDocument, deleteNodeDB, encodeCompoundKeyParts, encodeIndexEntryKey, encodeIndexMetadataKey, encodeIndexMetadataValue, encodeIndexScalar, extractLogicalIndexKey, extractLogicalIndexKeyFromDocument, findIndexDefinition, indexDefinitionIdentity, indexKey, indexKeyExactRange, indexRangeToPhysicalRange, indexesForStore, isInternalStoreName, jsonDecode, jsonEncode, jsonRecordCodec, keyCodecs, normalizeError, normalizeIndexDefinitions, openNodeDB, openRecordStore, prefixRange, prefixSuccessor, scalarKeyCodec, serializeNormalizedIndexDefinitions, splitCompoundKey, toPublicIndexDefinitions, u64Key, unsafeDebugCrashNodeWorker, utf8Decode, utf8Encode, withRecordTransaction };
3428
3716
 
3429
3717
  //# sourceMappingURL=node.js.map