@rocicorp/zero 0.12.2025013000 → 0.12.2025013100

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 (123) hide show
  1. package/out/advanced.js +1 -1
  2. package/out/chunk-ALG35NEG.js +1 -0
  3. package/out/{chunk-UEPZPKPV.js → chunk-XBQPXRPX.js} +1505 -1542
  4. package/out/chunk-XBQPXRPX.js.map +7 -0
  5. package/out/react.js.map +2 -2
  6. package/out/replicache/src/types.d.ts +2 -2
  7. package/out/replicache/src/types.d.ts.map +1 -1
  8. package/out/solid.js +2 -2
  9. package/out/solid.js.map +2 -2
  10. package/out/zero/src/advanced.d.ts.map +1 -1
  11. package/out/zero/src/react.d.ts.map +1 -1
  12. package/out/zero/src/solid.d.ts.map +1 -1
  13. package/out/zero/src/zero.d.ts.map +1 -1
  14. package/out/zero-cache/src/auth/write-authorizer.d.ts +1 -1
  15. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  16. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  17. package/out/zero-cache/src/db/delete-lite-db.js +1 -1
  18. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  19. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +0 -2
  20. package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
  21. package/out/zero-cache/src/services/change-streamer/error-type-enum.js +0 -1
  22. package/out/zero-cache/src/services/change-streamer/error-type-enum.js.map +1 -1
  23. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  24. package/out/zero-cache/src/services/change-streamer/storer.js +4 -5
  25. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  26. package/out/zero-cache/src/services/http-service.js +2 -2
  27. package/out/zero-cache/src/services/http-service.js.map +1 -1
  28. package/out/zero-cache/src/services/life-cycle.d.ts +2 -1
  29. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  30. package/out/zero-cache/src/services/life-cycle.js +3 -3
  31. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  32. package/out/zero-cache/src/services/running-state.js +1 -1
  33. package/out/zero-cache/src/services/running-state.js.map +1 -1
  34. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +1 -1
  35. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  36. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  37. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +3 -1
  38. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  39. package/out/zero-cache/src/services/view-syncer/view-syncer.js +0 -1
  40. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  41. package/out/zero-cache/src/workers/connection.d.ts +1 -1
  42. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  43. package/out/zero-cache/src/workers/connection.js +1 -1
  44. package/out/zero-cache/src/workers/connection.js.map +1 -1
  45. package/out/zero-cache/src/workers/syncer.d.ts +1 -1
  46. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  47. package/out/zero-cache/src/workers/syncer.js +2 -2
  48. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  49. package/out/zero-client/src/client/context.d.ts +2 -2
  50. package/out/zero-client/src/client/context.d.ts.map +1 -1
  51. package/out/zero-client/src/client/crud.d.ts +1 -1
  52. package/out/zero-client/src/client/crud.d.ts.map +1 -1
  53. package/out/zero-client/src/client/custom.d.ts +3 -1
  54. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  55. package/out/zero-client/src/client/log-options.d.ts +1 -1
  56. package/out/zero-client/src/client/log-options.d.ts.map +1 -1
  57. package/out/zero-client/src/client/options.d.ts +4 -4
  58. package/out/zero-client/src/client/options.d.ts.map +1 -1
  59. package/out/zero-client/src/client/query-manager.d.ts +4 -3
  60. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  61. package/out/zero-client/src/client/replicache-types.d.ts +3 -1
  62. package/out/zero-client/src/client/replicache-types.d.ts.map +1 -1
  63. package/out/zero-client/src/client/zero-poke-handler.d.ts +2 -2
  64. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  65. package/out/zero-client/src/client/zero.d.ts +7 -3
  66. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  67. package/out/zero-client/src/mod.d.ts +13 -3
  68. package/out/zero-client/src/mod.d.ts.map +1 -1
  69. package/out/zero-client/src/types/client-state.d.ts +1 -1
  70. package/out/zero-client/src/types/client-state.d.ts.map +1 -1
  71. package/out/zero-react/src/use-query.d.ts +2 -2
  72. package/out/zero-react/src/use-query.d.ts.map +1 -1
  73. package/out/zero-react/src/use-zero.d.ts +2 -2
  74. package/out/zero-react/src/use-zero.d.ts.map +1 -1
  75. package/out/zero-schema/src/build-schema.js +1 -0
  76. package/out/zero-schema/src/build-schema.js.map +1 -1
  77. package/out/zero-schema/src/builder/relationship-builder.d.ts.map +1 -1
  78. package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
  79. package/out/zero-schema/src/permissions.d.ts +1 -1
  80. package/out/zero-schema/src/permissions.d.ts.map +1 -1
  81. package/out/zero-solid/src/create-zero.d.ts +1 -2
  82. package/out/zero-solid/src/create-zero.d.ts.map +1 -1
  83. package/out/zero-solid/src/solid-view.d.ts +2 -3
  84. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  85. package/out/zero-solid/src/use-query.d.ts +2 -2
  86. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  87. package/out/zero.js +1 -1
  88. package/package.json +1 -1
  89. package/out/chunk-UEPZPKPV.js.map +0 -7
  90. package/out/chunk-ULOTOBTC.js +0 -1
  91. package/out/datadog/src/mod.d.ts +0 -2
  92. package/out/datadog/src/mod.d.ts.map +0 -1
  93. package/out/replicache/src/filter-async-iterable.d.ts +0 -10
  94. package/out/replicache/src/filter-async-iterable.d.ts.map +0 -1
  95. package/out/replicache/src/merge-async-iterables.d.ts +0 -16
  96. package/out/replicache/src/merge-async-iterables.d.ts.map +0 -1
  97. package/out/replicache/src/mod.d.ts +0 -39
  98. package/out/replicache/src/mod.d.ts.map +0 -1
  99. package/out/replicache/src/test-license-key.d.ts +0 -3
  100. package/out/replicache/src/test-license-key.d.ts.map +0 -1
  101. package/out/zero/src/change-protocol.d.ts +0 -2
  102. package/out/zero/src/change-protocol.d.ts.map +0 -1
  103. package/out/zero/src/change-protocol.js +0 -2
  104. package/out/zero/src/change-protocol.js.map +0 -1
  105. package/out/zero-cache/src/services/change-source/protocol/current/mod.d.ts +0 -7
  106. package/out/zero-cache/src/services/change-source/protocol/current/mod.d.ts.map +0 -1
  107. package/out/zero-cache/src/services/change-source/protocol/current/mod.js +0 -7
  108. package/out/zero-cache/src/services/change-source/protocol/current/mod.js.map +0 -1
  109. package/out/zero-cache/src/services/change-source/protocol/current/path.d.ts +0 -20
  110. package/out/zero-cache/src/services/change-source/protocol/current/path.d.ts.map +0 -1
  111. package/out/zero-cache/src/services/change-source/protocol/current/path.js +0 -20
  112. package/out/zero-cache/src/services/change-source/protocol/current/path.js.map +0 -1
  113. package/out/zero-cache/src/services/change-source/protocol/mod.d.ts +0 -2
  114. package/out/zero-cache/src/services/change-source/protocol/mod.d.ts.map +0 -1
  115. package/out/zero-cache/src/services/change-source/protocol/mod.js +0 -5
  116. package/out/zero-cache/src/services/change-source/protocol/mod.js.map +0 -1
  117. package/out/zero-protocol/src/mod.d.ts +0 -15
  118. package/out/zero-protocol/src/mod.d.ts.map +0 -1
  119. package/out/zero-protocol/src/mod.js +0 -16
  120. package/out/zero-protocol/src/mod.js.map +0 -1
  121. package/out/zero-schema/src/mod.d.ts +0 -5
  122. package/out/zero-schema/src/mod.d.ts.map +0 -1
  123. /package/out/{chunk-ULOTOBTC.js.map → chunk-ALG35NEG.js.map} +0 -0
@@ -715,1118 +715,1333 @@ var IDBNotFoundError = class extends Error {
715
715
  name = "IDBNotFoundError";
716
716
  };
717
717
 
718
- // ../replicache/src/transaction-closed-error.ts
719
- var TransactionClosedError = class extends Error {
720
- constructor() {
721
- super("Transaction is closed");
722
- }
723
- };
724
- function throwIfClosed(tx) {
725
- if (tx.closed) {
726
- throw new TransactionClosedError();
727
- }
728
- }
729
- function rejectIfClosed(tx) {
730
- return tx.closed ? Promise.reject(new TransactionClosedError()) : void 0;
731
- }
732
-
733
- // ../replicache/src/format-version-enum.ts
734
- var DD31 = 5;
735
- var V6 = 6;
736
- var V7 = 7;
737
- var Latest = V7;
738
-
739
- // ../shared/src/navigator.ts
740
- var localNavigator = typeof navigator !== "undefined" ? navigator : void 0;
741
-
742
- // ../replicache/src/kv/mem-store.ts
743
- import { RWLock } from "@rocicorp/lock";
744
-
745
- // ../replicache/src/kv/read-impl.ts
746
- var ReadImpl2 = class {
747
- #map;
748
- #release;
749
- #closed = false;
750
- constructor(map, release) {
751
- this.#map = map;
752
- this.#release = release;
753
- }
754
- release() {
755
- this.#release();
756
- this.#closed = true;
757
- }
758
- get closed() {
759
- return this.#closed;
760
- }
761
- has(key) {
762
- return Promise.resolve(this.#map.has(key));
763
- }
764
- get(key) {
765
- return Promise.resolve(this.#map.get(key));
766
- }
718
+ // ../shared/src/abort-error.ts
719
+ var AbortError = class extends Error {
720
+ name = "AbortError";
767
721
  };
768
722
 
769
- // ../replicache/src/kv/write-impl.ts
770
- var WriteImpl2 = class extends WriteImplBase {
771
- #map;
772
- constructor(map, release) {
773
- super(new ReadImpl2(map, release));
774
- this.#map = map;
723
+ // ../shared/src/sleep.ts
724
+ import { resolver as resolver2 } from "@rocicorp/resolver";
725
+ var promiseVoid2 = Promise.resolve();
726
+ var promiseNever = new Promise(() => void 0);
727
+ function sleep(ms, signal) {
728
+ const newAbortError = () => new AbortError("Aborted");
729
+ if (signal?.aborted) {
730
+ return Promise.reject(newAbortError());
775
731
  }
776
- commit() {
777
- this._pending.forEach((value, key) => {
778
- if (value === deleteSentinel) {
779
- this.#map.delete(key);
780
- } else {
781
- this.#map.set(key, value);
782
- }
783
- });
784
- this._pending.clear();
785
- this.release();
786
- return promiseVoid;
732
+ if (ms === 0) {
733
+ return promiseVoid2;
787
734
  }
788
- };
789
-
790
- // ../replicache/src/kv/mem-store.ts
791
- var stores = /* @__PURE__ */ new Map();
792
- function dropMemStore(name) {
793
- stores.delete(name);
794
- return promiseVoid;
795
- }
796
- var MemStore = class {
797
- #map;
798
- #rwLock;
799
- #closed = false;
800
- constructor(name) {
801
- const entry = stores.get(name);
802
- let lock;
803
- let map;
804
- if (entry) {
805
- ({ lock, map } = entry);
806
- } else {
807
- lock = new RWLock();
808
- map = /* @__PURE__ */ new Map();
809
- stores.set(name, { lock, map });
735
+ return new Promise((resolve, reject) => {
736
+ let handleAbort;
737
+ if (signal) {
738
+ handleAbort = () => {
739
+ clearTimeout(id);
740
+ reject(newAbortError());
741
+ };
742
+ signal.addEventListener("abort", handleAbort, { once: true });
810
743
  }
811
- this.#rwLock = lock;
812
- this.#map = map;
813
- }
814
- async read() {
815
- const release = await this.#rwLock.read();
816
- return new ReadImpl2(this.#map, release);
817
- }
818
- async write() {
819
- const release = await this.#rwLock.write();
820
- return new WriteImpl2(this.#map, release);
821
- }
822
- close() {
823
- this.#closed = true;
824
- return promiseVoid;
825
- }
826
- get closed() {
827
- return this.#closed;
744
+ const id = setTimeout(() => {
745
+ resolve();
746
+ signal?.removeEventListener("abort", handleAbort);
747
+ }, ms);
748
+ });
749
+ }
750
+ function sleepWithAbort(ms, signal) {
751
+ if (ms === 0) {
752
+ return [promiseVoid2, promiseNever];
828
753
  }
829
- };
754
+ const { promise: abortedPromise, resolve: abortedResolve } = resolver2();
755
+ const sleepPromise = new Promise((resolve) => {
756
+ const handleAbort = () => {
757
+ clearTimeout(id);
758
+ abortedResolve();
759
+ };
760
+ const id = setTimeout(() => {
761
+ resolve();
762
+ signal.removeEventListener("abort", handleAbort);
763
+ }, ms);
764
+ signal.addEventListener("abort", handleAbort, { once: true });
765
+ });
766
+ return [sleepPromise, abortedPromise];
767
+ }
830
768
 
831
- // ../replicache/src/kv/idb-store-with-mem-fallback.ts
832
- var IDBStoreWithMemFallback = class {
833
- #lc;
834
- #name;
835
- #store;
836
- constructor(lc, name) {
837
- this.#lc = lc;
838
- this.#name = name;
839
- this.#store = new IDBStore(name);
840
- }
841
- read() {
842
- return this.#withBrainTransplant((s) => s.read());
843
- }
844
- write() {
845
- return this.#withBrainTransplant((s) => s.write());
769
+ // ../replicache/src/bg-interval.ts
770
+ function initBgIntervalProcess(processName, process2, delayMs, lc, signal) {
771
+ void runBgIntervalProcess(processName, process2, delayMs, lc, signal);
772
+ }
773
+ async function runBgIntervalProcess(processName, process2, delayMs, lc, signal) {
774
+ if (signal.aborted) {
775
+ return;
846
776
  }
847
- async #withBrainTransplant(f) {
777
+ lc = lc.withContext("bgIntervalProcess", processName);
778
+ lc.debug?.("Starting");
779
+ while (!signal.aborted) {
848
780
  try {
849
- return await f(this.#store);
781
+ await sleep(delayMs(), signal);
850
782
  } catch (e) {
851
- if (isFirefoxPrivateBrowsingError(e)) {
852
- if (this.#store instanceof IDBStore) {
853
- this.#lc.info?.(
854
- "Switching to MemStore because of Firefox private browsing error"
855
- );
856
- this.#store = new MemStore(this.#name);
783
+ if (!(e instanceof AbortError)) {
784
+ throw e;
785
+ }
786
+ }
787
+ if (!signal.aborted) {
788
+ lc.debug?.("Running");
789
+ try {
790
+ await process2();
791
+ } catch (e) {
792
+ if (signal.aborted) {
793
+ lc.debug?.("Error running most likely due to close.", e);
794
+ } else {
795
+ lc.error?.("Error running.", e);
857
796
  }
858
- return f(this.#store);
859
797
  }
860
- throw e;
861
798
  }
862
799
  }
863
- close() {
864
- return this.#store.close();
865
- }
866
- get closed() {
867
- return this.#store.closed;
868
- }
869
- };
870
- function isFirefoxPrivateBrowsingError(e) {
871
- return isFirefox() && e instanceof DOMException && e.name === "InvalidStateError" && e.message === "A mutation operation was attempted on a database that did not allow mutations.";
800
+ lc.debug?.("Stopping");
872
801
  }
873
- function isFirefox() {
874
- return localNavigator?.userAgent.includes("Firefox") ?? false;
802
+
803
+ // ../shared/src/random-uint64.ts
804
+ function randomUint64() {
805
+ const high = Math.floor(Math.random() * 4294967295);
806
+ const low = Math.floor(Math.random() * 4294967295);
807
+ return BigInt(high) << 32n | BigInt(low);
875
808
  }
876
- function newIDBStoreWithMemFallback(lc, name) {
877
- if (isFirefox()) {
878
- return new IDBStoreWithMemFallback(lc, name);
809
+
810
+ // ../shared/src/valita.ts
811
+ var valita_exports = {};
812
+ __export(valita_exports, {
813
+ assert: () => assert2,
814
+ deepPartial: () => deepPartial,
815
+ instanceOfAbstractType: () => instanceOfAbstractType,
816
+ is: () => is,
817
+ parse: () => parse,
818
+ readonly: () => readonly,
819
+ readonlyArray: () => readonlyArray,
820
+ readonlyObject: () => readonlyObject,
821
+ readonlyRecord: () => readonlyRecord,
822
+ test: () => test,
823
+ testOptional: () => testOptional
824
+ });
825
+ __reExport(valita_exports, valita_star);
826
+ import * as v from "@badrap/valita";
827
+ import * as valita_star from "@badrap/valita";
828
+ function toDisplay(value) {
829
+ switch (typeof value) {
830
+ case "string":
831
+ case "number":
832
+ case "boolean":
833
+ return JSON.stringify(value);
834
+ case "undefined":
835
+ return "undefined";
836
+ case "bigint":
837
+ return value.toString() + "n";
838
+ default:
839
+ if (value === null) {
840
+ return "null";
841
+ }
842
+ if (Array.isArray(value)) {
843
+ return "array";
844
+ }
845
+ return typeof value;
879
846
  }
880
- return new IDBStore(name);
881
847
  }
882
- function dropIDBStoreWithMemFallback(name) {
883
- if (!isFirefox()) {
884
- return dropIDBStore(name);
848
+ function toDisplayAtPath(v2, path2) {
849
+ if (!path2?.length) {
850
+ return toDisplay(v2);
885
851
  }
886
- try {
887
- return dropIDBStore(name);
888
- } catch (e) {
889
- if (isFirefoxPrivateBrowsingError(e)) {
890
- return dropMemStore(name);
891
- }
852
+ let cur = v2;
853
+ for (const p of path2) {
854
+ cur = cur[p];
892
855
  }
893
- return promiseVoid;
894
- }
895
- function dropIDBStore(name) {
896
- return new Promise((resolve, reject) => {
897
- const req = indexedDB.deleteDatabase(name);
898
- req.onsuccess = () => resolve();
899
- req.onerror = () => reject(req.error);
900
- });
901
- }
902
-
903
- // ../replicache/src/replicache-impl.ts
904
- import { Lock as Lock2 } from "@rocicorp/lock";
905
- import { consoleLogSink as consoleLogSink2 } from "@rocicorp/logger";
906
- import { resolver as resolver6 } from "@rocicorp/resolver";
907
-
908
- // ../shared/src/abort-error.ts
909
- var AbortError = class extends Error {
910
- name = "AbortError";
911
- };
912
-
913
- // ../shared/src/document-visible.ts
914
- import { resolver as resolver2 } from "@rocicorp/resolver";
915
- function getDocumentVisibilityWatcher(doc, hiddenIntervalMS, signal) {
916
- return doc ? new DocumentVisibilityWatcherImpl(doc, hiddenIntervalMS, signal) : new DocumentVisibilityWatcherNoDoc();
856
+ return toDisplay(cur);
917
857
  }
918
- var DocumentVisibilityWatcherImpl = class {
919
- #doc;
920
- #hiddenIntervalMS;
921
- #timeoutID = 0;
922
- // This trails doc.visibilityState by hiddenIntervalMS when being hidden. This
923
- // is because we want to wait for the tab to be hidden for a while before
924
- // considering as hidden.
925
- visibilityState;
926
- #promises = /* @__PURE__ */ new Set();
927
- constructor(doc, hiddenIntervalMS, signal) {
928
- this.#doc = doc;
929
- this.#hiddenIntervalMS = hiddenIntervalMS;
930
- this.visibilityState = doc.visibilityState;
931
- this.#doc.addEventListener("visibilitychange", this.#onVisibilityChange, {
932
- signal
933
- });
858
+ function displayList(word, expected, toDisplay2 = (x) => String(x)) {
859
+ if (expected.length === 1) {
860
+ return toDisplay2(expected[0]);
934
861
  }
935
- #onVisibilityChange = () => {
936
- if (this.#doc.visibilityState === "visible") {
937
- clearTimeout(this.#timeoutID);
938
- this.#setVisibilityState("visible");
939
- } else {
940
- this.#timeoutID = setTimeout(() => {
941
- this.#setVisibilityState("hidden");
942
- }, this.#hiddenIntervalMS);
862
+ const suffix = `${toDisplay2(
863
+ expected[expected.length - 2]
864
+ )} ${word} ${toDisplay2(expected[expected.length - 1])}`;
865
+ if (expected.length === 2) {
866
+ return suffix;
867
+ }
868
+ return `${expected.slice(0, -2).map(toDisplay2).join(", ")}, ${suffix}`;
869
+ }
870
+ function getMessage(err2, v2, schema, mode) {
871
+ const firstIssue = err2.issues[0];
872
+ const { path: path2 } = firstIssue;
873
+ const atPath = path2?.length ? ` at ${path2.join(".")}` : "";
874
+ switch (firstIssue.code) {
875
+ case "invalid_type":
876
+ return `Expected ${displayList(
877
+ "or",
878
+ firstIssue.expected
879
+ )}${atPath}. Got ${toDisplayAtPath(v2, path2)}`;
880
+ case "missing_value": {
881
+ const atPath2 = path2 && path2.length > 1 ? ` at ${path2.slice(0, -1).join(".")}` : "";
882
+ if (firstIssue.path?.length) {
883
+ return `Missing property ${firstIssue.path.at(-1)}${atPath2}`;
884
+ }
885
+ return `TODO Unknown missing property${atPath2}`;
943
886
  }
944
- };
945
- #setVisibilityState(visibilityState) {
946
- if (visibilityState === this.visibilityState) {
947
- return;
887
+ case "invalid_literal":
888
+ return `Expected literal value ${displayList(
889
+ "or",
890
+ firstIssue.expected,
891
+ toDisplay
892
+ )}${atPath} Got ${toDisplayAtPath(v2, path2)}`;
893
+ case "invalid_length": {
894
+ return `Expected array with length ${firstIssue.minLength === firstIssue.maxLength ? firstIssue.minLength : `between ${firstIssue.minLength} and ${firstIssue.maxLength}`}${atPath}. Got array with length ${v2.length}`;
948
895
  }
949
- this.visibilityState = visibilityState;
950
- for (const entry of this.#promises) {
951
- const { resolve, state } = entry;
952
- if (state === visibilityState) {
953
- resolve();
954
- this.#promises.delete(entry);
896
+ case "unrecognized_keys":
897
+ if (firstIssue.keys.length === 1) {
898
+ return `Unexpected property ${firstIssue.keys[0]}${atPath}`;
955
899
  }
900
+ return `Unexpected properties ${displayList(
901
+ "and",
902
+ firstIssue.keys
903
+ )}${atPath}`;
904
+ case "invalid_union":
905
+ return schema.name === "union" ? getDeepestUnionParseError(v2, schema, mode ?? "strict") : `Invalid union value${atPath}`;
906
+ case "custom_error": {
907
+ const { error } = firstIssue;
908
+ const message = !error ? "unknown" : typeof error === "string" ? error : error.message ?? "unknown";
909
+ return `${message}${atPath}. Got ${toDisplayAtPath(v2, path2)}`;
956
910
  }
957
911
  }
958
- waitForVisible() {
959
- return this.#waitFor("visible");
960
- }
961
- waitForHidden() {
962
- return this.#waitFor("hidden");
963
- }
964
- #waitFor(state) {
965
- if (this.visibilityState === state) {
966
- return Promise.resolve();
912
+ }
913
+ function getDeepestUnionParseError(value, schema, mode) {
914
+ const failures = [];
915
+ for (const type of schema.options) {
916
+ const r = type.try(value, { mode });
917
+ if (!r.ok) {
918
+ failures.push({ type, err: r });
967
919
  }
968
- const { promise, resolve } = resolver2();
969
- this.#promises.add({ resolve, state });
970
- return promise;
971
- }
972
- };
973
- var resolvedPromise = Promise.resolve();
974
- var promiseThatNeverResolves = new Promise(() => void 0);
975
- var DocumentVisibilityWatcherNoDoc = class {
976
- visibilityState = "visible";
977
- waitForVisible() {
978
- return resolvedPromise;
979
920
  }
980
- waitForHidden() {
981
- return promiseThatNeverResolves;
921
+ if (failures.length) {
922
+ failures.sort(pathCmp);
923
+ if (failures.length === 1 || pathCmp(failures[0], failures[1]) < 0) {
924
+ return getMessage(failures[0].err, value, failures[0].type, mode);
925
+ }
982
926
  }
983
- };
984
-
985
- // ../replicache/src/connection-loop-delegates.ts
986
- var ConnectionLoopDelegateImpl = class {
987
- rep;
988
- invokeSend;
989
- // TODO: Remove the ability to have more than one concurrent connection and update tests.
990
- // Bug: https://github.com/rocicorp/replicache-internal/issues/303
991
- maxConnections = 1;
992
- constructor(rep, invokeSend) {
993
- this.rep = rep;
994
- this.invokeSend = invokeSend;
927
+ try {
928
+ const str = JSON.stringify(value);
929
+ return `Invalid union value: ${str}`;
930
+ } catch (e) {
931
+ return `Invalid union value`;
995
932
  }
996
- get maxDelayMs() {
997
- return this.rep.requestOptions.maxDelayMs;
933
+ }
934
+ function pathCmp(a, b) {
935
+ const aPath = a.err.issues[0].path;
936
+ const bPath = b.err.issues[0].path;
937
+ if (aPath.length !== bPath.length) {
938
+ return bPath.length - aPath.length;
998
939
  }
999
- get minDelayMs() {
1000
- return this.rep.requestOptions.minDelayMs;
940
+ for (let i = 0; i < aPath.length; i++) {
941
+ if (bPath[i] > aPath[i]) {
942
+ return -1;
943
+ }
944
+ if (bPath[i] < aPath[i]) {
945
+ return 1;
946
+ }
1001
947
  }
1002
- };
1003
- var PullDelegate = class extends ConnectionLoopDelegateImpl {
1004
- debounceDelay = 0;
1005
- get watchdogTimer() {
1006
- return this.rep.pullInterval;
948
+ return 0;
949
+ }
950
+ function parse(value, schema, mode) {
951
+ const res = test(value, schema, mode);
952
+ if (!res.ok) {
953
+ throw new TypeError(res.error);
1007
954
  }
1008
- };
1009
- var PushDelegate = class extends ConnectionLoopDelegateImpl {
1010
- get debounceDelay() {
1011
- return this.rep.pushDelay;
955
+ return res.value;
956
+ }
957
+ function is(value, schema, mode) {
958
+ return test(value, schema, mode).ok;
959
+ }
960
+ function assert2(value, schema, mode) {
961
+ parse(value, schema, mode);
962
+ }
963
+ function test(value, schema, mode) {
964
+ const res = schema.try(value, mode ? { mode } : void 0);
965
+ if (!res.ok) {
966
+ return {
967
+ ok: false,
968
+ error: getMessage(res, value, schema, mode)
969
+ };
1012
970
  }
1013
- watchdogTimer = null;
1014
- };
1015
-
1016
- // ../replicache/src/connection-loop.ts
1017
- import { resolver as resolver4 } from "@rocicorp/resolver";
1018
-
1019
- // ../shared/src/sleep.ts
1020
- import { resolver as resolver3 } from "@rocicorp/resolver";
1021
- var promiseVoid2 = Promise.resolve();
1022
- var promiseNever = new Promise(() => void 0);
1023
- function sleep(ms, signal) {
1024
- const newAbortError = () => new AbortError("Aborted");
1025
- if (signal?.aborted) {
1026
- return Promise.reject(newAbortError());
971
+ return res;
972
+ }
973
+ function testOptional(value, schema, mode) {
974
+ let flags = 1;
975
+ if (mode === "passthrough") {
976
+ flags = 0;
977
+ } else if (mode === "strip") {
978
+ flags = 2;
1027
979
  }
1028
- if (ms === 0) {
1029
- return promiseVoid2;
980
+ const res = schema.func(value, flags);
981
+ if (res === void 0) {
982
+ return { ok: true, value };
983
+ } else if (res.ok) {
984
+ return res;
1030
985
  }
1031
- return new Promise((resolve, reject) => {
1032
- let handleAbort;
1033
- if (signal) {
1034
- handleAbort = () => {
1035
- clearTimeout(id);
1036
- reject(newAbortError());
1037
- };
1038
- signal.addEventListener("abort", handleAbort, { once: true });
1039
- }
1040
- const id = setTimeout(() => {
1041
- resolve();
1042
- signal?.removeEventListener("abort", handleAbort);
1043
- }, ms);
1044
- });
986
+ const err2 = new v.ValitaError(res);
987
+ return { ok: false, error: getMessage(err2, value, schema, mode) };
1045
988
  }
1046
- function sleepWithAbort(ms, signal) {
1047
- if (ms === 0) {
1048
- return [promiseVoid2, promiseNever];
989
+ function readonly(t2) {
990
+ return t2;
991
+ }
992
+ function readonlyObject(t2) {
993
+ return v.object(t2);
994
+ }
995
+ function readonlyArray(t2) {
996
+ return v.array(t2);
997
+ }
998
+ function readonlyRecord(t2) {
999
+ return v.record(t2);
1000
+ }
1001
+ var AbstractType = Object.getPrototypeOf(
1002
+ Object.getPrototypeOf(v.string().optional())
1003
+ ).constructor;
1004
+ function instanceOfAbstractType(obj) {
1005
+ return obj instanceof AbstractType;
1006
+ }
1007
+ function deepPartial(s) {
1008
+ const shape = {};
1009
+ for (const [key, type] of Object.entries(s.shape)) {
1010
+ if (type.name === "object") {
1011
+ shape[key] = deepPartial(type).optional();
1012
+ } else {
1013
+ shape[key] = type.optional();
1014
+ }
1049
1015
  }
1050
- const { promise: abortedPromise, resolve: abortedResolve } = resolver3();
1051
- const sleepPromise = new Promise((resolve) => {
1052
- const handleAbort = () => {
1053
- clearTimeout(id);
1054
- abortedResolve();
1055
- };
1056
- const id = setTimeout(() => {
1057
- resolve();
1058
- signal.removeEventListener("abort", handleAbort);
1059
- }, ms);
1060
- signal.addEventListener("abort", handleAbort, { once: true });
1061
- });
1062
- return [sleepPromise, abortedPromise];
1016
+ return v.object(shape);
1063
1017
  }
1064
1018
 
1065
- // ../replicache/src/connection-loop.ts
1066
- var MIN_DELAY_MS = 30;
1067
- var MAX_DELAY_MS = 6e4;
1068
- var ConnectionLoop = class {
1069
- // ConnectionLoop runs a loop sending network requests (either pushes or
1070
- // pulls) to the server. Our goal, generally, is to send requests as fast as
1071
- // we can, but to adjust in case of slowness, network errors, etc. We will
1072
- // send requests in parallel if the server supports it. We also debounce
1073
- // pushes since they frequently happen in series very near to one another
1074
- // (e.g., during drag'n drops).
1075
- //
1076
- // The loop flows through the following states forever, until it is closed:
1077
- //
1078
- // Pending: Wait for event or watchdog
1079
- // |
1080
- // v
1081
- // Debounce: Wait for more events (we debounce pushes)
1082
- // |
1083
- // v
1084
- // Wait for available connection (we limit number of parallel requests
1085
- // allowed)
1086
- // |
1087
- // v
1088
- // Wait to send (if requests are taking too long, we will slow down)
1089
- // |
1090
- // v
1091
- // Send (asynchronously, wrt the loop)
1092
- // |
1093
- // v
1094
- // Back to the pending!
1095
- // Controls whether the next iteration of the loop will wait at the pending
1096
- // state.
1097
- #pendingResolver = resolver4();
1098
- /**
1099
- * This resolver is used to allow us to skip sleeps when we do send(true)
1100
- */
1101
- #skipSleepsResolver = resolver4();
1019
+ // ../replicache/src/hash.ts
1020
+ var STRING_LENGTH = 22;
1021
+ var hashRe = /^[0-9a-v-]+$/;
1022
+ var emptyUUID = "0".repeat(STRING_LENGTH);
1023
+ var emptyHash = emptyUUID;
1024
+ var newRandomHash = makeNewRandomHashFunctionInternal();
1025
+ function toStringAndSlice(n, len) {
1026
+ return n.toString(32).slice(-len).padStart(len, "0");
1027
+ }
1028
+ function makeNewRandomHashFunctionInternal() {
1029
+ let base = "";
1030
+ let i = 0;
1031
+ return () => {
1032
+ if (!base) {
1033
+ base = toStringAndSlice(randomUint64(), 12);
1034
+ }
1035
+ const tail = toStringAndSlice(i++, 10);
1036
+ return base + tail;
1037
+ };
1038
+ }
1039
+ function isHash(value) {
1040
+ return typeof value === "string" && hashRe.test(value);
1041
+ }
1042
+ function assertHash(value) {
1043
+ assert2(value, hashSchema);
1044
+ }
1045
+ var hashSchema = valita_exports.string().assert(isHash, "Invalid hash");
1046
+
1047
+ // ../replicache/src/dag/chunk.ts
1048
+ function asRefs(sortedRefs) {
1049
+ return sortedRefs;
1050
+ }
1051
+ function toRefs(refs) {
1052
+ if (Array.isArray(refs)) {
1053
+ refs.sort();
1054
+ for (let i = 1; i < refs.length; i++) {
1055
+ assert(refs[i - 1] !== refs[i], "Refs must not have duplicates");
1056
+ }
1057
+ return asRefs(refs);
1058
+ }
1059
+ const refsArray = [...refs];
1060
+ refsArray.sort();
1061
+ return asRefs(refsArray);
1062
+ }
1063
+ var Chunk = class {
1064
+ hash;
1065
+ data;
1102
1066
  /**
1103
- * Resolver for the next send. Never rejects. Returns an error instead since
1104
- * this resolver is used in cases where they might not be someone waiting,
1105
- * and we don't want an unhandled promise rejection in that case.
1067
+ * Meta is an array of refs. If there are no refs we do not write a meta
1068
+ * chunk.
1106
1069
  */
1107
- #sendResolver = resolver4();
1070
+ meta;
1071
+ constructor(hash2, data, refs) {
1072
+ assert(
1073
+ !refs.includes(hash2),
1074
+ "Chunk cannot reference itself"
1075
+ );
1076
+ assertDeepFrozen(data);
1077
+ this.hash = hash2;
1078
+ this.data = data;
1079
+ this.meta = refs;
1080
+ }
1081
+ };
1082
+ function assertRefs(v2) {
1083
+ if (!Array.isArray(v2)) {
1084
+ throw new Error("Refs must be an array");
1085
+ }
1086
+ if (v2.length > 0) {
1087
+ assertString(v2[0]);
1088
+ for (let i = 1; i < v2.length; i++) {
1089
+ assertString(v2[i]);
1090
+ }
1091
+ }
1092
+ }
1093
+ function createChunk(data, refs, chunkHasher) {
1094
+ const hash2 = chunkHasher();
1095
+ return new Chunk(hash2, data, refs);
1096
+ }
1097
+
1098
+ // ../replicache/src/dag/gc.ts
1099
+ function computeRefCountUpdates(headChanges, putChunks, delegate) {
1100
+ return new RefCountUpdates(headChanges, putChunks, delegate).compute();
1101
+ }
1102
+ var RefCountUpdates = class {
1103
+ #newHeads;
1104
+ #oldHeads;
1105
+ #putChunks;
1108
1106
  #delegate;
1109
- #closed = false;
1110
- /**
1111
- * Number of pending send calls.
1112
- *
1113
- * We keep track of this because if close happens while we are waiting for the
1114
- * send to resolve we should reject the send promise.
1115
- */
1116
- #sendCounter = 0;
1117
- #lc;
1118
- #visibilityWatcher;
1119
- constructor(lc, delegate, visibilityWatcher) {
1120
- this.#lc = lc;
1107
+ #refsCounted;
1108
+ #refCountUpdates;
1109
+ #loadedRefCountPromises;
1110
+ #isLazyDelegate;
1111
+ constructor(headChanges, putChunks, delegate) {
1112
+ const newHeads = [];
1113
+ const oldHeads = [];
1114
+ for (const changedHead of headChanges) {
1115
+ if (changedHead.old !== changedHead.new) {
1116
+ changedHead.old && oldHeads.push(changedHead.old);
1117
+ changedHead.new && newHeads.push(changedHead.new);
1118
+ }
1119
+ }
1120
+ this.#newHeads = newHeads;
1121
+ this.#oldHeads = oldHeads;
1122
+ this.#putChunks = putChunks;
1121
1123
  this.#delegate = delegate;
1122
- this.#visibilityWatcher = visibilityWatcher;
1123
- void this.run();
1124
+ this.#refCountUpdates = /* @__PURE__ */ new Map();
1125
+ this.#loadedRefCountPromises = /* @__PURE__ */ new Map();
1126
+ this.#isLazyDelegate = delegate.areRefsCounted !== void 0;
1127
+ this.#refsCounted = this.#isLazyDelegate ? /* @__PURE__ */ new Set() : null;
1124
1128
  }
1125
- close() {
1126
- this.#closed = true;
1127
- if (this.#sendCounter > 0) {
1128
- this.#sendResolver.resolve({ error: closeError() });
1129
+ async compute() {
1130
+ for (const n of this.#newHeads) {
1131
+ await this.#changeRefCount(n, 1);
1129
1132
  }
1130
- }
1131
- /**
1132
- *
1133
- * @returns Returns undefined if ok, otherwise it return the error that caused
1134
- * the send to fail.
1135
- */
1136
- async send(now) {
1137
- if (this.#closed) {
1138
- return { error: closeError() };
1133
+ await Promise.all(
1134
+ Array.from(
1135
+ this.#putChunks.values(),
1136
+ (hash2) => this.#ensureRefCountLoaded(hash2)
1137
+ )
1138
+ );
1139
+ if (this.#isLazyDelegate) {
1140
+ assert(this.#delegate.areRefsCounted);
1141
+ assert(this.#refsCounted);
1142
+ let refCountsUpdated;
1143
+ do {
1144
+ refCountsUpdated = false;
1145
+ for (const hash2 of this.#putChunks.values()) {
1146
+ if (!this.#delegate.areRefsCounted(hash2) && !this.#refsCounted.has(hash2) && this.#refCountUpdates.get(hash2) !== 0) {
1147
+ await this.#updateRefsCounts(hash2, 1);
1148
+ refCountsUpdated = true;
1149
+ break;
1150
+ }
1151
+ }
1152
+ } while (refCountsUpdated);
1139
1153
  }
1140
- this.#sendCounter++;
1141
- this.#lc.debug?.("send", now);
1142
- if (now) {
1143
- this.#skipSleepsResolver.resolve();
1144
- } else {
1145
- await this.#visibilityWatcher?.waitForVisible();
1154
+ for (const o of this.#oldHeads) {
1155
+ await this.#changeRefCount(o, -1);
1146
1156
  }
1147
- this.#pendingResolver.resolve();
1148
- const result = await this.#sendResolver.promise;
1149
- this.#sendCounter--;
1150
- return result;
1151
- }
1152
- async run() {
1153
- const sendRecords = [];
1154
- let recoverResolver = resolver4();
1155
- let lastSendTime;
1156
- let counter = 0;
1157
- const delegate = this.#delegate;
1158
- const { debug } = this.#lc;
1159
- let delay = 0;
1160
- debug?.("Starting connection loop");
1161
- const sleepMaybeSkip = (ms) => Promise.race([this.#skipSleepsResolver.promise, sleep(ms)]);
1162
- while (!this.#closed) {
1163
- debug?.(
1164
- didLastSendRequestFail(sendRecords) ? "Last request failed. Trying again" : "Waiting for a send"
1165
- );
1166
- const races = [this.#pendingResolver.promise];
1167
- const t2 = delegate.watchdogTimer;
1168
- if (t2 !== null) {
1169
- races.push(sleep(t2));
1170
- }
1171
- await Promise.race(races);
1172
- if (this.#closed) break;
1173
- debug?.("Waiting for debounce");
1174
- await sleepMaybeSkip(delegate.debounceDelay);
1175
- if (this.#closed) break;
1176
- debug?.("debounced");
1177
- this.#pendingResolver = resolver4();
1178
- if (counter >= delegate.maxConnections) {
1179
- debug?.("Too many request in flight. Waiting until one finishes...");
1180
- await this.#waitUntilAvailableConnection();
1181
- if (this.#closed) break;
1182
- debug?.("...finished");
1183
- }
1184
- if (counter > 0 || didLastSendRequestFail(sendRecords)) {
1185
- delay = computeDelayAndUpdateDurations(delay, delegate, sendRecords);
1186
- debug?.(
1187
- didLastSendRequestFail(sendRecords) ? "Last connection errored. Sleeping for" : "More than one outstanding connection (" + counter + "). Sleeping for",
1188
- delay,
1189
- "ms"
1157
+ if (!isProd) {
1158
+ for (const [hash2, update] of this.#refCountUpdates) {
1159
+ assert(
1160
+ update >= 0,
1161
+ `ref count update must be non-negative. ${hash2}:${update}`
1190
1162
  );
1191
- } else {
1192
- delay = 0;
1193
- }
1194
- const clampedDelay = Math.min(
1195
- delegate.maxDelayMs,
1196
- Math.max(delegate.minDelayMs, delay)
1197
- );
1198
- if (lastSendTime !== void 0) {
1199
- const timeSinceLastSend = Date.now() - lastSendTime;
1200
- if (clampedDelay > timeSinceLastSend) {
1201
- await Promise.race([
1202
- sleepMaybeSkip(clampedDelay - timeSinceLastSend),
1203
- recoverResolver.promise
1204
- ]);
1205
- if (this.#closed) break;
1206
- }
1207
1163
  }
1208
- counter++;
1209
- (async () => {
1210
- const start = Date.now();
1211
- let ok2;
1212
- let error;
1213
- try {
1214
- lastSendTime = start;
1215
- debug?.("Sending request");
1216
- this.#skipSleepsResolver = resolver4();
1217
- ok2 = await delegate.invokeSend();
1218
- debug?.("Send returned", ok2);
1219
- } catch (e) {
1220
- debug?.("Send failed", e);
1221
- error = e;
1222
- ok2 = false;
1223
- }
1224
- if (this.#closed) {
1225
- debug?.("Closed after invokeSend");
1226
- return;
1227
- }
1228
- debug?.("Request done", { duration: Date.now() - start, ok: ok2 });
1229
- sendRecords.push({ duration: Date.now() - start, ok: ok2 });
1230
- if (recovered(sendRecords)) {
1231
- recoverResolver.resolve();
1232
- recoverResolver = resolver4();
1233
- }
1234
- counter--;
1235
- this.#connectionAvailable();
1236
- const sendResolver = this.#sendResolver;
1237
- this.#sendResolver = resolver4();
1238
- if (error) {
1239
- sendResolver.resolve({ error });
1240
- } else {
1241
- sendResolver.resolve(void 0);
1242
- }
1243
- if (!ok2) {
1244
- this.#pendingResolver.resolve();
1245
- }
1246
- })();
1247
1164
  }
1165
+ return this.#refCountUpdates;
1248
1166
  }
1249
- #waitingConnectionResolve = void 0;
1250
- #connectionAvailable() {
1251
- if (this.#waitingConnectionResolve) {
1252
- const resolve = this.#waitingConnectionResolve;
1253
- this.#waitingConnectionResolve = void 0;
1254
- resolve();
1167
+ async #changeRefCount(hash2, delta) {
1168
+ await this.#ensureRefCountLoaded(hash2);
1169
+ if (this.#updateRefCount(hash2, delta)) {
1170
+ await this.#updateRefsCounts(hash2, delta);
1255
1171
  }
1256
1172
  }
1257
- #waitUntilAvailableConnection() {
1258
- const { promise, resolve } = resolver4();
1259
- this.#waitingConnectionResolve = resolve;
1260
- return promise;
1261
- }
1262
- };
1263
- var CONNECTION_MEMORY_COUNT = 9;
1264
- function closeError() {
1265
- return new Error("Closed");
1266
- }
1267
- function computeDelayAndUpdateDurations(delay, delegate, sendRecords) {
1268
- const { length } = sendRecords;
1269
- if (length === 0) {
1270
- return delay;
1271
- }
1272
- const { ok: ok2 } = sendRecords[sendRecords.length - 1];
1273
- const { maxConnections, minDelayMs } = delegate;
1274
- if (!ok2) {
1275
- return delay === 0 ? minDelayMs : delay * 2;
1276
- }
1277
- if (length > 1) {
1278
- const previous = sendRecords[sendRecords.length - 2];
1279
- while (sendRecords.length > CONNECTION_MEMORY_COUNT) {
1280
- sendRecords.shift();
1173
+ async #updateRefsCounts(hash2, delta) {
1174
+ if (hash2 === emptyHash) {
1175
+ return;
1281
1176
  }
1282
- if (ok2 && !previous.ok) {
1283
- return minDelayMs;
1177
+ const refs = await this.#delegate.getRefs(hash2);
1178
+ if (!isProd) {
1179
+ assert(
1180
+ refs || this.#isLazyDelegate && !this.#putChunks.has(hash2),
1181
+ "refs must be defined"
1182
+ );
1183
+ }
1184
+ if (refs !== void 0) {
1185
+ this.#refsCounted?.add(hash2);
1186
+ const ps = refs.map((ref) => this.#changeRefCount(ref, delta));
1187
+ await Promise.all(ps);
1284
1188
  }
1285
1189
  }
1286
- const med = median(
1287
- sendRecords.filter(({ ok: ok3 }) => ok3).map(({ duration }) => duration)
1288
- );
1289
- return med / maxConnections | 0;
1290
- }
1291
- function median(values) {
1292
- values.sort();
1293
- const { length } = values;
1294
- const half = length >> 1;
1295
- if (length % 2 === 1) {
1296
- return values[half];
1190
+ #ensureRefCountLoaded(hash2) {
1191
+ let p = this.#loadedRefCountPromises.get(hash2);
1192
+ if (p === void 0) {
1193
+ p = (async () => {
1194
+ const value = await this.#delegate.getRefCount(hash2) || 0;
1195
+ this.#refCountUpdates.set(hash2, value);
1196
+ return value;
1197
+ })();
1198
+ this.#loadedRefCountPromises.set(hash2, p);
1199
+ }
1200
+ return p;
1297
1201
  }
1298
- return (values[half - 1] + values[half]) / 2;
1202
+ #updateRefCount(hash2, delta) {
1203
+ const oldCount = this.#refCountUpdates.get(hash2);
1204
+ assertNumber(oldCount);
1205
+ this.#refCountUpdates.set(hash2, oldCount + delta);
1206
+ return oldCount === 0 && delta === 1 || oldCount === 1 && delta === -1;
1207
+ }
1208
+ };
1209
+
1210
+ // ../replicache/src/dag/key.ts
1211
+ function chunkDataKey(hash2) {
1212
+ return `c/${hash2}/d`;
1299
1213
  }
1300
- function didLastSendRequestFail(sendRecords) {
1301
- return sendRecords.length > 0 && !sendRecords[sendRecords.length - 1].ok;
1214
+ function chunkMetaKey(hash2) {
1215
+ return `c/${hash2}/m`;
1302
1216
  }
1303
- function recovered(sendRecords) {
1304
- return sendRecords.length > 1 && !sendRecords[sendRecords.length - 2].ok && sendRecords[sendRecords.length - 1].ok;
1217
+ function chunkRefCountKey(hash2) {
1218
+ return `c/${hash2}/r`;
1219
+ }
1220
+ function headKey(name) {
1221
+ return `h/${name}`;
1305
1222
  }
1306
1223
 
1307
- // ../replicache/src/dag/lazy-store.ts
1308
- import { RWLock as RWLock2 } from "@rocicorp/lock";
1309
-
1310
- // ../shared/src/iterables.ts
1311
- function* joinIterables(...iters) {
1312
- for (const iter of iters) {
1313
- yield* iter;
1224
+ // ../replicache/src/dag/store.ts
1225
+ var ChunkNotFoundError = class extends Error {
1226
+ name = "ChunkNotFoundError";
1227
+ hash;
1228
+ constructor(hash2) {
1229
+ super(`Chunk not found ${hash2}`);
1230
+ this.hash = hash2;
1314
1231
  }
1315
- }
1316
- function* mergeIterables(iterables, comparator2, distinct = false) {
1317
- const iterators = iterables.map((i) => i[Symbol.iterator]());
1318
- try {
1319
- const current = iterators.map((i) => i.next());
1320
- let lastYielded;
1321
- while (current.some((c) => !c.done)) {
1322
- const min = current.reduce(
1323
- (acc, c, i) => {
1324
- if (c.done) {
1325
- return acc;
1326
- }
1327
- if (acc === void 0 || comparator2(c.value, acc[0]) < 0) {
1328
- return [c.value, i];
1329
- }
1330
- return acc;
1331
- },
1332
- void 0
1333
- );
1334
- assert(min !== void 0, "min is undefined");
1335
- current[min[1]] = iterators[min[1]].next();
1336
- if (lastYielded !== void 0 && distinct && comparator2(lastYielded, min[0]) === 0) {
1337
- continue;
1338
- }
1339
- lastYielded = min[0];
1340
- yield min[0];
1341
- }
1342
- } finally {
1343
- for (const it of iterators) {
1344
- it.return?.();
1345
- }
1232
+ };
1233
+ async function mustGetChunk(store, hash2) {
1234
+ const chunk = await store.getChunk(hash2);
1235
+ if (chunk) {
1236
+ return chunk;
1346
1237
  }
1238
+ throw new ChunkNotFoundError(hash2);
1239
+ }
1240
+ async function mustGetHeadHash(name, store) {
1241
+ const hash2 = await store.getHead(name);
1242
+ assert(hash2, `Missing head ${name}`);
1243
+ return hash2;
1347
1244
  }
1348
1245
 
1349
- // ../replicache/src/size-of-value.ts
1350
- var SIZE_TAG = 1;
1351
- var SIZE_INT32 = 4;
1352
- var SIZE_SMI = 5;
1353
- var SIZE_DOUBLE = 8;
1354
- function getSizeOfValue(value) {
1355
- switch (typeof value) {
1356
- case "string":
1357
- return SIZE_TAG + SIZE_INT32 + value.length;
1358
- case "number":
1359
- if (isSmi(value)) {
1360
- if (value <= -(2 ** 30) || value >= 2 ** 30 - 1) {
1361
- return SIZE_TAG + SIZE_SMI;
1362
- }
1363
- return SIZE_TAG + SIZE_INT32;
1364
- }
1365
- return SIZE_TAG + SIZE_DOUBLE;
1366
- case "boolean":
1367
- return SIZE_TAG;
1368
- case "object":
1369
- if (value === null) {
1370
- return SIZE_TAG;
1371
- }
1372
- if (Array.isArray(value)) {
1373
- let sum = 2 * SIZE_TAG + SIZE_INT32;
1374
- for (const element of value) {
1375
- sum += getSizeOfValue(element);
1376
- }
1377
- return sum;
1378
- }
1379
- {
1380
- const val = value;
1381
- let sum = 2 * SIZE_TAG + SIZE_INT32;
1382
- for (const k in val) {
1383
- if (hasOwn(val, k)) {
1384
- const propertyValue = val[k];
1385
- if (propertyValue !== void 0) {
1386
- sum += getSizeOfValue(k) + getSizeOfValue(propertyValue);
1387
- }
1388
- }
1389
- }
1390
- return sum;
1391
- }
1246
+ // ../replicache/src/dag/store-impl.ts
1247
+ var StoreImpl = class {
1248
+ #kv;
1249
+ #chunkHasher;
1250
+ #assertValidHash;
1251
+ constructor(kv, chunkHasher, assertValidHash) {
1252
+ this.#kv = kv;
1253
+ this.#chunkHasher = chunkHasher;
1254
+ this.#assertValidHash = assertValidHash;
1392
1255
  }
1393
- throw new Error(`Invalid value. type: ${typeof value}, value: ${value}`);
1394
- }
1395
- function isSmi(value) {
1396
- return value === (value | 0);
1397
- }
1398
- var entryFixed = 2 * SIZE_TAG + SIZE_INT32 + SIZE_TAG + SIZE_INT32;
1399
- function getSizeOfEntry(key, value) {
1400
- return entryFixed + getSizeOfValue(key) + getSizeOfValue(value);
1401
- }
1402
-
1403
- // ../replicache/src/dag/chunk.ts
1404
- function asRefs(sortedRefs) {
1405
- return sortedRefs;
1406
- }
1407
- function toRefs(refs) {
1408
- if (Array.isArray(refs)) {
1409
- refs.sort();
1410
- for (let i = 1; i < refs.length; i++) {
1411
- assert(refs[i - 1] !== refs[i], "Refs must not have duplicates");
1412
- }
1413
- return asRefs(refs);
1256
+ async read() {
1257
+ return new ReadImpl2(await this.#kv.read(), this.#assertValidHash);
1414
1258
  }
1415
- const refsArray = [...refs];
1416
- refsArray.sort();
1417
- return asRefs(refsArray);
1418
- }
1419
- var Chunk = class {
1420
- hash;
1421
- data;
1422
- /**
1423
- * Meta is an array of refs. If there are no refs we do not write a meta
1424
- * chunk.
1425
- */
1426
- meta;
1427
- constructor(hash2, data, refs) {
1428
- assert(
1429
- !refs.includes(hash2),
1430
- "Chunk cannot reference itself"
1259
+ async write() {
1260
+ return new WriteImpl2(
1261
+ await this.#kv.write(),
1262
+ this.#chunkHasher,
1263
+ this.#assertValidHash
1431
1264
  );
1432
- assertDeepFrozen(data);
1433
- this.hash = hash2;
1434
- this.data = data;
1435
- this.meta = refs;
1265
+ }
1266
+ close() {
1267
+ return this.#kv.close();
1436
1268
  }
1437
1269
  };
1438
- function assertRefs(v2) {
1439
- if (!Array.isArray(v2)) {
1440
- throw new Error("Refs must be an array");
1270
+ var ReadImpl2 = class {
1271
+ _tx;
1272
+ assertValidHash;
1273
+ constructor(kv, assertValidHash) {
1274
+ this._tx = kv;
1275
+ this.assertValidHash = assertValidHash;
1441
1276
  }
1442
- if (v2.length > 0) {
1443
- assertString(v2[0]);
1444
- for (let i = 1; i < v2.length; i++) {
1445
- assertString(v2[i]);
1277
+ hasChunk(hash2) {
1278
+ return this._tx.has(chunkDataKey(hash2));
1279
+ }
1280
+ async getChunk(hash2) {
1281
+ const data = await this._tx.get(chunkDataKey(hash2));
1282
+ if (data === void 0) {
1283
+ return void 0;
1284
+ }
1285
+ const refsVal = await this._tx.get(chunkMetaKey(hash2));
1286
+ let refs;
1287
+ if (refsVal !== void 0) {
1288
+ assertRefs(refsVal);
1289
+ refs = refsVal;
1290
+ } else {
1291
+ refs = [];
1446
1292
  }
1293
+ return new Chunk(hash2, data, refs);
1447
1294
  }
1448
- }
1449
- function createChunk(data, refs, chunkHasher) {
1450
- const hash2 = chunkHasher();
1451
- return new Chunk(hash2, data, refs);
1452
- }
1453
-
1454
- // ../shared/src/random-uint64.ts
1455
- function randomUint64() {
1456
- const high = Math.floor(Math.random() * 4294967295);
1457
- const low = Math.floor(Math.random() * 4294967295);
1458
- return BigInt(high) << 32n | BigInt(low);
1459
- }
1460
-
1461
- // ../shared/src/valita.ts
1462
- var valita_exports = {};
1463
- __export(valita_exports, {
1464
- assert: () => assert2,
1465
- deepPartial: () => deepPartial,
1466
- instanceOfAbstractType: () => instanceOfAbstractType,
1467
- is: () => is,
1468
- parse: () => parse,
1469
- readonly: () => readonly,
1470
- readonlyArray: () => readonlyArray,
1471
- readonlyObject: () => readonlyObject,
1472
- readonlyRecord: () => readonlyRecord,
1473
- test: () => test,
1474
- testOptional: () => testOptional
1475
- });
1476
- __reExport(valita_exports, valita_star);
1477
- import * as v from "@badrap/valita";
1478
- import * as valita_star from "@badrap/valita";
1479
- function toDisplay(value) {
1480
- switch (typeof value) {
1481
- case "string":
1482
- case "number":
1483
- case "boolean":
1484
- return JSON.stringify(value);
1485
- case "undefined":
1486
- return "undefined";
1487
- case "bigint":
1488
- return value.toString() + "n";
1489
- default:
1490
- if (value === null) {
1491
- return "null";
1492
- }
1493
- if (Array.isArray(value)) {
1494
- return "array";
1495
- }
1496
- return typeof value;
1295
+ mustGetChunk(hash2) {
1296
+ return mustGetChunk(this, hash2);
1497
1297
  }
1498
- }
1499
- function toDisplayAtPath(v2, path2) {
1500
- if (!path2?.length) {
1501
- return toDisplay(v2);
1298
+ async getHead(name) {
1299
+ const data = await this._tx.get(headKey(name));
1300
+ if (data === void 0) {
1301
+ return void 0;
1302
+ }
1303
+ assertHash(data);
1304
+ return data;
1502
1305
  }
1503
- let cur = v2;
1504
- for (const p of path2) {
1505
- cur = cur[p];
1306
+ release() {
1307
+ this._tx.release();
1506
1308
  }
1507
- return toDisplay(cur);
1508
- }
1509
- function displayList(word, expected, toDisplay2 = (x) => String(x)) {
1510
- if (expected.length === 1) {
1511
- return toDisplay2(expected[0]);
1309
+ get closed() {
1310
+ return this._tx.closed;
1512
1311
  }
1513
- const suffix = `${toDisplay2(
1514
- expected[expected.length - 2]
1515
- )} ${word} ${toDisplay2(expected[expected.length - 1])}`;
1516
- if (expected.length === 2) {
1517
- return suffix;
1312
+ };
1313
+ var WriteImpl2 = class extends ReadImpl2 {
1314
+ #chunkHasher;
1315
+ #putChunks = /* @__PURE__ */ new Set();
1316
+ #changedHeads = /* @__PURE__ */ new Map();
1317
+ constructor(kvw, chunkHasher, assertValidHash) {
1318
+ super(kvw, assertValidHash);
1319
+ this.#chunkHasher = chunkHasher;
1518
1320
  }
1519
- return `${expected.slice(0, -2).map(toDisplay2).join(", ")}, ${suffix}`;
1520
- }
1521
- function getMessage(err2, v2, schema, mode) {
1522
- const firstIssue = err2.issues[0];
1523
- const { path: path2 } = firstIssue;
1524
- const atPath = path2?.length ? ` at ${path2.join(".")}` : "";
1525
- switch (firstIssue.code) {
1526
- case "invalid_type":
1527
- return `Expected ${displayList(
1528
- "or",
1529
- firstIssue.expected
1530
- )}${atPath}. Got ${toDisplayAtPath(v2, path2)}`;
1531
- case "missing_value": {
1532
- const atPath2 = path2 && path2.length > 1 ? ` at ${path2.slice(0, -1).join(".")}` : "";
1533
- if (firstIssue.path?.length) {
1534
- return `Missing property ${firstIssue.path.at(-1)}${atPath2}`;
1321
+ createChunk = (data, refs) => createChunk(data, refs, this.#chunkHasher);
1322
+ get kvWrite() {
1323
+ return this._tx;
1324
+ }
1325
+ async putChunk(c) {
1326
+ const { hash: hash2, data, meta } = c;
1327
+ this.assertValidHash(hash2);
1328
+ const key = chunkDataKey(hash2);
1329
+ const p1 = this._tx.put(key, data);
1330
+ let p2;
1331
+ if (meta.length > 0) {
1332
+ for (const h of meta) {
1333
+ this.assertValidHash(h);
1535
1334
  }
1536
- return `TODO Unknown missing property${atPath2}`;
1537
- }
1538
- case "invalid_literal":
1539
- return `Expected literal value ${displayList(
1540
- "or",
1541
- firstIssue.expected,
1542
- toDisplay
1543
- )}${atPath} Got ${toDisplayAtPath(v2, path2)}`;
1544
- case "invalid_length": {
1545
- return `Expected array with length ${firstIssue.minLength === firstIssue.maxLength ? firstIssue.minLength : `between ${firstIssue.minLength} and ${firstIssue.maxLength}`}${atPath}. Got array with length ${v2.length}`;
1546
- }
1547
- case "unrecognized_keys":
1548
- if (firstIssue.keys.length === 1) {
1549
- return `Unexpected property ${firstIssue.keys[0]}${atPath}`;
1550
- }
1551
- return `Unexpected properties ${displayList(
1552
- "and",
1553
- firstIssue.keys
1554
- )}${atPath}`;
1555
- case "invalid_union":
1556
- return schema.name === "union" ? getDeepestUnionParseError(v2, schema, mode ?? "strict") : `Invalid union value${atPath}`;
1557
- case "custom_error": {
1558
- const { error } = firstIssue;
1559
- const message = !error ? "unknown" : typeof error === "string" ? error : error.message ?? "unknown";
1560
- return `${message}${atPath}. Got ${toDisplayAtPath(v2, path2)}`;
1335
+ p2 = this._tx.put(chunkMetaKey(hash2), meta);
1561
1336
  }
1337
+ this.#putChunks.add(hash2);
1338
+ await p1;
1339
+ await p2;
1562
1340
  }
1563
- }
1564
- function getDeepestUnionParseError(value, schema, mode) {
1565
- const failures = [];
1566
- for (const type of schema.options) {
1567
- const r = type.try(value, { mode });
1568
- if (!r.ok) {
1569
- failures.push({ type, err: r });
1570
- }
1341
+ setHead(name, hash2) {
1342
+ return this.#setHead(name, hash2);
1571
1343
  }
1572
- if (failures.length) {
1573
- failures.sort(pathCmp);
1574
- if (failures.length === 1 || pathCmp(failures[0], failures[1]) < 0) {
1575
- return getMessage(failures[0].err, value, failures[0].type, mode);
1344
+ removeHead(name) {
1345
+ return this.#setHead(name, void 0);
1346
+ }
1347
+ async #setHead(name, hash2) {
1348
+ const oldHash = await this.getHead(name);
1349
+ const hk = headKey(name);
1350
+ let p1;
1351
+ if (hash2 === void 0) {
1352
+ p1 = this._tx.del(hk);
1353
+ } else {
1354
+ p1 = this._tx.put(hk, hash2);
1355
+ }
1356
+ const v2 = this.#changedHeads.get(name);
1357
+ if (v2 === void 0) {
1358
+ this.#changedHeads.set(name, { new: hash2, old: oldHash });
1359
+ } else {
1360
+ v2.new = hash2;
1576
1361
  }
1362
+ await p1;
1577
1363
  }
1578
- try {
1579
- const str = JSON.stringify(value);
1580
- return `Invalid union value: ${str}`;
1581
- } catch (e) {
1582
- return `Invalid union value`;
1364
+ async commit() {
1365
+ const refCountUpdates = await computeRefCountUpdates(
1366
+ this.#changedHeads.values(),
1367
+ this.#putChunks,
1368
+ this
1369
+ );
1370
+ await this.#applyRefCountUpdates(refCountUpdates);
1371
+ await this._tx.commit();
1583
1372
  }
1584
- }
1585
- function pathCmp(a, b) {
1586
- const aPath = a.err.issues[0].path;
1587
- const bPath = b.err.issues[0].path;
1588
- if (aPath.length !== bPath.length) {
1589
- return bPath.length - aPath.length;
1373
+ async getRefCount(hash2) {
1374
+ const value = await this._tx.get(chunkRefCountKey(hash2));
1375
+ if (value === void 0) {
1376
+ return void 0;
1377
+ }
1378
+ assertNumber(value);
1379
+ if (value < 0 || value > 65535 || value !== (value | 0)) {
1380
+ throw new Error(
1381
+ `Invalid ref count ${value}. We expect the value to be a Uint16`
1382
+ );
1383
+ }
1384
+ return value;
1590
1385
  }
1591
- for (let i = 0; i < aPath.length; i++) {
1592
- if (bPath[i] > aPath[i]) {
1593
- return -1;
1386
+ async getRefs(hash2) {
1387
+ const meta = await this._tx.get(chunkMetaKey(hash2));
1388
+ if (meta === void 0) {
1389
+ return [];
1594
1390
  }
1595
- if (bPath[i] < aPath[i]) {
1596
- return 1;
1391
+ assertRefs(meta);
1392
+ return meta;
1393
+ }
1394
+ async #applyRefCountUpdates(refCountCache) {
1395
+ const ps = [];
1396
+ for (const [hash2, count] of refCountCache) {
1397
+ if (count === 0) {
1398
+ ps.push(this.#removeAllRelatedKeys(hash2));
1399
+ } else {
1400
+ const refCountKey = chunkRefCountKey(hash2);
1401
+ ps.push(this._tx.put(refCountKey, count));
1402
+ }
1597
1403
  }
1404
+ await Promise.all(ps);
1598
1405
  }
1599
- return 0;
1600
- }
1601
- function parse(value, schema, mode) {
1602
- const res = test(value, schema, mode);
1603
- if (!res.ok) {
1604
- throw new TypeError(res.error);
1406
+ async #removeAllRelatedKeys(hash2) {
1407
+ await Promise.all([
1408
+ this._tx.del(chunkDataKey(hash2)),
1409
+ this._tx.del(chunkMetaKey(hash2)),
1410
+ this._tx.del(chunkRefCountKey(hash2))
1411
+ ]);
1412
+ this.#putChunks.delete(hash2);
1605
1413
  }
1606
- return res.value;
1607
- }
1608
- function is(value, schema, mode) {
1609
- return test(value, schema, mode).ok;
1610
- }
1611
- function assert2(value, schema, mode) {
1612
- parse(value, schema, mode);
1613
- }
1614
- function test(value, schema, mode) {
1615
- const res = schema.try(value, mode ? { mode } : void 0);
1616
- if (!res.ok) {
1617
- return {
1618
- ok: false,
1619
- error: getMessage(res, value, schema, mode)
1620
- };
1414
+ release() {
1415
+ this._tx.release();
1621
1416
  }
1622
- return res;
1417
+ };
1418
+
1419
+ // ../replicache/src/format-version-enum.ts
1420
+ var DD31 = 5;
1421
+ var V6 = 6;
1422
+ var V7 = 7;
1423
+ var Latest = V7;
1424
+
1425
+ // ../replicache/src/log-options.ts
1426
+ import {
1427
+ consoleLogSink,
1428
+ LogContext,
1429
+ TeeLogSink
1430
+ } from "@rocicorp/logger";
1431
+ function createLogContext(logLevel = "info", logSinks = [consoleLogSink], context) {
1432
+ const logSink = logSinks.length === 1 ? logSinks[0] : new TeeLogSink(logSinks);
1433
+ return new LogContext(logLevel, context, logSink);
1623
1434
  }
1624
- function testOptional(value, schema, mode) {
1625
- let flags = 1;
1626
- if (mode === "passthrough") {
1627
- flags = 0;
1628
- } else if (mode === "strip") {
1629
- flags = 2;
1435
+
1436
+ // ../shared/src/navigator.ts
1437
+ var localNavigator = typeof navigator !== "undefined" ? navigator : void 0;
1438
+
1439
+ // ../replicache/src/kv/mem-store.ts
1440
+ import { RWLock } from "@rocicorp/lock";
1441
+
1442
+ // ../replicache/src/kv/read-impl.ts
1443
+ var ReadImpl3 = class {
1444
+ #map;
1445
+ #release;
1446
+ #closed = false;
1447
+ constructor(map, release) {
1448
+ this.#map = map;
1449
+ this.#release = release;
1630
1450
  }
1631
- const res = schema.func(value, flags);
1632
- if (res === void 0) {
1633
- return { ok: true, value };
1634
- } else if (res.ok) {
1635
- return res;
1451
+ release() {
1452
+ this.#release();
1453
+ this.#closed = true;
1636
1454
  }
1637
- const err2 = new v.ValitaError(res);
1638
- return { ok: false, error: getMessage(err2, value, schema, mode) };
1639
- }
1640
- function readonly(t2) {
1641
- return t2;
1642
- }
1643
- function readonlyObject(t2) {
1644
- return v.object(t2);
1645
- }
1646
- function readonlyArray(t2) {
1647
- return v.array(t2);
1648
- }
1649
- function readonlyRecord(t2) {
1650
- return v.record(t2);
1651
- }
1652
- var AbstractType = Object.getPrototypeOf(
1653
- Object.getPrototypeOf(v.string().optional())
1654
- ).constructor;
1655
- function instanceOfAbstractType(obj) {
1656
- return obj instanceof AbstractType;
1455
+ get closed() {
1456
+ return this.#closed;
1457
+ }
1458
+ has(key) {
1459
+ return Promise.resolve(this.#map.has(key));
1460
+ }
1461
+ get(key) {
1462
+ return Promise.resolve(this.#map.get(key));
1463
+ }
1464
+ };
1465
+
1466
+ // ../replicache/src/kv/write-impl.ts
1467
+ var WriteImpl3 = class extends WriteImplBase {
1468
+ #map;
1469
+ constructor(map, release) {
1470
+ super(new ReadImpl3(map, release));
1471
+ this.#map = map;
1472
+ }
1473
+ commit() {
1474
+ this._pending.forEach((value, key) => {
1475
+ if (value === deleteSentinel) {
1476
+ this.#map.delete(key);
1477
+ } else {
1478
+ this.#map.set(key, value);
1479
+ }
1480
+ });
1481
+ this._pending.clear();
1482
+ this.release();
1483
+ return promiseVoid;
1484
+ }
1485
+ };
1486
+
1487
+ // ../replicache/src/kv/mem-store.ts
1488
+ var stores = /* @__PURE__ */ new Map();
1489
+ function dropMemStore(name) {
1490
+ stores.delete(name);
1491
+ return promiseVoid;
1657
1492
  }
1658
- function deepPartial(s) {
1659
- const shape = {};
1660
- for (const [key, type] of Object.entries(s.shape)) {
1661
- if (type.name === "object") {
1662
- shape[key] = deepPartial(type).optional();
1493
+ var MemStore = class {
1494
+ #map;
1495
+ #rwLock;
1496
+ #closed = false;
1497
+ constructor(name) {
1498
+ const entry = stores.get(name);
1499
+ let lock;
1500
+ let map;
1501
+ if (entry) {
1502
+ ({ lock, map } = entry);
1663
1503
  } else {
1664
- shape[key] = type.optional();
1504
+ lock = new RWLock();
1505
+ map = /* @__PURE__ */ new Map();
1506
+ stores.set(name, { lock, map });
1507
+ }
1508
+ this.#rwLock = lock;
1509
+ this.#map = map;
1510
+ }
1511
+ async read() {
1512
+ const release = await this.#rwLock.read();
1513
+ return new ReadImpl3(this.#map, release);
1514
+ }
1515
+ async write() {
1516
+ const release = await this.#rwLock.write();
1517
+ return new WriteImpl3(this.#map, release);
1518
+ }
1519
+ close() {
1520
+ this.#closed = true;
1521
+ return promiseVoid;
1522
+ }
1523
+ get closed() {
1524
+ return this.#closed;
1525
+ }
1526
+ };
1527
+
1528
+ // ../replicache/src/kv/idb-store-with-mem-fallback.ts
1529
+ var IDBStoreWithMemFallback = class {
1530
+ #lc;
1531
+ #name;
1532
+ #store;
1533
+ constructor(lc, name) {
1534
+ this.#lc = lc;
1535
+ this.#name = name;
1536
+ this.#store = new IDBStore(name);
1537
+ }
1538
+ read() {
1539
+ return this.#withBrainTransplant((s) => s.read());
1540
+ }
1541
+ write() {
1542
+ return this.#withBrainTransplant((s) => s.write());
1543
+ }
1544
+ async #withBrainTransplant(f) {
1545
+ try {
1546
+ return await f(this.#store);
1547
+ } catch (e) {
1548
+ if (isFirefoxPrivateBrowsingError(e)) {
1549
+ if (this.#store instanceof IDBStore) {
1550
+ this.#lc.info?.(
1551
+ "Switching to MemStore because of Firefox private browsing error"
1552
+ );
1553
+ this.#store = new MemStore(this.#name);
1554
+ }
1555
+ return f(this.#store);
1556
+ }
1557
+ throw e;
1558
+ }
1559
+ }
1560
+ close() {
1561
+ return this.#store.close();
1562
+ }
1563
+ get closed() {
1564
+ return this.#store.closed;
1565
+ }
1566
+ };
1567
+ function isFirefoxPrivateBrowsingError(e) {
1568
+ return isFirefox() && e instanceof DOMException && e.name === "InvalidStateError" && e.message === "A mutation operation was attempted on a database that did not allow mutations.";
1569
+ }
1570
+ function isFirefox() {
1571
+ return localNavigator?.userAgent.includes("Firefox") ?? false;
1572
+ }
1573
+ function newIDBStoreWithMemFallback(lc, name) {
1574
+ if (isFirefox()) {
1575
+ return new IDBStoreWithMemFallback(lc, name);
1576
+ }
1577
+ return new IDBStore(name);
1578
+ }
1579
+ function dropIDBStoreWithMemFallback(name) {
1580
+ if (!isFirefox()) {
1581
+ return dropIDBStore(name);
1582
+ }
1583
+ try {
1584
+ return dropIDBStore(name);
1585
+ } catch (e) {
1586
+ if (isFirefoxPrivateBrowsingError(e)) {
1587
+ return dropMemStore(name);
1588
+ }
1589
+ }
1590
+ return promiseVoid;
1591
+ }
1592
+ function dropIDBStore(name) {
1593
+ return new Promise((resolve, reject) => {
1594
+ const req = indexedDB.deleteDatabase(name);
1595
+ req.onsuccess = () => resolve();
1596
+ req.onerror = () => reject(req.error);
1597
+ });
1598
+ }
1599
+
1600
+ // ../replicache/src/replicache-impl.ts
1601
+ import { Lock as Lock2 } from "@rocicorp/lock";
1602
+ import { consoleLogSink as consoleLogSink2 } from "@rocicorp/logger";
1603
+ import { resolver as resolver6 } from "@rocicorp/resolver";
1604
+
1605
+ // ../shared/src/document-visible.ts
1606
+ import { resolver as resolver3 } from "@rocicorp/resolver";
1607
+ function getDocumentVisibilityWatcher(doc, hiddenIntervalMS, signal) {
1608
+ return doc ? new DocumentVisibilityWatcherImpl(doc, hiddenIntervalMS, signal) : new DocumentVisibilityWatcherNoDoc();
1609
+ }
1610
+ var DocumentVisibilityWatcherImpl = class {
1611
+ #doc;
1612
+ #hiddenIntervalMS;
1613
+ #timeoutID = 0;
1614
+ // This trails doc.visibilityState by hiddenIntervalMS when being hidden. This
1615
+ // is because we want to wait for the tab to be hidden for a while before
1616
+ // considering as hidden.
1617
+ visibilityState;
1618
+ #promises = /* @__PURE__ */ new Set();
1619
+ constructor(doc, hiddenIntervalMS, signal) {
1620
+ this.#doc = doc;
1621
+ this.#hiddenIntervalMS = hiddenIntervalMS;
1622
+ this.visibilityState = doc.visibilityState;
1623
+ this.#doc.addEventListener("visibilitychange", this.#onVisibilityChange, {
1624
+ signal
1625
+ });
1626
+ }
1627
+ #onVisibilityChange = () => {
1628
+ if (this.#doc.visibilityState === "visible") {
1629
+ clearTimeout(this.#timeoutID);
1630
+ this.#setVisibilityState("visible");
1631
+ } else {
1632
+ this.#timeoutID = setTimeout(() => {
1633
+ this.#setVisibilityState("hidden");
1634
+ }, this.#hiddenIntervalMS);
1635
+ }
1636
+ };
1637
+ #setVisibilityState(visibilityState) {
1638
+ if (visibilityState === this.visibilityState) {
1639
+ return;
1640
+ }
1641
+ this.visibilityState = visibilityState;
1642
+ for (const entry of this.#promises) {
1643
+ const { resolve, state } = entry;
1644
+ if (state === visibilityState) {
1645
+ resolve();
1646
+ this.#promises.delete(entry);
1647
+ }
1648
+ }
1649
+ }
1650
+ waitForVisible() {
1651
+ return this.#waitFor("visible");
1652
+ }
1653
+ waitForHidden() {
1654
+ return this.#waitFor("hidden");
1655
+ }
1656
+ #waitFor(state) {
1657
+ if (this.visibilityState === state) {
1658
+ return Promise.resolve();
1659
+ }
1660
+ const { promise, resolve } = resolver3();
1661
+ this.#promises.add({ resolve, state });
1662
+ return promise;
1663
+ }
1664
+ };
1665
+ var resolvedPromise = Promise.resolve();
1666
+ var promiseThatNeverResolves = new Promise(() => void 0);
1667
+ var DocumentVisibilityWatcherNoDoc = class {
1668
+ visibilityState = "visible";
1669
+ waitForVisible() {
1670
+ return resolvedPromise;
1671
+ }
1672
+ waitForHidden() {
1673
+ return promiseThatNeverResolves;
1674
+ }
1675
+ };
1676
+
1677
+ // ../replicache/src/connection-loop-delegates.ts
1678
+ var ConnectionLoopDelegateImpl = class {
1679
+ rep;
1680
+ invokeSend;
1681
+ // TODO: Remove the ability to have more than one concurrent connection and update tests.
1682
+ // Bug: https://github.com/rocicorp/replicache-internal/issues/303
1683
+ maxConnections = 1;
1684
+ constructor(rep, invokeSend) {
1685
+ this.rep = rep;
1686
+ this.invokeSend = invokeSend;
1687
+ }
1688
+ get maxDelayMs() {
1689
+ return this.rep.requestOptions.maxDelayMs;
1690
+ }
1691
+ get minDelayMs() {
1692
+ return this.rep.requestOptions.minDelayMs;
1693
+ }
1694
+ };
1695
+ var PullDelegate = class extends ConnectionLoopDelegateImpl {
1696
+ debounceDelay = 0;
1697
+ get watchdogTimer() {
1698
+ return this.rep.pullInterval;
1699
+ }
1700
+ };
1701
+ var PushDelegate = class extends ConnectionLoopDelegateImpl {
1702
+ get debounceDelay() {
1703
+ return this.rep.pushDelay;
1704
+ }
1705
+ watchdogTimer = null;
1706
+ };
1707
+
1708
+ // ../replicache/src/connection-loop.ts
1709
+ import { resolver as resolver4 } from "@rocicorp/resolver";
1710
+ var MIN_DELAY_MS = 30;
1711
+ var MAX_DELAY_MS = 6e4;
1712
+ var ConnectionLoop = class {
1713
+ // ConnectionLoop runs a loop sending network requests (either pushes or
1714
+ // pulls) to the server. Our goal, generally, is to send requests as fast as
1715
+ // we can, but to adjust in case of slowness, network errors, etc. We will
1716
+ // send requests in parallel if the server supports it. We also debounce
1717
+ // pushes since they frequently happen in series very near to one another
1718
+ // (e.g., during drag'n drops).
1719
+ //
1720
+ // The loop flows through the following states forever, until it is closed:
1721
+ //
1722
+ // Pending: Wait for event or watchdog
1723
+ // |
1724
+ // v
1725
+ // Debounce: Wait for more events (we debounce pushes)
1726
+ // |
1727
+ // v
1728
+ // Wait for available connection (we limit number of parallel requests
1729
+ // allowed)
1730
+ // |
1731
+ // v
1732
+ // Wait to send (if requests are taking too long, we will slow down)
1733
+ // |
1734
+ // v
1735
+ // Send (asynchronously, wrt the loop)
1736
+ // |
1737
+ // v
1738
+ // Back to the pending!
1739
+ // Controls whether the next iteration of the loop will wait at the pending
1740
+ // state.
1741
+ #pendingResolver = resolver4();
1742
+ /**
1743
+ * This resolver is used to allow us to skip sleeps when we do send(true)
1744
+ */
1745
+ #skipSleepsResolver = resolver4();
1746
+ /**
1747
+ * Resolver for the next send. Never rejects. Returns an error instead since
1748
+ * this resolver is used in cases where they might not be someone waiting,
1749
+ * and we don't want an unhandled promise rejection in that case.
1750
+ */
1751
+ #sendResolver = resolver4();
1752
+ #delegate;
1753
+ #closed = false;
1754
+ /**
1755
+ * Number of pending send calls.
1756
+ *
1757
+ * We keep track of this because if close happens while we are waiting for the
1758
+ * send to resolve we should reject the send promise.
1759
+ */
1760
+ #sendCounter = 0;
1761
+ #lc;
1762
+ #visibilityWatcher;
1763
+ constructor(lc, delegate, visibilityWatcher) {
1764
+ this.#lc = lc;
1765
+ this.#delegate = delegate;
1766
+ this.#visibilityWatcher = visibilityWatcher;
1767
+ void this.run();
1768
+ }
1769
+ close() {
1770
+ this.#closed = true;
1771
+ if (this.#sendCounter > 0) {
1772
+ this.#sendResolver.resolve({ error: closeError() });
1773
+ }
1774
+ }
1775
+ /**
1776
+ *
1777
+ * @returns Returns undefined if ok, otherwise it return the error that caused
1778
+ * the send to fail.
1779
+ */
1780
+ async send(now) {
1781
+ if (this.#closed) {
1782
+ return { error: closeError() };
1783
+ }
1784
+ this.#sendCounter++;
1785
+ this.#lc.debug?.("send", now);
1786
+ if (now) {
1787
+ this.#skipSleepsResolver.resolve();
1788
+ } else {
1789
+ await this.#visibilityWatcher?.waitForVisible();
1790
+ }
1791
+ this.#pendingResolver.resolve();
1792
+ const result = await this.#sendResolver.promise;
1793
+ this.#sendCounter--;
1794
+ return result;
1795
+ }
1796
+ async run() {
1797
+ const sendRecords = [];
1798
+ let recoverResolver = resolver4();
1799
+ let lastSendTime;
1800
+ let counter = 0;
1801
+ const delegate = this.#delegate;
1802
+ const { debug } = this.#lc;
1803
+ let delay = 0;
1804
+ debug?.("Starting connection loop");
1805
+ const sleepMaybeSkip = (ms) => Promise.race([this.#skipSleepsResolver.promise, sleep(ms)]);
1806
+ while (!this.#closed) {
1807
+ debug?.(
1808
+ didLastSendRequestFail(sendRecords) ? "Last request failed. Trying again" : "Waiting for a send"
1809
+ );
1810
+ const races = [this.#pendingResolver.promise];
1811
+ const t2 = delegate.watchdogTimer;
1812
+ if (t2 !== null) {
1813
+ races.push(sleep(t2));
1814
+ }
1815
+ await Promise.race(races);
1816
+ if (this.#closed) break;
1817
+ debug?.("Waiting for debounce");
1818
+ await sleepMaybeSkip(delegate.debounceDelay);
1819
+ if (this.#closed) break;
1820
+ debug?.("debounced");
1821
+ this.#pendingResolver = resolver4();
1822
+ if (counter >= delegate.maxConnections) {
1823
+ debug?.("Too many request in flight. Waiting until one finishes...");
1824
+ await this.#waitUntilAvailableConnection();
1825
+ if (this.#closed) break;
1826
+ debug?.("...finished");
1827
+ }
1828
+ if (counter > 0 || didLastSendRequestFail(sendRecords)) {
1829
+ delay = computeDelayAndUpdateDurations(delay, delegate, sendRecords);
1830
+ debug?.(
1831
+ didLastSendRequestFail(sendRecords) ? "Last connection errored. Sleeping for" : "More than one outstanding connection (" + counter + "). Sleeping for",
1832
+ delay,
1833
+ "ms"
1834
+ );
1835
+ } else {
1836
+ delay = 0;
1837
+ }
1838
+ const clampedDelay = Math.min(
1839
+ delegate.maxDelayMs,
1840
+ Math.max(delegate.minDelayMs, delay)
1841
+ );
1842
+ if (lastSendTime !== void 0) {
1843
+ const timeSinceLastSend = Date.now() - lastSendTime;
1844
+ if (clampedDelay > timeSinceLastSend) {
1845
+ await Promise.race([
1846
+ sleepMaybeSkip(clampedDelay - timeSinceLastSend),
1847
+ recoverResolver.promise
1848
+ ]);
1849
+ if (this.#closed) break;
1850
+ }
1851
+ }
1852
+ counter++;
1853
+ (async () => {
1854
+ const start = Date.now();
1855
+ let ok2;
1856
+ let error;
1857
+ try {
1858
+ lastSendTime = start;
1859
+ debug?.("Sending request");
1860
+ this.#skipSleepsResolver = resolver4();
1861
+ ok2 = await delegate.invokeSend();
1862
+ debug?.("Send returned", ok2);
1863
+ } catch (e) {
1864
+ debug?.("Send failed", e);
1865
+ error = e;
1866
+ ok2 = false;
1867
+ }
1868
+ if (this.#closed) {
1869
+ debug?.("Closed after invokeSend");
1870
+ return;
1871
+ }
1872
+ debug?.("Request done", { duration: Date.now() - start, ok: ok2 });
1873
+ sendRecords.push({ duration: Date.now() - start, ok: ok2 });
1874
+ if (recovered(sendRecords)) {
1875
+ recoverResolver.resolve();
1876
+ recoverResolver = resolver4();
1877
+ }
1878
+ counter--;
1879
+ this.#connectionAvailable();
1880
+ const sendResolver = this.#sendResolver;
1881
+ this.#sendResolver = resolver4();
1882
+ if (error) {
1883
+ sendResolver.resolve({ error });
1884
+ } else {
1885
+ sendResolver.resolve(void 0);
1886
+ }
1887
+ if (!ok2) {
1888
+ this.#pendingResolver.resolve();
1889
+ }
1890
+ })();
1891
+ }
1892
+ }
1893
+ #waitingConnectionResolve = void 0;
1894
+ #connectionAvailable() {
1895
+ if (this.#waitingConnectionResolve) {
1896
+ const resolve = this.#waitingConnectionResolve;
1897
+ this.#waitingConnectionResolve = void 0;
1898
+ resolve();
1899
+ }
1900
+ }
1901
+ #waitUntilAvailableConnection() {
1902
+ const { promise, resolve } = resolver4();
1903
+ this.#waitingConnectionResolve = resolve;
1904
+ return promise;
1905
+ }
1906
+ };
1907
+ var CONNECTION_MEMORY_COUNT = 9;
1908
+ function closeError() {
1909
+ return new Error("Closed");
1910
+ }
1911
+ function computeDelayAndUpdateDurations(delay, delegate, sendRecords) {
1912
+ const { length } = sendRecords;
1913
+ if (length === 0) {
1914
+ return delay;
1915
+ }
1916
+ const { ok: ok2 } = sendRecords[sendRecords.length - 1];
1917
+ const { maxConnections, minDelayMs } = delegate;
1918
+ if (!ok2) {
1919
+ return delay === 0 ? minDelayMs : delay * 2;
1920
+ }
1921
+ if (length > 1) {
1922
+ const previous = sendRecords[sendRecords.length - 2];
1923
+ while (sendRecords.length > CONNECTION_MEMORY_COUNT) {
1924
+ sendRecords.shift();
1925
+ }
1926
+ if (ok2 && !previous.ok) {
1927
+ return minDelayMs;
1665
1928
  }
1666
1929
  }
1667
- return v.object(shape);
1668
- }
1669
-
1670
- // ../replicache/src/hash.ts
1671
- var STRING_LENGTH = 22;
1672
- var hashRe = /^[0-9a-v-]+$/;
1673
- var emptyUUID = "0".repeat(STRING_LENGTH);
1674
- var emptyHash = emptyUUID;
1675
- var newRandomHash = makeNewRandomHashFunctionInternal();
1676
- function toStringAndSlice(n, len) {
1677
- return n.toString(32).slice(-len).padStart(len, "0");
1930
+ const med = median(
1931
+ sendRecords.filter(({ ok: ok3 }) => ok3).map(({ duration }) => duration)
1932
+ );
1933
+ return med / maxConnections | 0;
1678
1934
  }
1679
- function makeNewRandomHashFunctionInternal() {
1680
- let base = "";
1681
- let i = 0;
1682
- return () => {
1683
- if (!base) {
1684
- base = toStringAndSlice(randomUint64(), 12);
1685
- }
1686
- const tail = toStringAndSlice(i++, 10);
1687
- return base + tail;
1688
- };
1935
+ function median(values) {
1936
+ values.sort();
1937
+ const { length } = values;
1938
+ const half = length >> 1;
1939
+ if (length % 2 === 1) {
1940
+ return values[half];
1941
+ }
1942
+ return (values[half - 1] + values[half]) / 2;
1689
1943
  }
1690
- function isHash(value) {
1691
- return typeof value === "string" && hashRe.test(value);
1944
+ function didLastSendRequestFail(sendRecords) {
1945
+ return sendRecords.length > 0 && !sendRecords[sendRecords.length - 1].ok;
1692
1946
  }
1693
- function assertHash(value) {
1694
- assert2(value, hashSchema);
1947
+ function recovered(sendRecords) {
1948
+ return sendRecords.length > 1 && !sendRecords[sendRecords.length - 2].ok && sendRecords[sendRecords.length - 1].ok;
1695
1949
  }
1696
- var hashSchema = valita_exports.string().assert(isHash, "Invalid hash");
1697
1950
 
1698
- // ../replicache/src/dag/gc.ts
1699
- function computeRefCountUpdates(headChanges, putChunks, delegate) {
1700
- return new RefCountUpdates(headChanges, putChunks, delegate).compute();
1701
- }
1702
- var RefCountUpdates = class {
1703
- #newHeads;
1704
- #oldHeads;
1705
- #putChunks;
1706
- #delegate;
1707
- #refsCounted;
1708
- #refCountUpdates;
1709
- #loadedRefCountPromises;
1710
- #isLazyDelegate;
1711
- constructor(headChanges, putChunks, delegate) {
1712
- const newHeads = [];
1713
- const oldHeads = [];
1714
- for (const changedHead of headChanges) {
1715
- if (changedHead.old !== changedHead.new) {
1716
- changedHead.old && oldHeads.push(changedHead.old);
1717
- changedHead.new && newHeads.push(changedHead.new);
1718
- }
1719
- }
1720
- this.#newHeads = newHeads;
1721
- this.#oldHeads = oldHeads;
1722
- this.#putChunks = putChunks;
1723
- this.#delegate = delegate;
1724
- this.#refCountUpdates = /* @__PURE__ */ new Map();
1725
- this.#loadedRefCountPromises = /* @__PURE__ */ new Map();
1726
- this.#isLazyDelegate = delegate.areRefsCounted !== void 0;
1727
- this.#refsCounted = this.#isLazyDelegate ? /* @__PURE__ */ new Set() : null;
1951
+ // ../replicache/src/dag/lazy-store.ts
1952
+ import { RWLock as RWLock2 } from "@rocicorp/lock";
1953
+
1954
+ // ../shared/src/iterables.ts
1955
+ function* joinIterables(...iters) {
1956
+ for (const iter of iters) {
1957
+ yield* iter;
1728
1958
  }
1729
- async compute() {
1730
- for (const n of this.#newHeads) {
1731
- await this.#changeRefCount(n, 1);
1732
- }
1733
- await Promise.all(
1734
- Array.from(
1735
- this.#putChunks.values(),
1736
- (hash2) => this.#ensureRefCountLoaded(hash2)
1737
- )
1738
- );
1739
- if (this.#isLazyDelegate) {
1740
- assert(this.#delegate.areRefsCounted);
1741
- assert(this.#refsCounted);
1742
- let refCountsUpdated;
1743
- do {
1744
- refCountsUpdated = false;
1745
- for (const hash2 of this.#putChunks.values()) {
1746
- if (!this.#delegate.areRefsCounted(hash2) && !this.#refsCounted.has(hash2) && this.#refCountUpdates.get(hash2) !== 0) {
1747
- await this.#updateRefsCounts(hash2, 1);
1748
- refCountsUpdated = true;
1749
- break;
1959
+ }
1960
+ function* mergeIterables(iterables, comparator2, distinct = false) {
1961
+ const iterators = iterables.map((i) => i[Symbol.iterator]());
1962
+ try {
1963
+ const current = iterators.map((i) => i.next());
1964
+ let lastYielded;
1965
+ while (current.some((c) => !c.done)) {
1966
+ const min = current.reduce(
1967
+ (acc, c, i) => {
1968
+ if (c.done) {
1969
+ return acc;
1750
1970
  }
1751
- }
1752
- } while (refCountsUpdated);
1753
- }
1754
- for (const o of this.#oldHeads) {
1755
- await this.#changeRefCount(o, -1);
1756
- }
1757
- if (!isProd) {
1758
- for (const [hash2, update] of this.#refCountUpdates) {
1759
- assert(
1760
- update >= 0,
1761
- `ref count update must be non-negative. ${hash2}:${update}`
1762
- );
1763
- }
1764
- }
1765
- return this.#refCountUpdates;
1766
- }
1767
- async #changeRefCount(hash2, delta) {
1768
- await this.#ensureRefCountLoaded(hash2);
1769
- if (this.#updateRefCount(hash2, delta)) {
1770
- await this.#updateRefsCounts(hash2, delta);
1771
- }
1772
- }
1773
- async #updateRefsCounts(hash2, delta) {
1774
- if (hash2 === emptyHash) {
1775
- return;
1776
- }
1777
- const refs = await this.#delegate.getRefs(hash2);
1778
- if (!isProd) {
1779
- assert(
1780
- refs || this.#isLazyDelegate && !this.#putChunks.has(hash2),
1781
- "refs must be defined"
1971
+ if (acc === void 0 || comparator2(c.value, acc[0]) < 0) {
1972
+ return [c.value, i];
1973
+ }
1974
+ return acc;
1975
+ },
1976
+ void 0
1782
1977
  );
1978
+ assert(min !== void 0, "min is undefined");
1979
+ current[min[1]] = iterators[min[1]].next();
1980
+ if (lastYielded !== void 0 && distinct && comparator2(lastYielded, min[0]) === 0) {
1981
+ continue;
1982
+ }
1983
+ lastYielded = min[0];
1984
+ yield min[0];
1783
1985
  }
1784
- if (refs !== void 0) {
1785
- this.#refsCounted?.add(hash2);
1786
- const ps = refs.map((ref) => this.#changeRefCount(ref, delta));
1787
- await Promise.all(ps);
1788
- }
1789
- }
1790
- #ensureRefCountLoaded(hash2) {
1791
- let p = this.#loadedRefCountPromises.get(hash2);
1792
- if (p === void 0) {
1793
- p = (async () => {
1794
- const value = await this.#delegate.getRefCount(hash2) || 0;
1795
- this.#refCountUpdates.set(hash2, value);
1796
- return value;
1797
- })();
1798
- this.#loadedRefCountPromises.set(hash2, p);
1986
+ } finally {
1987
+ for (const it of iterators) {
1988
+ it.return?.();
1799
1989
  }
1800
- return p;
1801
- }
1802
- #updateRefCount(hash2, delta) {
1803
- const oldCount = this.#refCountUpdates.get(hash2);
1804
- assertNumber(oldCount);
1805
- this.#refCountUpdates.set(hash2, oldCount + delta);
1806
- return oldCount === 0 && delta === 1 || oldCount === 1 && delta === -1;
1807
1990
  }
1808
- };
1991
+ }
1809
1992
 
1810
- // ../replicache/src/dag/store.ts
1811
- var ChunkNotFoundError = class extends Error {
1812
- name = "ChunkNotFoundError";
1813
- hash;
1814
- constructor(hash2) {
1815
- super(`Chunk not found ${hash2}`);
1816
- this.hash = hash2;
1817
- }
1818
- };
1819
- async function mustGetChunk(store, hash2) {
1820
- const chunk = await store.getChunk(hash2);
1821
- if (chunk) {
1822
- return chunk;
1993
+ // ../replicache/src/size-of-value.ts
1994
+ var SIZE_TAG = 1;
1995
+ var SIZE_INT32 = 4;
1996
+ var SIZE_SMI = 5;
1997
+ var SIZE_DOUBLE = 8;
1998
+ function getSizeOfValue(value) {
1999
+ switch (typeof value) {
2000
+ case "string":
2001
+ return SIZE_TAG + SIZE_INT32 + value.length;
2002
+ case "number":
2003
+ if (isSmi(value)) {
2004
+ if (value <= -(2 ** 30) || value >= 2 ** 30 - 1) {
2005
+ return SIZE_TAG + SIZE_SMI;
2006
+ }
2007
+ return SIZE_TAG + SIZE_INT32;
2008
+ }
2009
+ return SIZE_TAG + SIZE_DOUBLE;
2010
+ case "boolean":
2011
+ return SIZE_TAG;
2012
+ case "object":
2013
+ if (value === null) {
2014
+ return SIZE_TAG;
2015
+ }
2016
+ if (Array.isArray(value)) {
2017
+ let sum = 2 * SIZE_TAG + SIZE_INT32;
2018
+ for (const element of value) {
2019
+ sum += getSizeOfValue(element);
2020
+ }
2021
+ return sum;
2022
+ }
2023
+ {
2024
+ const val = value;
2025
+ let sum = 2 * SIZE_TAG + SIZE_INT32;
2026
+ for (const k in val) {
2027
+ if (hasOwn(val, k)) {
2028
+ const propertyValue = val[k];
2029
+ if (propertyValue !== void 0) {
2030
+ sum += getSizeOfValue(k) + getSizeOfValue(propertyValue);
2031
+ }
2032
+ }
2033
+ }
2034
+ return sum;
2035
+ }
1823
2036
  }
1824
- throw new ChunkNotFoundError(hash2);
2037
+ throw new Error(`Invalid value. type: ${typeof value}, value: ${value}`);
1825
2038
  }
1826
- async function mustGetHeadHash(name, store) {
1827
- const hash2 = await store.getHead(name);
1828
- assert(hash2, `Missing head ${name}`);
1829
- return hash2;
2039
+ function isSmi(value) {
2040
+ return value === (value | 0);
2041
+ }
2042
+ var entryFixed = 2 * SIZE_TAG + SIZE_INT32 + SIZE_TAG + SIZE_INT32;
2043
+ function getSizeOfEntry(key, value) {
2044
+ return entryFixed + getSizeOfValue(key) + getSizeOfValue(value);
1830
2045
  }
1831
2046
 
1832
2047
  // ../replicache/src/dag/lazy-store.ts
@@ -2327,193 +2542,6 @@ var ChunksCache = class {
2327
2542
  }
2328
2543
  };
2329
2544
 
2330
- // ../replicache/src/dag/key.ts
2331
- function chunkDataKey(hash2) {
2332
- return `c/${hash2}/d`;
2333
- }
2334
- function chunkMetaKey(hash2) {
2335
- return `c/${hash2}/m`;
2336
- }
2337
- function chunkRefCountKey(hash2) {
2338
- return `c/${hash2}/r`;
2339
- }
2340
- function headKey(name) {
2341
- return `h/${name}`;
2342
- }
2343
-
2344
- // ../replicache/src/dag/store-impl.ts
2345
- var StoreImpl = class {
2346
- #kv;
2347
- #chunkHasher;
2348
- #assertValidHash;
2349
- constructor(kv, chunkHasher, assertValidHash) {
2350
- this.#kv = kv;
2351
- this.#chunkHasher = chunkHasher;
2352
- this.#assertValidHash = assertValidHash;
2353
- }
2354
- async read() {
2355
- return new ReadImpl3(await this.#kv.read(), this.#assertValidHash);
2356
- }
2357
- async write() {
2358
- return new WriteImpl3(
2359
- await this.#kv.write(),
2360
- this.#chunkHasher,
2361
- this.#assertValidHash
2362
- );
2363
- }
2364
- close() {
2365
- return this.#kv.close();
2366
- }
2367
- };
2368
- var ReadImpl3 = class {
2369
- _tx;
2370
- assertValidHash;
2371
- constructor(kv, assertValidHash) {
2372
- this._tx = kv;
2373
- this.assertValidHash = assertValidHash;
2374
- }
2375
- hasChunk(hash2) {
2376
- return this._tx.has(chunkDataKey(hash2));
2377
- }
2378
- async getChunk(hash2) {
2379
- const data = await this._tx.get(chunkDataKey(hash2));
2380
- if (data === void 0) {
2381
- return void 0;
2382
- }
2383
- const refsVal = await this._tx.get(chunkMetaKey(hash2));
2384
- let refs;
2385
- if (refsVal !== void 0) {
2386
- assertRefs(refsVal);
2387
- refs = refsVal;
2388
- } else {
2389
- refs = [];
2390
- }
2391
- return new Chunk(hash2, data, refs);
2392
- }
2393
- mustGetChunk(hash2) {
2394
- return mustGetChunk(this, hash2);
2395
- }
2396
- async getHead(name) {
2397
- const data = await this._tx.get(headKey(name));
2398
- if (data === void 0) {
2399
- return void 0;
2400
- }
2401
- assertHash(data);
2402
- return data;
2403
- }
2404
- release() {
2405
- this._tx.release();
2406
- }
2407
- get closed() {
2408
- return this._tx.closed;
2409
- }
2410
- };
2411
- var WriteImpl3 = class extends ReadImpl3 {
2412
- #chunkHasher;
2413
- #putChunks = /* @__PURE__ */ new Set();
2414
- #changedHeads = /* @__PURE__ */ new Map();
2415
- constructor(kvw, chunkHasher, assertValidHash) {
2416
- super(kvw, assertValidHash);
2417
- this.#chunkHasher = chunkHasher;
2418
- }
2419
- createChunk = (data, refs) => createChunk(data, refs, this.#chunkHasher);
2420
- get kvWrite() {
2421
- return this._tx;
2422
- }
2423
- async putChunk(c) {
2424
- const { hash: hash2, data, meta } = c;
2425
- this.assertValidHash(hash2);
2426
- const key = chunkDataKey(hash2);
2427
- const p1 = this._tx.put(key, data);
2428
- let p2;
2429
- if (meta.length > 0) {
2430
- for (const h of meta) {
2431
- this.assertValidHash(h);
2432
- }
2433
- p2 = this._tx.put(chunkMetaKey(hash2), meta);
2434
- }
2435
- this.#putChunks.add(hash2);
2436
- await p1;
2437
- await p2;
2438
- }
2439
- setHead(name, hash2) {
2440
- return this.#setHead(name, hash2);
2441
- }
2442
- removeHead(name) {
2443
- return this.#setHead(name, void 0);
2444
- }
2445
- async #setHead(name, hash2) {
2446
- const oldHash = await this.getHead(name);
2447
- const hk = headKey(name);
2448
- let p1;
2449
- if (hash2 === void 0) {
2450
- p1 = this._tx.del(hk);
2451
- } else {
2452
- p1 = this._tx.put(hk, hash2);
2453
- }
2454
- const v2 = this.#changedHeads.get(name);
2455
- if (v2 === void 0) {
2456
- this.#changedHeads.set(name, { new: hash2, old: oldHash });
2457
- } else {
2458
- v2.new = hash2;
2459
- }
2460
- await p1;
2461
- }
2462
- async commit() {
2463
- const refCountUpdates = await computeRefCountUpdates(
2464
- this.#changedHeads.values(),
2465
- this.#putChunks,
2466
- this
2467
- );
2468
- await this.#applyRefCountUpdates(refCountUpdates);
2469
- await this._tx.commit();
2470
- }
2471
- async getRefCount(hash2) {
2472
- const value = await this._tx.get(chunkRefCountKey(hash2));
2473
- if (value === void 0) {
2474
- return void 0;
2475
- }
2476
- assertNumber(value);
2477
- if (value < 0 || value > 65535 || value !== (value | 0)) {
2478
- throw new Error(
2479
- `Invalid ref count ${value}. We expect the value to be a Uint16`
2480
- );
2481
- }
2482
- return value;
2483
- }
2484
- async getRefs(hash2) {
2485
- const meta = await this._tx.get(chunkMetaKey(hash2));
2486
- if (meta === void 0) {
2487
- return [];
2488
- }
2489
- assertRefs(meta);
2490
- return meta;
2491
- }
2492
- async #applyRefCountUpdates(refCountCache) {
2493
- const ps = [];
2494
- for (const [hash2, count] of refCountCache) {
2495
- if (count === 0) {
2496
- ps.push(this.#removeAllRelatedKeys(hash2));
2497
- } else {
2498
- const refCountKey = chunkRefCountKey(hash2);
2499
- ps.push(this._tx.put(refCountKey, count));
2500
- }
2501
- }
2502
- await Promise.all(ps);
2503
- }
2504
- async #removeAllRelatedKeys(hash2) {
2505
- await Promise.all([
2506
- this._tx.del(chunkDataKey(hash2)),
2507
- this._tx.del(chunkMetaKey(hash2)),
2508
- this._tx.del(chunkRefCountKey(hash2))
2509
- ]);
2510
- this.#putChunks.delete(hash2);
2511
- }
2512
- release() {
2513
- this._tx.release();
2514
- }
2515
- };
2516
-
2517
2545
  // ../replicache/src/db/meta-type-enum.ts
2518
2546
  var LocalDD31 = 4;
2519
2547
  var SnapshotDD31 = 5;
@@ -2999,13 +3027,13 @@ var DataNodeImpl = class extends NodeImpl {
2999
3027
  }
3000
3028
  }
3001
3029
  };
3002
- function readonlySplice(array10, start, deleteCount, ...items) {
3003
- const arr = array10.slice(0, start);
3030
+ function readonlySplice(array9, start, deleteCount, ...items) {
3031
+ const arr = array9.slice(0, start);
3004
3032
  for (let i = 0; i < items.length; i++) {
3005
3033
  arr.push(items[i]);
3006
3034
  }
3007
- for (let i = start + deleteCount; i < array10.length; i++) {
3008
- arr.push(array10[i]);
3035
+ for (let i = start + deleteCount; i < array9.length; i++) {
3036
+ arr.push(array9[i]);
3009
3037
  }
3010
3038
  return arr;
3011
3039
  }
@@ -3804,6 +3832,21 @@ function toDbScanOptions(options) {
3804
3832
  };
3805
3833
  }
3806
3834
 
3835
+ // ../replicache/src/transaction-closed-error.ts
3836
+ var TransactionClosedError = class extends Error {
3837
+ constructor() {
3838
+ super("Transaction is closed");
3839
+ }
3840
+ };
3841
+ function throwIfClosed(tx) {
3842
+ if (tx.closed) {
3843
+ throw new TransactionClosedError();
3844
+ }
3845
+ }
3846
+ function rejectIfClosed(tx) {
3847
+ return tx.closed ? Promise.reject(new TransactionClosedError()) : void 0;
3848
+ }
3849
+
3807
3850
  // ../replicache/src/scan-iterator.ts
3808
3851
  var ScanResultImpl = class {
3809
3852
  #iter;
@@ -4689,17 +4732,6 @@ function isDefaultPusher(pusher) {
4689
4732
  return defaultPushers.has(pusher);
4690
4733
  }
4691
4734
 
4692
- // ../replicache/src/log-options.ts
4693
- import {
4694
- consoleLogSink,
4695
- LogContext,
4696
- TeeLogSink
4697
- } from "@rocicorp/logger";
4698
- function createLogContext(logLevel = "info", logSinks = [consoleLogSink], context) {
4699
- const logSink = logSinks.length === 1 ? logSinks[0] : new TeeLogSink(logSinks);
4700
- return new LogContext(logLevel, context, logSink);
4701
- }
4702
-
4703
4735
  // ../replicache/src/index-defs.ts
4704
4736
  var indexDefinitionSchema = readonlyObject({
4705
4737
  prefix: valita_exports.string().optional(),
@@ -5492,47 +5524,13 @@ function initOnPersistChannel(replicacheName, signal, handlePersist) {
5492
5524
  // ../replicache/src/pending-mutations.ts
5493
5525
  async function pendingMutationsForAPI(dagRead) {
5494
5526
  const mainHeadHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagRead);
5495
- const pending = await localMutationsDD31(mainHeadHash, dagRead);
5496
- return pending.map((p) => ({
5497
- id: p.meta.mutationID,
5498
- name: p.meta.mutatorName,
5499
- args: p.meta.mutatorArgsJSON,
5500
- clientID: p.meta.clientID
5501
- })).reverse();
5502
- }
5503
-
5504
- // ../replicache/src/bg-interval.ts
5505
- function initBgIntervalProcess(processName, process2, delayMs, lc, signal) {
5506
- void runBgIntervalProcess(processName, process2, delayMs, lc, signal);
5507
- }
5508
- async function runBgIntervalProcess(processName, process2, delayMs, lc, signal) {
5509
- if (signal.aborted) {
5510
- return;
5511
- }
5512
- lc = lc.withContext("bgIntervalProcess", processName);
5513
- lc.debug?.("Starting");
5514
- while (!signal.aborted) {
5515
- try {
5516
- await sleep(delayMs(), signal);
5517
- } catch (e) {
5518
- if (!(e instanceof AbortError)) {
5519
- throw e;
5520
- }
5521
- }
5522
- if (!signal.aborted) {
5523
- lc.debug?.("Running");
5524
- try {
5525
- await process2();
5526
- } catch (e) {
5527
- if (signal.aborted) {
5528
- lc.debug?.("Error running most likely due to close.", e);
5529
- } else {
5530
- lc.error?.("Error running.", e);
5531
- }
5532
- }
5533
- }
5534
- }
5535
- lc.debug?.("Stopping");
5527
+ const pending = await localMutationsDD31(mainHeadHash, dagRead);
5528
+ return pending.map((p) => ({
5529
+ id: p.meta.mutationID,
5530
+ name: p.meta.mutatorName,
5531
+ args: p.meta.mutatorArgsJSON,
5532
+ clientID: p.meta.clientID
5533
+ })).reverse();
5536
5534
  }
5537
5535
 
5538
5536
  // ../replicache/src/persist/make-client-id.ts
@@ -5984,6 +5982,46 @@ function gcClientGroups(dagStore) {
5984
5982
  });
5985
5983
  }
5986
5984
 
5985
+ // ../replicache/src/persist/heartbeat.ts
5986
+ var HEARTBEAT_INTERVAL = 60 * 1e3;
5987
+ var latestHeartbeatUpdate;
5988
+ function startHeartbeats(clientID, dagStore, onClientStateNotFound, heartbeatIntervalMs, lc, signal) {
5989
+ initBgIntervalProcess(
5990
+ "Heartbeat",
5991
+ async () => {
5992
+ latestHeartbeatUpdate = writeHeartbeat(clientID, dagStore);
5993
+ try {
5994
+ return await latestHeartbeatUpdate;
5995
+ } catch (e) {
5996
+ if (e instanceof ClientStateNotFoundError) {
5997
+ onClientStateNotFound();
5998
+ return;
5999
+ }
6000
+ throw e;
6001
+ }
6002
+ },
6003
+ () => heartbeatIntervalMs,
6004
+ lc,
6005
+ signal
6006
+ );
6007
+ }
6008
+ function writeHeartbeat(clientID, dagStore) {
6009
+ return withWrite(dagStore, async (dagWrite) => {
6010
+ const clients = await getClients(dagWrite);
6011
+ const client = clients.get(clientID);
6012
+ if (!client) {
6013
+ throw new ClientStateNotFoundError(clientID);
6014
+ }
6015
+ const newClient = {
6016
+ ...client,
6017
+ heartbeatTimestampMs: Date.now()
6018
+ };
6019
+ const newClients = new Map(clients).set(clientID, newClient);
6020
+ await setClients(newClients, dagWrite);
6021
+ return newClients;
6022
+ });
6023
+ }
6024
+
5987
6025
  // ../replicache/src/persist/idb-databases-store-db-name.ts
5988
6026
  var IDB_DATABASES_VERSION = 0;
5989
6027
  var IDB_DATABASES_DB_NAME = "replicache-dbs-v" + IDB_DATABASES_VERSION;
@@ -6044,215 +6082,37 @@ var IDBDatabasesStore = class {
6044
6082
  const dbRecord = {
6045
6083
  ...oldDbRecord
6046
6084
  };
6047
- for (const name of names) {
6048
- delete dbRecord[name];
6049
- }
6050
- await write.put(DBS_KEY, dbRecord);
6051
- });
6052
- }
6053
- getDatabases() {
6054
- return withRead(this.#kvStore, getDatabases);
6055
- }
6056
- close() {
6057
- return this.#kvStore.close();
6058
- }
6059
- getProfileID() {
6060
- return withWrite(this.#kvStore, async (write) => {
6061
- let profileId = await write.get(PROFILE_ID_KEY);
6062
- if (profileId === void 0) {
6063
- profileId = `p${makeClientID()}`;
6064
- await write.put(PROFILE_ID_KEY, profileId);
6065
- }
6066
- assertString(profileId);
6067
- return profileId;
6068
- });
6069
- }
6070
- };
6071
- async function getDatabases(read) {
6072
- let dbRecord = await read.get(DBS_KEY);
6073
- if (!dbRecord) {
6074
- dbRecord = deepFreeze({});
6075
- }
6076
- assertIndexedDBDatabaseRecord(dbRecord);
6077
- return dbRecord;
6078
- }
6079
-
6080
- // ../replicache/src/persist/collect-idb-databases.ts
6081
- var COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1e3;
6082
- var SDD_IDB_MAX_AGE = 30 * 24 * 60 * 60 * 1e3;
6083
- var DD31_IDB_MAX_AGE = 14 * 24 * 60 * 60 * 1e3;
6084
- var INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1e3;
6085
- function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval, initialCollectDelay, sddMaxAge, dd31MaxAge, lc, signal) {
6086
- let initial = true;
6087
- initBgIntervalProcess(
6088
- "CollectIDBDatabases",
6089
- async () => {
6090
- await collectIDBDatabases(
6091
- idbDatabasesStore,
6092
- Date.now(),
6093
- sddMaxAge,
6094
- dd31MaxAge,
6095
- kvDropStore
6096
- );
6097
- },
6098
- () => {
6099
- if (initial) {
6100
- initial = false;
6101
- return initialCollectDelay;
6102
- }
6103
- return collectInterval;
6104
- },
6105
- lc,
6106
- signal
6107
- );
6108
- }
6109
- async function collectIDBDatabases(idbDatabasesStore, now, sddMaxAge, dd31MaxAge, kvDropStore, newDagStore = defaultNewDagStore) {
6110
- const databases = await idbDatabasesStore.getDatabases();
6111
- const dbs = Object.values(databases);
6112
- const canCollectResults = await Promise.all(
6113
- dbs.map(
6114
- async (db) => [
6115
- db.name,
6116
- await canCollectDatabase(db, now, sddMaxAge, dd31MaxAge, newDagStore)
6117
- ]
6118
- )
6119
- );
6120
- const namesToRemove = canCollectResults.filter((result) => result[1]).map((result) => result[0]);
6121
- const { errors } = await dropDatabases(
6122
- idbDatabasesStore,
6123
- namesToRemove,
6124
- kvDropStore
6125
- );
6126
- if (errors.length) {
6127
- throw errors[0];
6128
- }
6129
- }
6130
- async function dropDatabaseInternal(name, idbDatabasesStore, kvDropStore) {
6131
- await kvDropStore(name);
6132
- await idbDatabasesStore.deleteDatabases([name]);
6133
- }
6134
- async function dropDatabases(idbDatabasesStore, namesToRemove, kvDropStore) {
6135
- const dropStoreResults = await Promise.allSettled(
6136
- namesToRemove.map(async (name) => {
6137
- await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);
6138
- return name;
6139
- })
6140
- );
6141
- const dropped = [];
6142
- const errors = [];
6143
- for (const result of dropStoreResults) {
6144
- if (result.status === "fulfilled") {
6145
- dropped.push(result.value);
6146
- } else {
6147
- errors.push(result.reason);
6148
- }
6149
- }
6150
- return { dropped, errors };
6151
- }
6152
- function defaultNewDagStore(name) {
6153
- const perKvStore = new IDBStore(name);
6154
- return new StoreImpl(perKvStore, newRandomHash, assertHash);
6155
- }
6156
- async function canCollectDatabase(db, now, sddMaxAge, dd31MaxAge, newDagStore) {
6157
- if (db.replicacheFormatVersion > Latest) {
6158
- return false;
6159
- }
6160
- if (db.lastOpenedTimestampMS !== void 0) {
6161
- const isDD31 = db.replicacheFormatVersion >= DD31;
6162
- if (now - db.lastOpenedTimestampMS < (isDD31 ? dd31MaxAge : sddMaxAge)) {
6163
- return false;
6164
- }
6165
- if (!isDD31) {
6166
- return true;
6167
- }
6168
- assert(
6169
- db.replicacheFormatVersion === DD31 || db.replicacheFormatVersion === V6 || db.replicacheFormatVersion === V7
6170
- );
6171
- return !await anyPendingMutationsInClientGroups(newDagStore(db.name));
6172
- }
6173
- const perdag = newDagStore(db.name);
6174
- const clientMap = await withRead(perdag, getClients);
6175
- await perdag.close();
6176
- return allClientsOlderThan(clientMap, now, sddMaxAge);
6177
- }
6178
- function allClientsOlderThan(clients, now, maxAge) {
6179
- for (const client of clients.values()) {
6180
- if (now - client.heartbeatTimestampMs < maxAge) {
6181
- return false;
6182
- }
6183
- }
6184
- return true;
6185
- }
6186
- async function dropDatabase(dbName, opts) {
6187
- const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {
6188
- dropDatabase: void 0
6189
- });
6190
- const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);
6191
- await dropDatabaseInternal(
6192
- dbName,
6193
- new IDBDatabasesStore(kvStoreProvider.create),
6194
- kvStoreProvider.drop
6195
- );
6196
- }
6197
- async function dropAllDatabases(opts) {
6198
- const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {
6199
- dropAllDatabases: void 0
6200
- });
6201
- const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);
6202
- const store = new IDBDatabasesStore(kvStoreProvider.create);
6203
- const databases = await store.getDatabases();
6204
- const dbNames = Object.values(databases).map((db) => db.name);
6205
- const result = await dropDatabases(store, dbNames, kvStoreProvider.drop);
6206
- return result;
6207
- }
6208
- async function anyPendingMutationsInClientGroups(perdag) {
6209
- const clientGroups = await withRead(perdag, getClientGroups);
6210
- for (const clientGroup of clientGroups.values()) {
6211
- if (clientGroupHasPendingMutations(clientGroup)) {
6212
- return true;
6213
- }
6214
- }
6215
- return false;
6216
- }
6217
-
6218
- // ../replicache/src/persist/heartbeat.ts
6219
- var HEARTBEAT_INTERVAL = 60 * 1e3;
6220
- var latestHeartbeatUpdate;
6221
- function startHeartbeats(clientID, dagStore, onClientStateNotFound, heartbeatIntervalMs, lc, signal) {
6222
- initBgIntervalProcess(
6223
- "Heartbeat",
6224
- async () => {
6225
- latestHeartbeatUpdate = writeHeartbeat(clientID, dagStore);
6226
- try {
6227
- return await latestHeartbeatUpdate;
6228
- } catch (e) {
6229
- if (e instanceof ClientStateNotFoundError) {
6230
- onClientStateNotFound();
6231
- return;
6232
- }
6233
- throw e;
6234
- }
6235
- },
6236
- () => heartbeatIntervalMs,
6237
- lc,
6238
- signal
6239
- );
6240
- }
6241
- function writeHeartbeat(clientID, dagStore) {
6242
- return withWrite(dagStore, async (dagWrite) => {
6243
- const clients = await getClients(dagWrite);
6244
- const client = clients.get(clientID);
6245
- if (!client) {
6246
- throw new ClientStateNotFoundError(clientID);
6247
- }
6248
- const newClient = {
6249
- ...client,
6250
- heartbeatTimestampMs: Date.now()
6251
- };
6252
- const newClients = new Map(clients).set(clientID, newClient);
6253
- await setClients(newClients, dagWrite);
6254
- return newClients;
6255
- });
6085
+ for (const name of names) {
6086
+ delete dbRecord[name];
6087
+ }
6088
+ await write.put(DBS_KEY, dbRecord);
6089
+ });
6090
+ }
6091
+ getDatabases() {
6092
+ return withRead(this.#kvStore, getDatabases);
6093
+ }
6094
+ close() {
6095
+ return this.#kvStore.close();
6096
+ }
6097
+ getProfileID() {
6098
+ return withWrite(this.#kvStore, async (write) => {
6099
+ let profileId = await write.get(PROFILE_ID_KEY);
6100
+ if (profileId === void 0) {
6101
+ profileId = `p${makeClientID()}`;
6102
+ await write.put(PROFILE_ID_KEY, profileId);
6103
+ }
6104
+ assertString(profileId);
6105
+ return profileId;
6106
+ });
6107
+ }
6108
+ };
6109
+ async function getDatabases(read) {
6110
+ let dbRecord = await read.get(DBS_KEY);
6111
+ if (!dbRecord) {
6112
+ dbRecord = deepFreeze({});
6113
+ }
6114
+ assertIndexedDBDatabaseRecord(dbRecord);
6115
+ return dbRecord;
6256
6116
  }
6257
6117
 
6258
6118
  // ../replicache/src/dag/visitor.ts
@@ -7130,14 +6990,14 @@ function diffBinarySearch(diff2, prefix, compareKey) {
7130
6990
  }
7131
6991
 
7132
6992
  // ../shared/src/random-values.ts
7133
- function getNonCryptoRandomValues(array10) {
7134
- if (array10 === null) {
6993
+ function getNonCryptoRandomValues(array9) {
6994
+ if (array9 === null) {
7135
6995
  throw new TypeError("array cannot be null");
7136
6996
  }
7137
- for (let i = 0; i < array10.length; i++) {
7138
- array10[i] = Math.floor(Math.random() * 256);
6997
+ for (let i = 0; i < array9.length; i++) {
6998
+ array9[i] = Math.floor(Math.random() * 256);
7139
6999
  }
7140
- return array10;
7000
+ return array9;
7141
7001
  }
7142
7002
 
7143
7003
  // ../replicache/src/sync/request-id.ts
@@ -8307,8 +8167,143 @@ function getKVStoreProvider(lc, kvStore) {
8307
8167
  }
8308
8168
  }
8309
8169
 
8310
- // ../replicache/src/mod.ts
8311
- import { consoleLogSink as consoleLogSink3 } from "@rocicorp/logger";
8170
+ // ../replicache/src/persist/collect-idb-databases.ts
8171
+ var COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1e3;
8172
+ var SDD_IDB_MAX_AGE = 30 * 24 * 60 * 60 * 1e3;
8173
+ var DD31_IDB_MAX_AGE = 14 * 24 * 60 * 60 * 1e3;
8174
+ var INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1e3;
8175
+ function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval, initialCollectDelay, sddMaxAge, dd31MaxAge, lc, signal) {
8176
+ let initial = true;
8177
+ initBgIntervalProcess(
8178
+ "CollectIDBDatabases",
8179
+ async () => {
8180
+ await collectIDBDatabases(
8181
+ idbDatabasesStore,
8182
+ Date.now(),
8183
+ sddMaxAge,
8184
+ dd31MaxAge,
8185
+ kvDropStore
8186
+ );
8187
+ },
8188
+ () => {
8189
+ if (initial) {
8190
+ initial = false;
8191
+ return initialCollectDelay;
8192
+ }
8193
+ return collectInterval;
8194
+ },
8195
+ lc,
8196
+ signal
8197
+ );
8198
+ }
8199
+ async function collectIDBDatabases(idbDatabasesStore, now, sddMaxAge, dd31MaxAge, kvDropStore, newDagStore = defaultNewDagStore) {
8200
+ const databases = await idbDatabasesStore.getDatabases();
8201
+ const dbs = Object.values(databases);
8202
+ const canCollectResults = await Promise.all(
8203
+ dbs.map(
8204
+ async (db) => [
8205
+ db.name,
8206
+ await canCollectDatabase(db, now, sddMaxAge, dd31MaxAge, newDagStore)
8207
+ ]
8208
+ )
8209
+ );
8210
+ const namesToRemove = canCollectResults.filter((result) => result[1]).map((result) => result[0]);
8211
+ const { errors } = await dropDatabases(
8212
+ idbDatabasesStore,
8213
+ namesToRemove,
8214
+ kvDropStore
8215
+ );
8216
+ if (errors.length) {
8217
+ throw errors[0];
8218
+ }
8219
+ }
8220
+ async function dropDatabaseInternal(name, idbDatabasesStore, kvDropStore) {
8221
+ await kvDropStore(name);
8222
+ await idbDatabasesStore.deleteDatabases([name]);
8223
+ }
8224
+ async function dropDatabases(idbDatabasesStore, namesToRemove, kvDropStore) {
8225
+ const dropStoreResults = await Promise.allSettled(
8226
+ namesToRemove.map(async (name) => {
8227
+ await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);
8228
+ return name;
8229
+ })
8230
+ );
8231
+ const dropped = [];
8232
+ const errors = [];
8233
+ for (const result of dropStoreResults) {
8234
+ if (result.status === "fulfilled") {
8235
+ dropped.push(result.value);
8236
+ } else {
8237
+ errors.push(result.reason);
8238
+ }
8239
+ }
8240
+ return { dropped, errors };
8241
+ }
8242
+ function defaultNewDagStore(name) {
8243
+ const perKvStore = new IDBStore(name);
8244
+ return new StoreImpl(perKvStore, newRandomHash, assertHash);
8245
+ }
8246
+ async function canCollectDatabase(db, now, sddMaxAge, dd31MaxAge, newDagStore) {
8247
+ if (db.replicacheFormatVersion > Latest) {
8248
+ return false;
8249
+ }
8250
+ if (db.lastOpenedTimestampMS !== void 0) {
8251
+ const isDD31 = db.replicacheFormatVersion >= DD31;
8252
+ if (now - db.lastOpenedTimestampMS < (isDD31 ? dd31MaxAge : sddMaxAge)) {
8253
+ return false;
8254
+ }
8255
+ if (!isDD31) {
8256
+ return true;
8257
+ }
8258
+ assert(
8259
+ db.replicacheFormatVersion === DD31 || db.replicacheFormatVersion === V6 || db.replicacheFormatVersion === V7
8260
+ );
8261
+ return !await anyPendingMutationsInClientGroups(newDagStore(db.name));
8262
+ }
8263
+ const perdag = newDagStore(db.name);
8264
+ const clientMap = await withRead(perdag, getClients);
8265
+ await perdag.close();
8266
+ return allClientsOlderThan(clientMap, now, sddMaxAge);
8267
+ }
8268
+ function allClientsOlderThan(clients, now, maxAge) {
8269
+ for (const client of clients.values()) {
8270
+ if (now - client.heartbeatTimestampMs < maxAge) {
8271
+ return false;
8272
+ }
8273
+ }
8274
+ return true;
8275
+ }
8276
+ async function dropDatabase(dbName, opts) {
8277
+ const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {
8278
+ dropDatabase: void 0
8279
+ });
8280
+ const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);
8281
+ await dropDatabaseInternal(
8282
+ dbName,
8283
+ new IDBDatabasesStore(kvStoreProvider.create),
8284
+ kvStoreProvider.drop
8285
+ );
8286
+ }
8287
+ async function dropAllDatabases(opts) {
8288
+ const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {
8289
+ dropAllDatabases: void 0
8290
+ });
8291
+ const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);
8292
+ const store = new IDBDatabasesStore(kvStoreProvider.create);
8293
+ const databases = await store.getDatabases();
8294
+ const dbNames = Object.values(databases).map((db) => db.name);
8295
+ const result = await dropDatabases(store, dbNames, kvStoreProvider.drop);
8296
+ return result;
8297
+ }
8298
+ async function anyPendingMutationsInClientGroups(perdag) {
8299
+ const clientGroups = await withRead(perdag, getClientGroups);
8300
+ for (const clientGroup of clientGroups.values()) {
8301
+ if (clientGroupHasPendingMutations(clientGroup)) {
8302
+ return true;
8303
+ }
8304
+ }
8305
+ return false;
8306
+ }
8312
8307
 
8313
8308
  // ../zero-schema/src/builder/relationship-builder.ts
8314
8309
  function relationships(table2, cb) {
@@ -8898,8 +8893,8 @@ var negateOperatorMap = {
8898
8893
  function negateOperator(op) {
8899
8894
  return must(negateOperatorMap[op]);
8900
8895
  }
8901
- function filterUndefined(array10) {
8902
- return array10.filter((e) => e !== void 0);
8896
+ function filterUndefined(array9) {
8897
+ return array9.filter((e) => e !== void 0);
8903
8898
  }
8904
8899
  function filterTrue(conditions) {
8905
8900
  return conditions.filter((c) => !isAlwaysTrue(c));
@@ -11428,25 +11423,6 @@ function escapeLike(val) {
11428
11423
  import { LogContext as LogContext4 } from "@rocicorp/logger";
11429
11424
  import { resolver as resolver8 } from "@rocicorp/resolver";
11430
11425
 
11431
- // ../zero-protocol/src/error-kind-enum.ts
11432
- var AuthInvalidated = "AuthInvalidated";
11433
- var ClientNotFound = "ClientNotFound";
11434
- var InvalidConnectionRequest = "InvalidConnectionRequest";
11435
- var InvalidConnectionRequestBaseCookie = "InvalidConnectionRequestBaseCookie";
11436
- var InvalidConnectionRequestLastMutationID = "InvalidConnectionRequestLastMutationID";
11437
- var InvalidConnectionRequestClientDeleted = "InvalidConnectionRequestClientDeleted";
11438
- var InvalidMessage = "InvalidMessage";
11439
- var InvalidPush = "InvalidPush";
11440
- var MutationFailed = "MutationFailed";
11441
- var MutationRateLimited = "MutationRateLimited";
11442
- var Rebalance = "Rebalance";
11443
- var Rehome = "Rehome";
11444
- var Unauthorized = "Unauthorized";
11445
- var VersionNotSupported = "VersionNotSupported";
11446
- var SchemaVersionNotSupported = "SchemaVersionNotSupported";
11447
- var ServerOverloaded = "ServerOverloaded";
11448
- var Internal = "Internal";
11449
-
11450
11426
  // ../zero-protocol/src/queries-patch.ts
11451
11427
  var putOpSchema = valita_exports.object({
11452
11428
  op: valita_exports.literal("put"),
@@ -11463,30 +11439,6 @@ var clearOpSchema = valita_exports.object({
11463
11439
  var patchOpSchema = valita_exports.union(putOpSchema, delOpSchema, clearOpSchema);
11464
11440
  var queriesPatchSchema = valita_exports.array(patchOpSchema);
11465
11441
 
11466
- // ../zero-protocol/src/change-desired-queries.ts
11467
- var changeDesiredQueriesBodySchema = valita_exports.object({
11468
- desiredQueriesPatch: queriesPatchSchema
11469
- });
11470
- var changeDesiredQueriesMessageSchema = valita_exports.tuple([
11471
- valita_exports.literal("changeDesiredQueries"),
11472
- changeDesiredQueriesBodySchema
11473
- ]);
11474
-
11475
- // ../zero-protocol/src/clients-patch.ts
11476
- var putOpSchema2 = valita_exports.object({
11477
- op: valita_exports.literal("put"),
11478
- clientID: valita_exports.string()
11479
- });
11480
- var delOpSchema2 = valita_exports.object({
11481
- op: valita_exports.literal("del"),
11482
- clientID: valita_exports.string()
11483
- });
11484
- var clearOpSchema2 = valita_exports.object({
11485
- op: valita_exports.literal("clear")
11486
- });
11487
- var patchOpSchema2 = valita_exports.union(putOpSchema2, delOpSchema2, clearOpSchema2);
11488
- var clientsPatchSchema = valita_exports.array(patchOpSchema2);
11489
-
11490
11442
  // ../zero-protocol/src/connect.ts
11491
11443
  var connectedBodySchema = valita_exports.object({
11492
11444
  wsid: valita_exports.string(),
@@ -11511,6 +11463,25 @@ function encodeSecProtocols(initConnectionMessage, authToken) {
11511
11463
  return encodeURIComponent(btoa(JSON.stringify(protocols)));
11512
11464
  }
11513
11465
 
11466
+ // ../zero-protocol/src/error-kind-enum.ts
11467
+ var AuthInvalidated = "AuthInvalidated";
11468
+ var ClientNotFound = "ClientNotFound";
11469
+ var InvalidConnectionRequest = "InvalidConnectionRequest";
11470
+ var InvalidConnectionRequestBaseCookie = "InvalidConnectionRequestBaseCookie";
11471
+ var InvalidConnectionRequestLastMutationID = "InvalidConnectionRequestLastMutationID";
11472
+ var InvalidConnectionRequestClientDeleted = "InvalidConnectionRequestClientDeleted";
11473
+ var InvalidMessage = "InvalidMessage";
11474
+ var InvalidPush = "InvalidPush";
11475
+ var MutationFailed = "MutationFailed";
11476
+ var MutationRateLimited = "MutationRateLimited";
11477
+ var Rebalance = "Rebalance";
11478
+ var Rehome = "Rehome";
11479
+ var Unauthorized = "Unauthorized";
11480
+ var VersionNotSupported = "VersionNotSupported";
11481
+ var SchemaVersionNotSupported = "SchemaVersionNotSupported";
11482
+ var ServerOverloaded = "ServerOverloaded";
11483
+ var Internal = "Internal";
11484
+
11514
11485
  // ../zero-protocol/src/error.ts
11515
11486
  var basicErrorKindSchema = valita_exports.union(
11516
11487
  valita_exports.literal(AuthInvalidated),
@@ -11557,6 +11528,21 @@ var errorMessageSchema = valita_exports.tuple([
11557
11528
  errorBodySchema
11558
11529
  ]);
11559
11530
 
11531
+ // ../zero-protocol/src/clients-patch.ts
11532
+ var putOpSchema2 = valita_exports.object({
11533
+ op: valita_exports.literal("put"),
11534
+ clientID: valita_exports.string()
11535
+ });
11536
+ var delOpSchema2 = valita_exports.object({
11537
+ op: valita_exports.literal("del"),
11538
+ clientID: valita_exports.string()
11539
+ });
11540
+ var clearOpSchema2 = valita_exports.object({
11541
+ op: valita_exports.literal("clear")
11542
+ });
11543
+ var patchOpSchema2 = valita_exports.union(putOpSchema2, delOpSchema2, clearOpSchema2);
11544
+ var clientsPatchSchema = valita_exports.array(patchOpSchema2);
11545
+
11560
11546
  // ../zero-protocol/src/primary-key.ts
11561
11547
  var primaryKeySchema = readonly(
11562
11548
  valita_exports.tuple([valita_exports.string()]).concat(valita_exports.array(valita_exports.string()))
@@ -11700,14 +11686,15 @@ var downstreamSchema = valita_exports.union(
11700
11686
  pullResponseMessageSchema
11701
11687
  );
11702
11688
 
11703
- // ../zero-protocol/src/ping.ts
11704
- var pingBodySchema = valita_exports.object({});
11705
- var pingMessageSchema = valita_exports.tuple([valita_exports.literal("ping"), pingBodySchema]);
11706
-
11707
11689
  // ../zero-protocol/src/mutation-type-enum.ts
11708
11690
  var CRUD = "crud";
11709
11691
  var Custom = "custom";
11710
11692
 
11693
+ // ../zero-protocol/src/protocol-version.ts
11694
+ var PROTOCOL_VERSION = 4;
11695
+ var MIN_SERVER_SUPPORTED_PROTOCOL_VERSION = 2;
11696
+ assert(MIN_SERVER_SUPPORTED_PROTOCOL_VERSION < PROTOCOL_VERSION);
11697
+
11711
11698
  // ../zero-protocol/src/push.ts
11712
11699
  var CRUD_MUTATION_NAME = "_zero_crud";
11713
11700
  var insertOpSchema = valita_exports.object({
@@ -11773,30 +11760,6 @@ var pushBodySchema = valita_exports.object({
11773
11760
  });
11774
11761
  var pushMessageSchema = valita_exports.tuple([valita_exports.literal("push"), pushBodySchema]);
11775
11762
 
11776
- // ../zero-protocol/src/delete-clients.ts
11777
- var deleteClientsBodySchema = valita_exports.object({
11778
- clientIDs: valita_exports.array(valita_exports.string())
11779
- });
11780
- var deleteClientsMessageSchema = valita_exports.tuple([
11781
- valita_exports.literal("deleteClients"),
11782
- deleteClientsBodySchema
11783
- ]);
11784
-
11785
- // ../zero-protocol/src/up.ts
11786
- var upstreamSchema = valita_exports.union(
11787
- initConnectionMessageSchema,
11788
- pingMessageSchema,
11789
- deleteClientsMessageSchema,
11790
- changeDesiredQueriesMessageSchema,
11791
- pullRequestMessageSchema,
11792
- pushMessageSchema
11793
- );
11794
-
11795
- // ../zero-protocol/src/protocol-version.ts
11796
- var PROTOCOL_VERSION = 4;
11797
- var MIN_SERVER_SUPPORTED_PROTOCOL_VERSION = 2;
11798
- assert(MIN_SERVER_SUPPORTED_PROTOCOL_VERSION < PROTOCOL_VERSION);
11799
-
11800
11763
  // ../zero-client/src/util/nanoid.ts
11801
11764
  function nanoid(size = 21) {
11802
11765
  const randomBytes = getNonCryptoRandomValues(new Uint8Array(size));
@@ -13150,7 +13113,7 @@ function appendPath(url, toAppend) {
13150
13113
  // ../zero-client/src/client/log-options.ts
13151
13114
  import {
13152
13115
  TeeLogSink as TeeLogSink2,
13153
- consoleLogSink as consoleLogSink4
13116
+ consoleLogSink as consoleLogSink3
13154
13117
  } from "@rocicorp/logger";
13155
13118
 
13156
13119
  // ../datadog/src/datadog-log-sink.ts
@@ -13372,7 +13335,7 @@ function makeMessage(message, context, logLevel) {
13372
13335
  }
13373
13336
 
13374
13337
  // ../zero-client/src/client/version.ts
13375
- var version2 = "0.12.2025013000";
13338
+ var version2 = "0.12.2025013100";
13376
13339
 
13377
13340
  // ../zero-client/src/client/log-options.ts
13378
13341
  var LevelFilterLogSink = class {
@@ -13392,7 +13355,7 @@ var LevelFilterLogSink = class {
13392
13355
  this.#wrappedLogSink.log(level, context, ...args);
13393
13356
  }
13394
13357
  async flush() {
13395
- await consoleLogSink4.flush?.();
13358
+ await consoleLogSink3.flush?.();
13396
13359
  }
13397
13360
  };
13398
13361
  var DATADOG_LOG_LEVEL = "info";
@@ -13402,7 +13365,7 @@ function createLogOptions(options, createDatadogLogSink = (options2) => new Data
13402
13365
  if (!enableAnalytics || server === null) {
13403
13366
  return {
13404
13367
  logLevel: consoleLogLevel,
13405
- logSink: consoleLogSink4
13368
+ logSink: consoleLogSink3
13406
13369
  };
13407
13370
  }
13408
13371
  const serverURL = new URL(server);
@@ -13411,7 +13374,7 @@ function createLogOptions(options, createDatadogLogSink = (options2) => new Data
13411
13374
  const baseURL = new URL(appendPath(server, "/logs/v0/log"));
13412
13375
  const logLevel = consoleLogLevel === "debug" ? "debug" : "info";
13413
13376
  const logSink = new TeeLogSink2([
13414
- new LevelFilterLogSink(consoleLogSink4, consoleLogLevel),
13377
+ new LevelFilterLogSink(consoleLogSink3, consoleLogLevel),
13415
13378
  new LevelFilterLogSink(
13416
13379
  createDatadogLogSink({
13417
13380
  service: datadogServiceLabel,
@@ -14973,23 +14936,23 @@ var Zero = class {
14973
14936
  this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
14974
14937
  this.#pokeHandler.handleDisconnect();
14975
14938
  }
14976
- async #handlePokeStart(_lc, pokeMessage) {
14939
+ #handlePokeStart(_lc, pokeMessage) {
14977
14940
  resetBackoff();
14978
14941
  this.#abortPingTimeout();
14979
- await this.#pokeHandler.handlePokeStart(pokeMessage[1]);
14942
+ this.#pokeHandler.handlePokeStart(pokeMessage[1]);
14980
14943
  }
14981
- async #handlePokePart(_lc, pokeMessage) {
14944
+ #handlePokePart(_lc, pokeMessage) {
14982
14945
  this.#abortPingTimeout();
14983
- const lastMutationIDChangeForSelf = await this.#pokeHandler.handlePokePart(
14946
+ const lastMutationIDChangeForSelf = this.#pokeHandler.handlePokePart(
14984
14947
  pokeMessage[1]
14985
14948
  );
14986
14949
  if (lastMutationIDChangeForSelf !== void 0) {
14987
14950
  this.#lastMutationIDReceived = lastMutationIDChangeForSelf;
14988
14951
  }
14989
14952
  }
14990
- async #handlePokeEnd(_lc, pokeMessage) {
14953
+ #handlePokeEnd(_lc, pokeMessage) {
14991
14954
  this.#abortPingTimeout();
14992
- await this.#pokeHandler.handlePokeEnd(pokeMessage[1]);
14955
+ this.#pokeHandler.handlePokeEnd(pokeMessage[1]);
14993
14956
  }
14994
14957
  #onPokeError() {
14995
14958
  const lc = this.#lc;
@@ -15439,4 +15402,4 @@ export {
15439
15402
  escapeLike,
15440
15403
  Zero
15441
15404
  };
15442
- //# sourceMappingURL=chunk-UEPZPKPV.js.map
15405
+ //# sourceMappingURL=chunk-XBQPXRPX.js.map