on-zero 0.4.31 → 0.4.33

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 (126) hide show
  1. package/dist/cjs/cli.native.js.map +1 -1
  2. package/dist/cjs/combineZeroClients.native.js.map +1 -1
  3. package/dist/cjs/createPermissions.native.js.map +1 -1
  4. package/dist/cjs/createSchemaFromDrizzle.native.js.map +1 -1
  5. package/dist/cjs/createUseQuery.native.js.map +1 -1
  6. package/dist/cjs/createZeroClient.authData.test.cjs +67 -0
  7. package/dist/cjs/createZeroClient.authData.test.native.js +72 -0
  8. package/dist/cjs/createZeroClient.authData.test.native.js.map +1 -0
  9. package/dist/cjs/createZeroClient.cjs +41 -26
  10. package/dist/cjs/createZeroClient.native.js +47 -26
  11. package/dist/cjs/createZeroClient.native.js.map +1 -1
  12. package/dist/cjs/createZeroServer.native.js.map +1 -1
  13. package/dist/cjs/generate-helpers.native.js.map +1 -1
  14. package/dist/cjs/generate-lite.native.js.map +1 -1
  15. package/dist/cjs/generate-lite.test.native.js.map +1 -1
  16. package/dist/cjs/generate.cjs +41 -0
  17. package/dist/cjs/generate.native.js +63 -0
  18. package/dist/cjs/generate.native.js.map +1 -1
  19. package/dist/cjs/generate.test.native.js.map +1 -1
  20. package/dist/cjs/helpers/batchQuery.native.js.map +1 -1
  21. package/dist/cjs/helpers/clearZeroClientData.native.js.map +1 -1
  22. package/dist/cjs/helpers/createMutators.native.js.map +1 -1
  23. package/dist/cjs/helpers/didRunPermissionCheck.native.js.map +1 -1
  24. package/dist/cjs/helpers/ensureLoggedIn.native.js.map +1 -1
  25. package/dist/cjs/helpers/getAuth.native.js.map +1 -1
  26. package/dist/cjs/helpers/mutatorContext.native.js.map +1 -1
  27. package/dist/cjs/helpers/prettyFormatZeroQuery.native.js.map +1 -1
  28. package/dist/cjs/helpers/queryContext.native.js.map +1 -1
  29. package/dist/cjs/helpers/recoverZeroClient.cjs +101 -0
  30. package/dist/cjs/helpers/recoverZeroClient.native.js +130 -0
  31. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -0
  32. package/dist/cjs/helpers/recoverZeroClient.test.cjs +201 -0
  33. package/dist/cjs/helpers/recoverZeroClient.test.native.js +256 -0
  34. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -0
  35. package/dist/cjs/helpers/showZeroClientError.native.js.map +1 -1
  36. package/dist/cjs/helpers/useMutation.native.js.map +1 -1
  37. package/dist/cjs/helpers/useMutation.test.native.js.map +1 -1
  38. package/dist/cjs/helpers/useZeroDebug.native.js.map +1 -1
  39. package/dist/cjs/httpPull/auth.test.native.js.map +1 -1
  40. package/dist/cjs/httpPull/churn.test.native.js.map +1 -1
  41. package/dist/cjs/httpPull/fixtureSchema.native.js.map +1 -1
  42. package/dist/cjs/httpPull/fixtureServer.native.js.map +1 -1
  43. package/dist/cjs/httpPull/integration.test.native.js.map +1 -1
  44. package/dist/cjs/httpPull/rebase.test.native.js.map +1 -1
  45. package/dist/cjs/httpPull/relations.test.native.js.map +1 -1
  46. package/dist/cjs/httpPull/testHarness.native.js.map +1 -1
  47. package/dist/cjs/httpPull/transport.test.native.js.map +1 -1
  48. package/dist/cjs/httpPullTransport.native.js.map +1 -1
  49. package/dist/cjs/index.cjs +4 -1
  50. package/dist/cjs/index.native.js +3 -0
  51. package/dist/cjs/index.native.js.map +1 -1
  52. package/dist/cjs/instanceRegistry.native.js.map +1 -1
  53. package/dist/cjs/modelRegistry.native.js.map +1 -1
  54. package/dist/cjs/multiInstance.test.cjs +4 -3
  55. package/dist/cjs/multiInstance.test.native.js +6 -6
  56. package/dist/cjs/multiInstance.test.native.js.map +1 -1
  57. package/dist/cjs/multiInstanceNested.test.native.js.map +1 -1
  58. package/dist/cjs/mutations.native.js.map +1 -1
  59. package/dist/cjs/queryRegistry.native.js.map +1 -1
  60. package/dist/cjs/resolveQuery.native.js.map +1 -1
  61. package/dist/cjs/run.native.js.map +1 -1
  62. package/dist/cjs/serverWhere.native.js.map +1 -1
  63. package/dist/cjs/serverWhere.test.native.js.map +1 -1
  64. package/dist/cjs/state.native.js.map +1 -1
  65. package/dist/cjs/types.native.js.map +1 -1
  66. package/dist/cjs/usePermission.test.native.js.map +1 -1
  67. package/dist/cjs/vite-plugin.native.js.map +1 -1
  68. package/dist/cjs/where.native.js.map +1 -1
  69. package/dist/cjs/zeroRunner.native.js.map +1 -1
  70. package/dist/cjs/zql.native.js.map +1 -1
  71. package/dist/esm/createZeroClient.authData.test.mjs +68 -0
  72. package/dist/esm/createZeroClient.authData.test.mjs.map +1 -0
  73. package/dist/esm/createZeroClient.authData.test.native.js +70 -0
  74. package/dist/esm/createZeroClient.authData.test.native.js.map +1 -0
  75. package/dist/esm/createZeroClient.mjs +42 -27
  76. package/dist/esm/createZeroClient.mjs.map +1 -1
  77. package/dist/esm/createZeroClient.native.js +48 -27
  78. package/dist/esm/createZeroClient.native.js.map +1 -1
  79. package/dist/esm/createZeroServer.mjs.map +1 -1
  80. package/dist/esm/generate.mjs +41 -0
  81. package/dist/esm/generate.mjs.map +1 -1
  82. package/dist/esm/generate.native.js +63 -0
  83. package/dist/esm/generate.native.js.map +1 -1
  84. package/dist/esm/helpers/recoverZeroClient.mjs +74 -0
  85. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -0
  86. package/dist/esm/helpers/recoverZeroClient.native.js +100 -0
  87. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -0
  88. package/dist/esm/helpers/recoverZeroClient.test.mjs +202 -0
  89. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -0
  90. package/dist/esm/helpers/recoverZeroClient.test.native.js +254 -0
  91. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -0
  92. package/dist/esm/index.js +2 -1
  93. package/dist/esm/index.js.map +1 -1
  94. package/dist/esm/index.mjs +2 -1
  95. package/dist/esm/index.mjs.map +1 -1
  96. package/dist/esm/index.native.js +2 -1
  97. package/dist/esm/index.native.js.map +1 -1
  98. package/dist/esm/multiInstance.test.mjs +4 -3
  99. package/dist/esm/multiInstance.test.mjs.map +1 -1
  100. package/dist/esm/multiInstance.test.native.js +6 -6
  101. package/dist/esm/multiInstance.test.native.js.map +1 -1
  102. package/package.json +2 -2
  103. package/src/createZeroClient.authData.test.tsx +73 -0
  104. package/src/createZeroClient.tsx +60 -47
  105. package/src/createZeroServer.ts +2 -2
  106. package/src/generate.ts +62 -0
  107. package/src/helpers/recoverZeroClient.test.ts +172 -0
  108. package/src/helpers/recoverZeroClient.ts +173 -0
  109. package/src/index.ts +5 -0
  110. package/src/multiInstance.test.tsx +5 -3
  111. package/src/multiInstanceNested.test.tsx +1 -1
  112. package/src/types.ts +6 -1
  113. package/types/createZeroClient.authData.test.d.ts +5 -0
  114. package/types/createZeroClient.authData.test.d.ts.map +1 -0
  115. package/types/createZeroClient.d.ts +2 -1
  116. package/types/createZeroClient.d.ts.map +1 -1
  117. package/types/createZeroServer.d.ts +4 -4
  118. package/types/generate.d.ts.map +1 -1
  119. package/types/helpers/recoverZeroClient.d.ts +17 -0
  120. package/types/helpers/recoverZeroClient.d.ts.map +1 -0
  121. package/types/helpers/recoverZeroClient.test.d.ts +2 -0
  122. package/types/helpers/recoverZeroClient.test.d.ts.map +1 -0
  123. package/types/index.d.ts +1 -0
  124. package/types/index.d.ts.map +1 -1
  125. package/types/types.d.ts +6 -0
  126. package/types/types.d.ts.map +1 -1
@@ -0,0 +1,100 @@
1
+ function _type_of(obj) {
2
+ "@swc/helpers - typeof";
3
+
4
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
5
+ }
6
+ var RECOVER_GUARD_MS = 6e4;
7
+ var LOCAL_STORE_LOST = "Expected IndexedDB not found";
8
+ var reloadScheduled = false;
9
+ var pendingDeletes = [];
10
+ function recoveryGuardOpen(reasonKey) {
11
+ try {
12
+ var key = `on-zero-recover-${reasonKey}`;
13
+ var last = Number(window.sessionStorage.getItem(key) || 0);
14
+ if (Date.now() - last < RECOVER_GUARD_MS) return false;
15
+ window.sessionStorage.setItem(key, String(Date.now()));
16
+ } catch (e) {}
17
+ return true;
18
+ }
19
+ function recover(deps, reasonKey, message, dropLocalState) {
20
+ if (typeof window === "undefined") return;
21
+ if (dropLocalState) {
22
+ pendingDeletes.push(Promise.resolve().then(deps.deleteLocalState).catch(function () {}));
23
+ }
24
+ if (reloadScheduled) return;
25
+ if (!recoveryGuardOpen(reasonKey)) {
26
+ console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
27
+ deps.zeroEvents.emit({
28
+ type: "fatal",
29
+ reason: message
30
+ });
31
+ return;
32
+ }
33
+ reloadScheduled = true;
34
+ console.warn(`[on-zero] ${message} \u2014 recovering`);
35
+ deps.zeroEvents.emit({
36
+ type: "recovering",
37
+ reason: message
38
+ });
39
+ var _deps_reload;
40
+ var doReload = (_deps_reload = deps.reload) !== null && _deps_reload !== void 0 ? _deps_reload : function () {
41
+ return window.location.reload();
42
+ };
43
+ Promise.resolve().then(function () {
44
+ return Promise.allSettled(pendingDeletes);
45
+ }).then(function () {
46
+ var _deps_beforeReload;
47
+ return (_deps_beforeReload = deps.beforeReload) === null || _deps_beforeReload === void 0 ? void 0 : _deps_beforeReload.call(deps);
48
+ }).catch(function () {}).finally(doReload);
49
+ }
50
+ function makeZeroRecovery(deps) {
51
+ return {
52
+ onUpdateNeeded(reason) {
53
+ var dropLocalState = reason.type === "SchemaVersionNotSupported";
54
+ recover(deps, reason.type, `update needed (${reason.message || reason.type})`, dropLocalState);
55
+ },
56
+ onClientStateNotFound() {
57
+ recover(deps, "client-state-not-found", "client state not found", true);
58
+ }
59
+ };
60
+ }
61
+ function logToConsole(level, context) {
62
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
63
+ args[_key - 2] = arguments[_key];
64
+ }
65
+ var prefix = context ? Object.entries(context).map(function (param) {
66
+ var [key, value] = param;
67
+ return value === void 0 ? key : `${key}=${value}`;
68
+ }).join(" ") : "";
69
+ var method = level === "debug" ? "debug" : level;
70
+ console[method](...(prefix ? [prefix] : []), ...args);
71
+ }
72
+ function composeRecoveryLogSink(deps, consumerLogSink) {
73
+ var consumerFlush = consumerLogSink === null || consumerLogSink === void 0 ? void 0 : consumerLogSink.flush;
74
+ return {
75
+ log(level, context) {
76
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
77
+ args[_key - 2] = arguments[_key];
78
+ }
79
+ if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
80
+ if (level !== "error") return;
81
+ var text = args.map(function (arg) {
82
+ return typeof arg === "string" ? arg : arg && (typeof arg === "undefined" ? "undefined" : _type_of(arg)) === "object" && "message" in arg ? String(arg.message) : "";
83
+ }).join(" ");
84
+ if (text.includes(LOCAL_STORE_LOST)) {
85
+ recover(deps, "local-store", "local store lost", true);
86
+ }
87
+ },
88
+ // call through the consumer sink so a class-based sink keeps its `this`,
89
+ // rather than handing Zero a detached method reference.
90
+ flush: consumerFlush ? function () {
91
+ return consumerFlush.call(consumerLogSink);
92
+ } : void 0
93
+ };
94
+ }
95
+ function resetRecoveryStateForTests() {
96
+ reloadScheduled = false;
97
+ pendingDeletes.length = 0;
98
+ }
99
+ export { composeRecoveryLogSink, makeZeroRecovery, resetRecoveryStateForTests };
100
+ //# sourceMappingURL=recoverZeroClient.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_type_of","obj","Symbol","constructor","RECOVER_GUARD_MS","LOCAL_STORE_LOST","reloadScheduled","pendingDeletes","recoveryGuardOpen","reasonKey","key","last","Number","window","sessionStorage","getItem","Date","now","setItem","String","e","recover","deps","message","dropLocalState","push","Promise","resolve","then","deleteLocalState","catch","console","error","zeroEvents","emit","type","reason","warn","_deps_reload","doReload","reload","location","allSettled","_deps_beforeReload","beforeReload","call","finally","makeZeroRecovery","onUpdateNeeded","onClientStateNotFound","logToConsole","level","context","_len","arguments","length","args","Array","_key","prefix","Object","entries","map","param","value","join","method","composeRecoveryLogSink","consumerLogSink","consumerFlush","flush","log"],"sources":["../../../src/helpers/recoverZeroClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,202 @@
1
+ import { createEmitter } from "@take-out/helpers";
2
+ import { UpdateNeededReasonType } from "@rocicorp/zero";
3
+ import { beforeEach, describe, expect, test, vi } from "vitest";
4
+ import { composeRecoveryLogSink, makeZeroRecovery, resetRecoveryStateForTests } from "./recoverZeroClient.mjs";
5
+ let emitterSeq = 0;
6
+ function setup() {
7
+ const events = [];
8
+ const zeroEvents = createEmitter(`test-recover-${emitterSeq++}`, null);
9
+ zeroEvents.listen(event => {
10
+ if (event) events.push(event);
11
+ });
12
+ const deleteLocalState = vi.fn(() => Promise.resolve());
13
+ const reload = vi.fn();
14
+ const deps = {
15
+ deleteLocalState,
16
+ zeroEvents,
17
+ reload
18
+ };
19
+ return {
20
+ deps,
21
+ deleteLocalState,
22
+ reload,
23
+ events
24
+ };
25
+ }
26
+ async function flush() {
27
+ await new Promise(resolve => setTimeout(resolve, 0));
28
+ }
29
+ beforeEach(() => {
30
+ window.sessionStorage.clear();
31
+ resetRecoveryStateForTests();
32
+ });
33
+ describe("zero recovery", () => {
34
+ test("SchemaVersionNotSupported drops local state and reloads, emitting recovering", async () => {
35
+ const {
36
+ deps,
37
+ deleteLocalState,
38
+ reload,
39
+ events
40
+ } = setup();
41
+ makeZeroRecovery(deps).onUpdateNeeded({
42
+ type: UpdateNeededReasonType.SchemaVersionNotSupported
43
+ });
44
+ expect(events).toEqual([{
45
+ type: "recovering",
46
+ reason: expect.stringContaining("SchemaVersionNotSupported")
47
+ }]);
48
+ await flush();
49
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
50
+ expect(reload).toHaveBeenCalledTimes(1);
51
+ });
52
+ test("NewClientGroup / VersionNotSupported reload WITHOUT deleting (sibling-tab safe)", async () => {
53
+ const {
54
+ deps,
55
+ deleteLocalState,
56
+ reload
57
+ } = setup();
58
+ const recovery = makeZeroRecovery(deps);
59
+ recovery.onUpdateNeeded({
60
+ type: UpdateNeededReasonType.NewClientGroup
61
+ });
62
+ await flush();
63
+ resetRecoveryStateForTests();
64
+ recovery.onUpdateNeeded({
65
+ type: UpdateNeededReasonType.VersionNotSupported
66
+ });
67
+ await flush();
68
+ expect(deleteLocalState).not.toHaveBeenCalled();
69
+ expect(reload).toHaveBeenCalledTimes(2);
70
+ });
71
+ test("onClientStateNotFound drops local state and reloads", async () => {
72
+ const {
73
+ deps,
74
+ deleteLocalState,
75
+ reload
76
+ } = setup();
77
+ makeZeroRecovery(deps).onClientStateNotFound();
78
+ await flush();
79
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
80
+ expect(reload).toHaveBeenCalledTimes(1);
81
+ });
82
+ test("combined client: every instance deletes its own store, but only ONE reload", async () => {
83
+ const a = setup();
84
+ const b = setup();
85
+ makeZeroRecovery(a.deps).onClientStateNotFound();
86
+ makeZeroRecovery(b.deps).onClientStateNotFound();
87
+ await flush();
88
+ expect(a.deleteLocalState).toHaveBeenCalledTimes(1);
89
+ expect(b.deleteLocalState).toHaveBeenCalledTimes(1);
90
+ expect(a.reload.mock.calls.length + b.reload.mock.calls.length).toBe(1);
91
+ });
92
+ test("a second trigger in the same page-load adds no extra reload or fatal", async () => {
93
+ const {
94
+ deps,
95
+ reload,
96
+ events
97
+ } = setup();
98
+ const recovery = makeZeroRecovery(deps);
99
+ recovery.onClientStateNotFound();
100
+ recovery.onUpdateNeeded({
101
+ type: UpdateNeededReasonType.NewClientGroup
102
+ });
103
+ await flush();
104
+ expect(reload).toHaveBeenCalledTimes(1);
105
+ expect(events.filter(event => event.type === "fatal")).toEqual([]);
106
+ });
107
+ test("after a reload, a re-failing reason emits fatal instead of reloading again", async () => {
108
+ const {
109
+ deps,
110
+ reload,
111
+ events
112
+ } = setup();
113
+ const recovery = makeZeroRecovery(deps);
114
+ recovery.onClientStateNotFound();
115
+ await flush();
116
+ resetRecoveryStateForTests();
117
+ recovery.onClientStateNotFound();
118
+ await flush();
119
+ expect(reload).toHaveBeenCalledTimes(1);
120
+ expect(events.some(event => event.type === "fatal")).toBe(true);
121
+ });
122
+ test("after a reload, a different reason still recovers", async () => {
123
+ const {
124
+ deps,
125
+ reload
126
+ } = setup();
127
+ const recovery = makeZeroRecovery(deps);
128
+ recovery.onClientStateNotFound();
129
+ await flush();
130
+ resetRecoveryStateForTests();
131
+ recovery.onUpdateNeeded({
132
+ type: UpdateNeededReasonType.SchemaVersionNotSupported
133
+ });
134
+ await flush();
135
+ expect(reload).toHaveBeenCalledTimes(2);
136
+ });
137
+ test("logSink recovers on local-store-lost and forwards to the consumer sink", async () => {
138
+ const {
139
+ deps,
140
+ deleteLocalState,
141
+ reload
142
+ } = setup();
143
+ const consumer = {
144
+ log: vi.fn()
145
+ };
146
+ const sink = composeRecoveryLogSink(deps, consumer);
147
+ sink.log("error", void 0, "Error during persist: Expected IndexedDB not found");
148
+ expect(consumer.log).toHaveBeenCalledTimes(1);
149
+ await flush();
150
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
151
+ expect(reload).toHaveBeenCalledTimes(1);
152
+ });
153
+ test("logSink with no consumer preserves console output and still watches", async () => {
154
+ const {
155
+ deps,
156
+ deleteLocalState,
157
+ reload
158
+ } = setup();
159
+ const infoSpy = vi.spyOn(console, "info").mockImplementation(() => {});
160
+ const sink = composeRecoveryLogSink(deps);
161
+ sink.log("info", {
162
+ worker: "sync"
163
+ }, "connected");
164
+ expect(infoSpy).toHaveBeenCalledWith("worker=sync", "connected");
165
+ infoSpy.mockRestore();
166
+ sink.log("error", void 0, "Expected IndexedDB not found");
167
+ await flush();
168
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
169
+ expect(reload).toHaveBeenCalledTimes(1);
170
+ });
171
+ test("logSink flush calls through the consumer sink (preserves its this)", async () => {
172
+ const {
173
+ deps
174
+ } = setup();
175
+ class ClassSink {
176
+ flushed = false;
177
+ log() {}
178
+ flush() {
179
+ this.flushed = true;
180
+ return Promise.resolve();
181
+ }
182
+ }
183
+ const consumer = new ClassSink();
184
+ const sink = composeRecoveryLogSink(deps, consumer);
185
+ await sink.flush?.();
186
+ expect(consumer.flushed).toBe(true);
187
+ });
188
+ test("logSink ignores non-error level and non-matching messages", async () => {
189
+ const {
190
+ deps,
191
+ deleteLocalState,
192
+ reload
193
+ } = setup();
194
+ const sink = composeRecoveryLogSink(deps);
195
+ sink.log("info", void 0, "Expected IndexedDB not found");
196
+ sink.log("error", void 0, "some unrelated error");
197
+ await flush();
198
+ expect(deleteLocalState).not.toHaveBeenCalled();
199
+ expect(reload).not.toHaveBeenCalled();
200
+ });
201
+ });
202
+ //# sourceMappingURL=recoverZeroClient.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createEmitter","UpdateNeededReasonType","beforeEach","describe","expect","test","vi","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","emitterSeq","setup","events","zeroEvents","listen","event","push","deleteLocalState","fn","Promise","resolve","reload","deps","flush","setTimeout","window","sessionStorage","clear","onUpdateNeeded","type","SchemaVersionNotSupported","toEqual","reason","stringContaining","toHaveBeenCalledTimes","recovery","NewClientGroup","VersionNotSupported","not","toHaveBeenCalled","onClientStateNotFound","a","b","mock","calls","length","toBe","filter","some","consumer","log","sink","infoSpy","spyOn","console","mockImplementation","worker","toHaveBeenCalledWith","mockRestore","ClassSink","flushed"],"sources":["../../../src/helpers/recoverZeroClient.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,254 @@
1
+ import { createEmitter } from "@take-out/helpers";
2
+ import { UpdateNeededReasonType } from "@rocicorp/zero";
3
+ import { beforeEach, describe, expect, test, vi } from "vitest";
4
+ import { composeRecoveryLogSink, makeZeroRecovery, resetRecoveryStateForTests } from "./recoverZeroClient.native.js";
5
+ function _class_call_check(instance, Constructor) {
6
+ if (!(instance instanceof Constructor)) {
7
+ throw new TypeError("Cannot call a class as a function");
8
+ }
9
+ }
10
+ function _defineProperties(target, props) {
11
+ for (var i = 0; i < props.length; i++) {
12
+ var descriptor = props[i];
13
+ descriptor.enumerable = descriptor.enumerable || false;
14
+ descriptor.configurable = true;
15
+ if ("value" in descriptor) descriptor.writable = true;
16
+ Object.defineProperty(target, descriptor.key, descriptor);
17
+ }
18
+ }
19
+ function _create_class(Constructor, protoProps, staticProps) {
20
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
21
+ if (staticProps) _defineProperties(Constructor, staticProps);
22
+ return Constructor;
23
+ }
24
+ function _define_property(obj, key, value) {
25
+ if (key in obj) {
26
+ Object.defineProperty(obj, key, {
27
+ value,
28
+ enumerable: true,
29
+ configurable: true,
30
+ writable: true
31
+ });
32
+ } else {
33
+ obj[key] = value;
34
+ }
35
+ return obj;
36
+ }
37
+ var emitterSeq = 0;
38
+ function setup() {
39
+ var events = [];
40
+ var zeroEvents = createEmitter(`test-recover-${emitterSeq++}`, null);
41
+ zeroEvents.listen(function (event) {
42
+ if (event) events.push(event);
43
+ });
44
+ var deleteLocalState = vi.fn(function () {
45
+ return Promise.resolve();
46
+ });
47
+ var reload = vi.fn();
48
+ var deps = {
49
+ deleteLocalState,
50
+ zeroEvents,
51
+ reload
52
+ };
53
+ return {
54
+ deps,
55
+ deleteLocalState,
56
+ reload,
57
+ events
58
+ };
59
+ }
60
+ async function flush() {
61
+ await new Promise(function (resolve) {
62
+ return setTimeout(resolve, 0);
63
+ });
64
+ }
65
+ beforeEach(function () {
66
+ window.sessionStorage.clear();
67
+ resetRecoveryStateForTests();
68
+ });
69
+ describe("zero recovery", function () {
70
+ test("SchemaVersionNotSupported drops local state and reloads, emitting recovering", async function () {
71
+ var {
72
+ deps,
73
+ deleteLocalState,
74
+ reload,
75
+ events
76
+ } = setup();
77
+ makeZeroRecovery(deps).onUpdateNeeded({
78
+ type: UpdateNeededReasonType.SchemaVersionNotSupported
79
+ });
80
+ expect(events).toEqual([{
81
+ type: "recovering",
82
+ reason: expect.stringContaining("SchemaVersionNotSupported")
83
+ }]);
84
+ await flush();
85
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
86
+ expect(reload).toHaveBeenCalledTimes(1);
87
+ });
88
+ test("NewClientGroup / VersionNotSupported reload WITHOUT deleting (sibling-tab safe)", async function () {
89
+ var {
90
+ deps,
91
+ deleteLocalState,
92
+ reload
93
+ } = setup();
94
+ var recovery = makeZeroRecovery(deps);
95
+ recovery.onUpdateNeeded({
96
+ type: UpdateNeededReasonType.NewClientGroup
97
+ });
98
+ await flush();
99
+ resetRecoveryStateForTests();
100
+ recovery.onUpdateNeeded({
101
+ type: UpdateNeededReasonType.VersionNotSupported
102
+ });
103
+ await flush();
104
+ expect(deleteLocalState).not.toHaveBeenCalled();
105
+ expect(reload).toHaveBeenCalledTimes(2);
106
+ });
107
+ test("onClientStateNotFound drops local state and reloads", async function () {
108
+ var {
109
+ deps,
110
+ deleteLocalState,
111
+ reload
112
+ } = setup();
113
+ makeZeroRecovery(deps).onClientStateNotFound();
114
+ await flush();
115
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
116
+ expect(reload).toHaveBeenCalledTimes(1);
117
+ });
118
+ test("combined client: every instance deletes its own store, but only ONE reload", async function () {
119
+ var a = setup();
120
+ var b = setup();
121
+ makeZeroRecovery(a.deps).onClientStateNotFound();
122
+ makeZeroRecovery(b.deps).onClientStateNotFound();
123
+ await flush();
124
+ expect(a.deleteLocalState).toHaveBeenCalledTimes(1);
125
+ expect(b.deleteLocalState).toHaveBeenCalledTimes(1);
126
+ expect(a.reload.mock.calls.length + b.reload.mock.calls.length).toBe(1);
127
+ });
128
+ test("a second trigger in the same page-load adds no extra reload or fatal", async function () {
129
+ var {
130
+ deps,
131
+ reload,
132
+ events
133
+ } = setup();
134
+ var recovery = makeZeroRecovery(deps);
135
+ recovery.onClientStateNotFound();
136
+ recovery.onUpdateNeeded({
137
+ type: UpdateNeededReasonType.NewClientGroup
138
+ });
139
+ await flush();
140
+ expect(reload).toHaveBeenCalledTimes(1);
141
+ expect(events.filter(function (event) {
142
+ return event.type === "fatal";
143
+ })).toEqual([]);
144
+ });
145
+ test("after a reload, a re-failing reason emits fatal instead of reloading again", async function () {
146
+ var {
147
+ deps,
148
+ reload,
149
+ events
150
+ } = setup();
151
+ var recovery = makeZeroRecovery(deps);
152
+ recovery.onClientStateNotFound();
153
+ await flush();
154
+ resetRecoveryStateForTests();
155
+ recovery.onClientStateNotFound();
156
+ await flush();
157
+ expect(reload).toHaveBeenCalledTimes(1);
158
+ expect(events.some(function (event) {
159
+ return event.type === "fatal";
160
+ })).toBe(true);
161
+ });
162
+ test("after a reload, a different reason still recovers", async function () {
163
+ var {
164
+ deps,
165
+ reload
166
+ } = setup();
167
+ var recovery = makeZeroRecovery(deps);
168
+ recovery.onClientStateNotFound();
169
+ await flush();
170
+ resetRecoveryStateForTests();
171
+ recovery.onUpdateNeeded({
172
+ type: UpdateNeededReasonType.SchemaVersionNotSupported
173
+ });
174
+ await flush();
175
+ expect(reload).toHaveBeenCalledTimes(2);
176
+ });
177
+ test("logSink recovers on local-store-lost and forwards to the consumer sink", async function () {
178
+ var {
179
+ deps,
180
+ deleteLocalState,
181
+ reload
182
+ } = setup();
183
+ var consumer = {
184
+ log: vi.fn()
185
+ };
186
+ var sink = composeRecoveryLogSink(deps, consumer);
187
+ sink.log("error", void 0, "Error during persist: Expected IndexedDB not found");
188
+ expect(consumer.log).toHaveBeenCalledTimes(1);
189
+ await flush();
190
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
191
+ expect(reload).toHaveBeenCalledTimes(1);
192
+ });
193
+ test("logSink with no consumer preserves console output and still watches", async function () {
194
+ var {
195
+ deps,
196
+ deleteLocalState,
197
+ reload
198
+ } = setup();
199
+ var infoSpy = vi.spyOn(console, "info").mockImplementation(function () {});
200
+ var sink = composeRecoveryLogSink(deps);
201
+ sink.log("info", {
202
+ worker: "sync"
203
+ }, "connected");
204
+ expect(infoSpy).toHaveBeenCalledWith("worker=sync", "connected");
205
+ infoSpy.mockRestore();
206
+ sink.log("error", void 0, "Expected IndexedDB not found");
207
+ await flush();
208
+ expect(deleteLocalState).toHaveBeenCalledTimes(1);
209
+ expect(reload).toHaveBeenCalledTimes(1);
210
+ });
211
+ test("logSink flush calls through the consumer sink (preserves its this)", async function () {
212
+ var _sink_flush;
213
+ var {
214
+ deps
215
+ } = setup();
216
+ var ClassSink = /* @__PURE__ */function () {
217
+ "use strict";
218
+
219
+ function ClassSink2() {
220
+ _class_call_check(this, ClassSink2);
221
+ _define_property(this, "flushed", false);
222
+ }
223
+ _create_class(ClassSink2, [{
224
+ key: "log",
225
+ value: function log() {}
226
+ }, {
227
+ key: "flush",
228
+ value: function flush2() {
229
+ this.flushed = true;
230
+ return Promise.resolve();
231
+ }
232
+ }]);
233
+ return ClassSink2;
234
+ }();
235
+ var consumer = new ClassSink();
236
+ var sink = composeRecoveryLogSink(deps, consumer);
237
+ await ((_sink_flush = sink.flush) === null || _sink_flush === void 0 ? void 0 : _sink_flush.call(sink));
238
+ expect(consumer.flushed).toBe(true);
239
+ });
240
+ test("logSink ignores non-error level and non-matching messages", async function () {
241
+ var {
242
+ deps,
243
+ deleteLocalState,
244
+ reload
245
+ } = setup();
246
+ var sink = composeRecoveryLogSink(deps);
247
+ sink.log("info", void 0, "Expected IndexedDB not found");
248
+ sink.log("error", void 0, "some unrelated error");
249
+ await flush();
250
+ expect(deleteLocalState).not.toHaveBeenCalled();
251
+ expect(reload).not.toHaveBeenCalled();
252
+ });
253
+ });
254
+ //# sourceMappingURL=recoverZeroClient.test.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createEmitter","UpdateNeededReasonType","beforeEach","describe","expect","test","vi","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","_class_call_check","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_create_class","protoProps","staticProps","prototype","_define_property","obj","value","emitterSeq","setup","events","zeroEvents","listen","event","push","deleteLocalState","fn","Promise","resolve","reload","deps","flush","setTimeout","window","sessionStorage","clear","onUpdateNeeded","type","SchemaVersionNotSupported","toEqual","reason","stringContaining","toHaveBeenCalledTimes","recovery","NewClientGroup","VersionNotSupported","not","toHaveBeenCalled","onClientStateNotFound","a","b","mock","calls","toBe","filter","some"],"sources":["../../../src/helpers/recoverZeroClient.test.ts"],"sourcesContent":[null],"mappings":"AACA,SAASA,aAAA,QAAqB;AAC9B,SAASC,sBAAA,QAA8B;AACvC,SAASC,UAAA,EAAYC,QAAA,EAAUC,MAAA,EAAQC,IAAA,EAAMC,EAAA,QAAU;AAEvD,SAAAC,sBAAA,EAAAC,gBAAA,EAAAC,0BAAA;AAAA,SACEC,kBAAAC,QAAA,EAAAC,WAAA;EACA,MAAAD,QAAA,YAAAC,WAAA;IACA,UAAAC,SAAA;EAAA;AAMF;AAEA,SAASC,iBAAQA,CAAAC,MAAA,EAAAC,KAAA;EACf,SAAMC,CAAA,MAAuBA,CAAA,GAAAD,KAAA,CAAAE,MAAA,EAAAD,CAAA;IAC7B,IAAME,UAAA,GAAaH,KAAA,CAAAC,CAAA;IACnBE,UAAW,CAAAC,UAAQ,GAAAD,UAAU,CAAAC,UAAA;IAC3BD,UAAW,CAAAE,YAAY,OAAK;IAC7B,eAAAF,UAAA,EAAAA,UAAA,CAAAG,QAAA;IACDC,MAAM,CAAAC,cAAA,CAAAT,MAAsB,EAAGI,UAAM,CAAAM,GAAQ,EAAAN,UAAS;EACtD;AACA;AACA,SAAOO,aAAQA,CAAAd,WAAA,EAAkBe,UAAQ,EAAAC,WAAO;EAClD,IAAAD,UAAA,EAAAb,iBAAA,CAAAF,WAAA,CAAAiB,SAAA,EAAAF,UAAA;EAIA,IAAAC,WAAe,EAAAd,iBAAQ,CAAAF,WAAA,EAAAgB,WAAA;EACrB,OAAMhB,WAAY;AACpB;AAEA,SAAAkB,gBAAiBA,CAAAC,GAAA,EAAAN,GAAA,EAAAO,KAAA;EACf,IAAAP,GAAO,IAAAM,GAAA;IACPR,MAAA,CAAAC,cAAA,CAAAO,GAA2B,EAAAN,GAAA;MAC5BO,KAAA;MAEDZ,UAAS;MACPC,YAAK;MACHC,QAAQ;IACR;EAAsC,OACpC;IACFS,GAAC,CAAAN,GAAA,IAAAO,KAAA;EACD;EAAuB,OACrBD,GAAA;AAAA;AACQ,IAAAE,UACN,GAAQ;AAAmD,SAC7DC,MAAA;EAAA,IACDC,MAAA;EACD,IAAAC,UAAY,GAAApC,aAAA,iBAAAiC,UAAA;EACZG,UAAO,CAAAC,MAAA,WAAkBC,KAAA;IACzB,IAAAA,KAAO,EAAAH,MAAQ,CAAAI,IAAA,CAAAD,KAAA;EACjB,CAAC;EAED,IAAAE,gBAAK,GAAAlC,EAAA,CAAAmC,EAAA;IACH,OAAMC,OAAQ,CAAAC,OAAA;EACd;EACA,IAAAC,MAAA,GAAStC,EAAA,CAAAmC,EAAA;EACT,IAAAI,IAAM;IACNL,gBAAA;IACAJ,UAAS;IACTQ;EACA;EACA;IACDC,IAAA;IAEDL,gBAAK;IACHI,MAAM;IACNT;EACA;AACA;AACA,eAAOW,KAAQA,CAAA;EACjB,MAAC,IAAAJ,OAAA,WAAAC,OAAA;IAED,OAAKI,UAAA,CAAAJ,OAAA;EAGH;AACA;AACAzC,UAAA,aAAiB;EACjB8C,MAAA,CAAAC,cAAmB,CAAAC,KAAM;EACzBzC,0BAAY;AACZ;AACAN,QAAA,gBAAS,cAAkB;EAC3BE,IAAA,+EAAsE;IACvE;MAAAwC,IAAA;MAAAL,gBAAA;MAAAI,MAAA;MAAAT;IAAA,IAAAD,KAAA;IAED1B,gBAAK,CAAAqC,IAAA,EAAAM,cAAA;MACHC,IAAM,EAAEnD,sBAAqB,CAAAoD;IAC7B;IACAjD,MAAA,CAAA+B,MAAS,EAAAmB,OAAA,EACT;MACAF,IAAM,cAAM;MACZG,MAAO,EAAAnD,MAAQ,CAAAoD,gBAAA,4BAAuB;IACtC,EACD;IAED,MAAKV,KAAA;IACH1C,MAAM,CAAAoC,gBAAgB,EAAAiB,qBAAiB;IACvCrD,MAAM,CAAAwC,MAAA,EAAAa,qBAA4B,EAAI;EACtC;EACApD,IAAA,kFAAY;IACZ;MAAAwC,IAAA;MAAAL,gBAA2B;MAAAI;IAAA,IAAAV,KAAA;IAC3B,IAAAwB,QAAS,GAAAlD,gBAAsB,CAAAqC,IAAA;IAC/Ba,QAAM,CAAAP,cAAM;MACZC,IAAA,EAAOnD,sBAAQ,CAAA0D;IACf;IACD,MAAAb,KAAA;IAEDrC,0BAAK;IACHiD,QAAQ,CAAAP,cAAa;MACrBC,IAAM,EAAAnD,sBAAW,CAAA2D;IACjB;IACA,MAAMd,KAAA,CAAM;IACZ1C,MAAA,CAAAoC,gBAAA,EAAAqB,GAA2B,CAAAC,gBAAA;IAC3B1D,MAAA,CAAAwC,MAAS,EAAAa,qBAAuB;EAChC;EACApD,IAAA,sDAAsC;IACvC;MAAAwC,IAAA;MAAAL,gBAAA;MAAAI;IAAA,IAAAV,KAAA;IAED1B,gBAAK,CAAAqC,IAAA,EAAAkB,qBAAA;IACH,MAAMjB,KAAE;IACR1C,MAAM,CAAAoC,gBAAa,CAAK,CAAAiB,qBAAQ;IAChCrD,MAAM,CAAAwC,MAAO,EAAAa,qBAAuB;EACpC;EACApD,IAAA,6EAA4C;IAC5C,IAAA2D,CAAA,GAAM9B,KAAM;IACZ,IAAA+B,CAAA,GAAO/B,KAAA;IACP1B,gBAAe,CAAAwD,CAAA,CAAAnB,IAAA,EAAAkB,qBAAuB;IACvCvD,gBAAA,CAAAyD,CAAA,CAAApB,IAAA,EAAAkB,qBAAA;IAED,MAAKjB,KAAA;IACH1C,MAAM,CAAA4D,CAAE,CAAAxB,gBAAM,EAAAiB,qBAA6B,CAAM;IACjDrD,MAAM,CAAA6D,CAAA,CAAAzB,gBAAmB,EAAAiB,qBAAiB;IAA0BrD,MAAC,CAAA4D,CAAA,CAAApB,MAAA,CAAAsB,IAAA,CAAAC,KAAA,CAAAjD,MAAA,GAAA+C,CAAA,CAAArB,MAAA,CAAAsB,IAAA,CAAAC,KAAA,CAAAjD,MAAA,EAAAkD,IAAA;EACrE;EACA/D,IAAA,uEAAgD;IAChD;MAAAwC,IAAO;MAAAD,MAAS;MAAAT;IAAA,IAAAD,KAAA,CAAqB;IACrC,IAAAwB,QAAQ,GAAAlD,gBAAY,CAAAqC,IAAA;IACpBa,QAAK,CAAIK,qBAAoB;IAC7BL,QAAM,CAAAP,cAAM;MACZC,IAAA,EAAOnD,sBAAkB,CAAA0D;IACzB;IACD,MAAAb,KAAA;IAED1C,MAAK,CAAAwC,MAAA,EAAAa,qBAAA;IACHrD,MAAM,CAAA+B,MAAO,CAAAkC,MAAI,WAAM/B,KAAA;MACvB,OAAMA,KAAA,CAAAc,IAAU;IAAA,EACd,EAAAE,OAAA,CAAU;EAAA;EACEjD,IAAC;IAAA,IACb;MAAAwC,IAAuB;MAAAD,MAAA;MAAAT;IAAA,IAAAD,KAAA;IACrB,IAAAwB,QAAK,GAAAlD,gBAAU,CAAAqC,IAAA;IACfa,QAAA,CAAAK,qBAAuB;IAAA,MACzBjB,KAAA;IACFrC,0BAAA;IACAiD,QAAM,CAAAK,qBAAe,CAAU;IAC/B,MAAMjB,KAAA,EAAO;IACb1C,MAAM,CAAAwC,MAAK,EAAAa,qBAAQ;IACnBrD,MAAA,CAAO+B,MAAA,CAAAmC,IAAS,WAAShC,KAAK,EAAI;MACnC,OAAAA,KAAA,CAAAc,IAAA;IAED,GAAK,CAAAgB,IAAA;EACH;EACA/D,IAAA,oDAAwC;IACxC;MAAKwC,IAAI;MAAAD;IAAQ,IAAAV,KAAW;IAC5B,IAAAwB,QAAS,GAAAlD,gBAAoB,CAAAqC,IAAA;IAC7Ba,QAAM,CAAAK,qBAAM;IACZ,MAAAjB,KAAO;IACPrC,0BAAmB;IACpBiD,QAAA,CAAAP,cAAA;MACFC,IAAA,EAAAnD,sBAAA,CAAAoD","ignoreList":[]}
package/dist/esm/index.js CHANGED
@@ -21,5 +21,6 @@ export * from "./zql.mjs";
21
21
  import { defineQuery, defineQueries } from "@rocicorp/zero";
22
22
  import { clearZeroClientData } from "./helpers/clearZeroClientData.mjs";
23
23
  import { showZeroClientErrorOnce, resetShownZeroClientError } from "./helpers/showZeroClientError.mjs";
24
- export { clearZeroClientData, defineQueries, defineQuery, ensureAuth, getAuth, resetShownZeroClientError, setAuthData, setEnvironment, setRunner, showZeroClientErrorOnce };
24
+ import { makeZeroRecovery, composeRecoveryLogSink } from "./helpers/recoverZeroClient.mjs";
25
+ export { clearZeroClientData, composeRecoveryLogSink, defineQueries, defineQuery, ensureAuth, getAuth, makeZeroRecovery, resetShownZeroClientError, setAuthData, setEnvironment, setRunner, showZeroClientErrorOnce };
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["ensureAuth","getAuth","setAuthData","setEnvironment","setRunner","defineQuery","defineQueries","clearZeroClientData","showZeroClientErrorOnce","resetShownZeroClientError"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASA,UAAA,EAAYC,OAAA,QAAe;AACpC,SAASC,WAAA,EAAaC,cAAA,QAAsB;AAE5C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,SAAA,QAAkC;AAC3C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,WAAA,EAAaC,aAAA,QAAqB;AAQ3C,SACEC,mBAAA,QAEK;AACP,SACEC,uBAAA,EACAC,yBAAA,QAGK","ignoreList":[]}
1
+ {"version":3,"names":["ensureAuth","getAuth","setAuthData","setEnvironment","setRunner","defineQuery","defineQueries","clearZeroClientData","showZeroClientErrorOnce","resetShownZeroClientError","makeZeroRecovery","composeRecoveryLogSink"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASA,UAAA,EAAYC,OAAA,QAAe;AACpC,SAASC,WAAA,EAAaC,cAAA,QAAsB;AAE5C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,SAAA,QAAkC;AAC3C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,WAAA,EAAaC,aAAA,QAAqB;AAQ3C,SACEC,mBAAA,QAEK;AACP,SACEC,uBAAA,EACAC,yBAAA,QAGK;AACP,SACEC,gBAAA,EACAC,sBAAA,QAEK","ignoreList":[]}
@@ -21,5 +21,6 @@ export * from "./zql.mjs";
21
21
  import { defineQuery, defineQueries } from "@rocicorp/zero";
22
22
  import { clearZeroClientData } from "./helpers/clearZeroClientData.mjs";
23
23
  import { showZeroClientErrorOnce, resetShownZeroClientError } from "./helpers/showZeroClientError.mjs";
24
- export { clearZeroClientData, defineQueries, defineQuery, ensureAuth, getAuth, resetShownZeroClientError, setAuthData, setEnvironment, setRunner, showZeroClientErrorOnce };
24
+ import { makeZeroRecovery, composeRecoveryLogSink } from "./helpers/recoverZeroClient.mjs";
25
+ export { clearZeroClientData, composeRecoveryLogSink, defineQueries, defineQuery, ensureAuth, getAuth, makeZeroRecovery, resetShownZeroClientError, setAuthData, setEnvironment, setRunner, showZeroClientErrorOnce };
25
26
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"names":["ensureAuth","getAuth","setAuthData","setEnvironment","setRunner","defineQuery","defineQueries","clearZeroClientData","showZeroClientErrorOnce","resetShownZeroClientError"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASA,UAAA,EAAYC,OAAA,QAAe;AACpC,SAASC,WAAA,EAAaC,cAAA,QAAsB;AAE5C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,SAAA,QAAkC;AAC3C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,WAAA,EAAaC,aAAA,QAAqB;AAQ3C,SACEC,mBAAA,QAEK;AACP,SACEC,uBAAA,EACAC,yBAAA,QAGK","ignoreList":[]}
1
+ {"version":3,"names":["ensureAuth","getAuth","setAuthData","setEnvironment","setRunner","defineQuery","defineQueries","clearZeroClientData","showZeroClientErrorOnce","resetShownZeroClientError","makeZeroRecovery","composeRecoveryLogSink"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASA,UAAA,EAAYC,OAAA,QAAe;AACpC,SAASC,WAAA,EAAaC,cAAA,QAAsB;AAE5C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,SAAA,QAAkC;AAC3C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,WAAA,EAAaC,aAAA,QAAqB;AAQ3C,SACEC,mBAAA,QAEK;AACP,SACEC,uBAAA,EACAC,yBAAA,QAGK;AACP,SACEC,gBAAA,EACAC,sBAAA,QAEK","ignoreList":[]}
@@ -21,5 +21,6 @@ export * from "./zql.native.js";
21
21
  import { defineQuery, defineQueries } from "@rocicorp/zero";
22
22
  import { clearZeroClientData } from "./helpers/clearZeroClientData.native.js";
23
23
  import { showZeroClientErrorOnce, resetShownZeroClientError } from "./helpers/showZeroClientError.native.js";
24
- export { clearZeroClientData, defineQueries, defineQuery, ensureAuth, getAuth, resetShownZeroClientError, setAuthData, setEnvironment, setRunner, showZeroClientErrorOnce };
24
+ import { makeZeroRecovery, composeRecoveryLogSink } from "./helpers/recoverZeroClient.native.js";
25
+ export { clearZeroClientData, composeRecoveryLogSink, defineQueries, defineQuery, ensureAuth, getAuth, makeZeroRecovery, resetShownZeroClientError, setAuthData, setEnvironment, setRunner, showZeroClientErrorOnce };
25
26
  //# sourceMappingURL=index.native.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["ensureAuth","getAuth","setAuthData","setEnvironment","setRunner","defineQuery","defineQueries","clearZeroClientData","showZeroClientErrorOnce","resetShownZeroClientError"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASA,UAAA,EAAYC,OAAA,QAAe;AACpC,SAASC,WAAA,EAAaC,cAAA,QAAsB;AAE5C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,SAAA,QAAkC;AAC3C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,WAAA,EAAaC,aAAA,QAAqB;AAQ3C,SAAAC,mBAAA;AAAA,SACEC,uBAAA,EAAAC,yBAAA;AAAA,SAGFF,mBAAA,EACED,aAAA,EACAD,WAAA,EAAAL,UAGK,E","ignoreList":[]}
1
+ {"version":3,"names":["ensureAuth","getAuth","setAuthData","setEnvironment","setRunner","defineQuery","defineQueries","clearZeroClientData","showZeroClientErrorOnce","resetShownZeroClientError","makeZeroRecovery","composeRecoveryLogSink"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASA,UAAA,EAAYC,OAAA,QAAe;AACpC,SAASC,WAAA,EAAaC,cAAA,QAAsB;AAE5C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,SAAA,QAAkC;AAC3C,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAASC,WAAA,EAAaC,aAAA,QAAqB;AAQ3C,SAAAC,mBAAA;AAAA,SACEC,uBAAA,EAAAC,yBAAA;AAAA,SAEKC,gBAAA,EAAAC,sBAAA;AACP,SACEJ,mBAAA,EACAI,sBAAA,EAAAL,aAGK,EACPD,WAAA,EACEL,UAAA,EACAC,OAAA,EAAAS,gBAEK,E","ignoreList":[]}
@@ -315,9 +315,10 @@ describe("combineZeroClients facade", () => {
315
315
  type: "error",
316
316
  message: "from-b"
317
317
  });
318
- expect(seen.map(event => event?.message)).toEqual(["from-a", "from-b"]);
319
- expect(a.zeroEvents.value?.message).toBe("from-a");
320
- expect(b.zeroEvents.value?.message).toBe("from-b");
318
+ const messageOf = event => event?.type === "error" ? event.message : void 0;
319
+ expect(seen.map(messageOf)).toEqual(["from-a", "from-b"]);
320
+ expect(messageOf(a.zeroEvents.value)).toBe("from-a");
321
+ expect(messageOf(b.zeroEvents.value)).toBe("from-b");
321
322
  });
322
323
  });
323
324
  //# sourceMappingURL=multiInstance.test.mjs.map