on-zero 0.6.2 → 0.6.4

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 (82) hide show
  1. package/dist/cjs/createZeroClient.cjs +91 -12
  2. package/dist/cjs/createZeroClient.connection.test.cjs +163 -0
  3. package/dist/cjs/createZeroClient.connection.test.native.js +242 -0
  4. package/dist/cjs/createZeroClient.connection.test.native.js.map +1 -0
  5. package/dist/cjs/createZeroClient.native.js +99 -12
  6. package/dist/cjs/createZeroClient.native.js.map +1 -1
  7. package/dist/cjs/createZeroClient.recovery.test.cjs +52 -0
  8. package/dist/cjs/createZeroClient.recovery.test.native.js +52 -0
  9. package/dist/cjs/createZeroClient.recovery.test.native.js.map +1 -1
  10. package/dist/cjs/helpers/recoverZeroClient.cjs +197 -14
  11. package/dist/cjs/helpers/recoverZeroClient.native.js +220 -24
  12. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
  13. package/dist/cjs/helpers/recoverZeroClient.test.cjs +241 -0
  14. package/dist/cjs/helpers/recoverZeroClient.test.native.js +269 -0
  15. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
  16. package/dist/cjs/index.cjs +2 -0
  17. package/dist/cjs/index.native.js +2 -0
  18. package/dist/cjs/index.native.js.map +1 -1
  19. package/dist/cjs/multi.cjs +13 -0
  20. package/dist/cjs/multi.native.js +35 -0
  21. package/dist/cjs/multi.native.js.map +1 -1
  22. package/dist/cjs/multiPartition.test.cjs +42 -0
  23. package/dist/cjs/multiPartition.test.native.js +51 -0
  24. package/dist/cjs/multiPartition.test.native.js.map +1 -0
  25. package/dist/esm/createZeroClient.connection.test.mjs +164 -0
  26. package/dist/esm/createZeroClient.connection.test.mjs.map +1 -0
  27. package/dist/esm/createZeroClient.connection.test.native.js +240 -0
  28. package/dist/esm/createZeroClient.connection.test.native.js.map +1 -0
  29. package/dist/esm/createZeroClient.mjs +92 -13
  30. package/dist/esm/createZeroClient.mjs.map +1 -1
  31. package/dist/esm/createZeroClient.native.js +100 -13
  32. package/dist/esm/createZeroClient.native.js.map +1 -1
  33. package/dist/esm/createZeroClient.recovery.test.mjs +52 -0
  34. package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
  35. package/dist/esm/createZeroClient.recovery.test.native.js +52 -0
  36. package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
  37. package/dist/esm/helpers/recoverZeroClient.mjs +196 -15
  38. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
  39. package/dist/esm/helpers/recoverZeroClient.native.js +219 -25
  40. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
  41. package/dist/esm/helpers/recoverZeroClient.test.mjs +242 -1
  42. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
  43. package/dist/esm/helpers/recoverZeroClient.test.native.js +270 -1
  44. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
  45. package/dist/esm/index.js +2 -2
  46. package/dist/esm/index.js.map +1 -1
  47. package/dist/esm/index.mjs +2 -2
  48. package/dist/esm/index.mjs.map +1 -1
  49. package/dist/esm/index.native.js +2 -2
  50. package/dist/esm/index.native.js.map +1 -1
  51. package/dist/esm/multi.mjs +13 -1
  52. package/dist/esm/multi.mjs.map +1 -1
  53. package/dist/esm/multi.native.js +35 -1
  54. package/dist/esm/multi.native.js.map +1 -1
  55. package/dist/esm/multiPartition.test.mjs +43 -0
  56. package/dist/esm/multiPartition.test.mjs.map +1 -0
  57. package/dist/esm/multiPartition.test.native.js +49 -0
  58. package/dist/esm/multiPartition.test.native.js.map +1 -0
  59. package/lint/ssr-guards.js +164 -0
  60. package/package.json +2 -2
  61. package/readme.md +126 -0
  62. package/src/createZeroClient.connection.test.tsx +162 -0
  63. package/src/createZeroClient.recovery.test.tsx +68 -0
  64. package/src/createZeroClient.tsx +159 -13
  65. package/src/helpers/recoverZeroClient.test.ts +270 -1
  66. package/src/helpers/recoverZeroClient.ts +347 -50
  67. package/src/index.ts +6 -0
  68. package/src/multi.ts +33 -0
  69. package/src/multiPartition.test.ts +38 -0
  70. package/types/createZeroClient.connection.test.d.ts +5 -0
  71. package/types/createZeroClient.connection.test.d.ts.map +1 -0
  72. package/types/createZeroClient.d.ts +17 -0
  73. package/types/createZeroClient.d.ts.map +1 -1
  74. package/types/createZeroServer.d.ts +4 -4
  75. package/types/helpers/recoverZeroClient.d.ts +23 -1
  76. package/types/helpers/recoverZeroClient.d.ts.map +1 -1
  77. package/types/index.d.ts +1 -1
  78. package/types/index.d.ts.map +1 -1
  79. package/types/multi.d.ts +1 -0
  80. package/types/multi.d.ts.map +1 -1
  81. package/types/multiPartition.test.d.ts +2 -0
  82. package/types/multiPartition.test.d.ts.map +1 -0
@@ -22,31 +22,85 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
22
22
  }), mod);
23
23
  var recoverZeroClient_exports = {};
24
24
  __export(recoverZeroClient_exports, {
25
+ classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
25
26
  composeRecoveryLogSink: () => composeRecoveryLogSink,
27
+ isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
26
28
  makeZeroRecovery: () => makeZeroRecovery,
27
29
  resetRecoveryStateForTests: () => resetRecoveryStateForTests
28
30
  });
29
31
  module.exports = __toCommonJS(recoverZeroClient_exports);
30
32
  const RECOVER_GUARD_MS = 6e4;
33
+ const RELOAD_LATCH_TIMEOUT_MS = 15e3;
31
34
  const LOCAL_STORE_LOST = "Expected IndexedDB not found";
35
+ const SQLITE_ERROR_NAME = "SqliteError";
36
+ const SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
37
+ const STORE_CLOSED = "Store is closed";
38
+ const STORE_CLOSED_REPEAT_MIN_MS = 2e3;
39
+ const STORE_CLOSED_REPEAT_MAX_MS = 6e4;
32
40
  let reloadScheduled = false;
41
+ let reloadInProgress = false;
42
+ let reloadLatchTimer;
33
43
  const pendingDeletes = [];
34
- function recoveryGuardOpen(reasonKey) {
44
+ const inMemoryGuard = /* @__PURE__ */new Map();
45
+ function defaultGuardStorage() {
35
46
  try {
36
- const key = `on-zero-recover-${reasonKey}`;
37
- const last = Number(window.sessionStorage.getItem(key) || 0);
38
- if (Date.now() - last < RECOVER_GUARD_MS) return false;
39
- window.sessionStorage.setItem(key, String(Date.now()));
40
- } catch {}
47
+ if (typeof window === "undefined" || !window.sessionStorage) return void 0;
48
+ return window.sessionStorage;
49
+ } catch {
50
+ return void 0;
51
+ }
52
+ }
53
+ function recoveryGuardOpen(reasonKey, guardStorage) {
54
+ const key = `on-zero-recover-${reasonKey}`;
55
+ const now = Date.now();
56
+ const memLast = inMemoryGuard.get(key) ?? 0;
57
+ if (memLast > 0 && now - memLast < RECOVER_GUARD_MS) return false;
58
+ const storage = guardStorage ?? defaultGuardStorage();
59
+ if (storage) {
60
+ try {
61
+ const rawLast = storage.getItem(key);
62
+ const last = rawLast ? Number(rawLast) : 0;
63
+ if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
64
+ storage.setItem(key, String(now));
65
+ } catch {}
66
+ }
67
+ inMemoryGuard.set(key, now);
41
68
  return true;
42
69
  }
70
+ let lastStoreClosedAtMs = 0;
71
+ function armReloadLatchTimeout() {
72
+ if (typeof setTimeout !== "function") return;
73
+ if (reloadLatchTimer) clearTimeout(reloadLatchTimer);
74
+ reloadLatchTimer = setTimeout(() => {
75
+ reloadLatchTimer = void 0;
76
+ reloadScheduled = false;
77
+ }, RELOAD_LATCH_TIMEOUT_MS);
78
+ if (reloadLatchTimer && typeof reloadLatchTimer === "object" && "unref" in reloadLatchTimer) {
79
+ reloadLatchTimer.unref();
80
+ }
81
+ }
82
+ function disarmReloadLatchTimeout() {
83
+ if (reloadLatchTimer) {
84
+ clearTimeout(reloadLatchTimer);
85
+ reloadLatchTimer = void 0;
86
+ }
87
+ }
88
+ function performReload(deps) {
89
+ if (reloadInProgress) return Promise.resolve();
90
+ reloadInProgress = true;
91
+ disarmReloadLatchTimeout();
92
+ const doReload = deps.reload ?? (() => globalThis.location?.reload?.());
93
+ return Promise.resolve().then(() => Promise.allSettled(pendingDeletes.splice(0).map(run => run()))).then(() => deps.beforeReload?.()).catch(() => {}).then(() => {
94
+ doReload();
95
+ });
96
+ }
43
97
  function recover(deps, reasonKey, message, dropLocalState) {
44
98
  if (typeof window === "undefined") return;
45
99
  if (dropLocalState) {
46
- pendingDeletes.push(Promise.resolve().then(deps.deleteLocalState).catch(() => {}));
100
+ pendingDeletes.push(() => Promise.resolve().then(deps.deleteLocalState));
47
101
  }
48
102
  if (reloadScheduled) return;
49
- if (!recoveryGuardOpen(reasonKey)) {
103
+ if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
50
104
  console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
51
105
  deps.zeroEvents.emit({
52
106
  type: "fatal",
@@ -55,13 +109,23 @@ function recover(deps, reasonKey, message, dropLocalState) {
55
109
  return;
56
110
  }
57
111
  reloadScheduled = true;
112
+ armReloadLatchTimeout();
58
113
  console.warn(`[on-zero] ${message} \u2014 recovering`);
59
114
  deps.zeroEvents.emit({
60
115
  type: "recovering",
61
116
  reason: message
62
117
  });
63
- const doReload = deps.reload ?? (() => globalThis.location?.reload?.());
64
- Promise.resolve().then(() => Promise.allSettled(pendingDeletes)).then(() => deps.beforeReload?.()).catch(() => {}).finally(doReload);
118
+ const runReload = () => performReload(deps);
119
+ if (deps.scheduleReload) {
120
+ deps.scheduleReload({
121
+ reason: message,
122
+ reasonKey,
123
+ dropLocalState,
124
+ performReload: runReload
125
+ });
126
+ } else {
127
+ void runReload();
128
+ }
65
129
  }
66
130
  function makeZeroRecovery(deps) {
67
131
  return {
@@ -79,23 +143,142 @@ function logToConsole(level, context, ...args) {
79
143
  const method = level === "debug" ? "debug" : level;
80
144
  console[method](...(prefix ? [prefix] : []), ...args);
81
145
  }
146
+ function logArgText(arg) {
147
+ if (typeof arg === "string") return arg;
148
+ if (arg instanceof Error) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
149
+ if (arg && typeof arg === "object") {
150
+ const message = "message" in arg ? arg.message : void 0;
151
+ const name = "name" in arg ? arg.name : void 0;
152
+ if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
153
+ }
154
+ return "";
155
+ }
156
+ function isBenignStoreClosedLog(text) {
157
+ if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
158
+ if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
159
+ return false;
160
+ }
161
+ function classifyMutationDesync(text) {
162
+ if (text.includes("sent mutation ID") && text.includes("but expected")) {
163
+ return {
164
+ reason: "mutation-desync",
165
+ reasonKey: "mutation-desync",
166
+ message: "mutation id desync"
167
+ };
168
+ }
169
+ if (text.includes("oooMutation") || text.includes("Server reported an out-of-order mutation")) {
170
+ return {
171
+ reason: "mutation-desync",
172
+ reasonKey: "mutation-desync",
173
+ message: "out-of-order mutation"
174
+ };
175
+ }
176
+ if (text.includes("already processed")) {
177
+ return {
178
+ reason: "mutation-desync",
179
+ reasonKey: "mutation-desync",
180
+ message: "mutation already processed"
181
+ };
182
+ }
183
+ if (text.includes("InvalidConnectionRequestLastMutationID")) {
184
+ return {
185
+ reason: "mutation-desync",
186
+ reasonKey: "mutation-desync",
187
+ message: "invalid connection last mutation id"
188
+ };
189
+ }
190
+ if (text.includes("InvalidConnectionRequestBaseCookie")) {
191
+ return {
192
+ reason: "connection-cookie-invalid",
193
+ reasonKey: "connection-cookie-invalid",
194
+ message: "invalid connection base cookie"
195
+ };
196
+ }
197
+ if (text.includes("ClientNotFound") || text.includes("Client not found")) {
198
+ return {
199
+ reason: "client-not-found",
200
+ reasonKey: "client-not-found",
201
+ message: "client not found"
202
+ };
203
+ }
204
+ if (text.includes("connection userID mismatch")) {
205
+ return {
206
+ reason: "connection-userid-mismatch",
207
+ reasonKey: "connection-userid-mismatch",
208
+ message: "connection user id mismatch"
209
+ };
210
+ }
211
+ return void 0;
212
+ }
213
+ function classifyZeroRecoveryLog(level, args, nowMs = Date.now()) {
214
+ if (level !== "error") return void 0;
215
+ const text = args.map(logArgText).join(" ");
216
+ if (text.includes(LOCAL_STORE_LOST)) {
217
+ return {
218
+ reason: "indexeddb-not-found",
219
+ reasonKey: "local-store",
220
+ message: "local store lost",
221
+ dropLocalState: true
222
+ };
223
+ }
224
+ if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
225
+ return {
226
+ reason: "sqlite-statement-finalized",
227
+ reasonKey: "sqlite-statement-finalized",
228
+ message: "sqlite statement finalized",
229
+ dropLocalState: true
230
+ };
231
+ }
232
+ const desync = classifyMutationDesync(text);
233
+ if (desync) {
234
+ return {
235
+ ...desync,
236
+ dropLocalState: true
237
+ };
238
+ }
239
+ if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
240
+ const prevMs = lastStoreClosedAtMs;
241
+ lastStoreClosedAtMs = nowMs;
242
+ if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
243
+ return {
244
+ reason: "store-closed-repeat",
245
+ reasonKey: "store-closed-repeat",
246
+ message: "local store closed repeatedly",
247
+ dropLocalState: true
248
+ };
249
+ }
250
+ }
251
+ return void 0;
252
+ }
82
253
  function composeRecoveryLogSink(deps, consumerLogSink) {
83
254
  const consumerFlush = consumerLogSink?.flush;
84
255
  return {
85
256
  log(level, context, ...args) {
86
257
  if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
87
- if (level !== "error") return;
88
- const text = args.map(arg => typeof arg === "string" ? arg : arg && typeof arg === "object" && "message" in arg ? String(arg.message) : "").join(" ");
89
- if (text.includes(LOCAL_STORE_LOST)) {
90
- recover(deps, "local-store", "local store lost", true);
258
+ const recovery = classifyZeroRecoveryLog(level, args);
259
+ if (!recovery) return;
260
+ if (deps.benignLogFilter) {
261
+ const text = args.map(logArgText).join(" ");
262
+ if (deps.benignLogFilter(text)) return;
91
263
  }
264
+ recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
92
265
  },
93
266
  // call through the consumer sink so a class-based sink keeps its `this`,
94
267
  // rather than handing Zero a detached method reference.
95
268
  flush: consumerFlush ? () => consumerFlush.call(consumerLogSink) : void 0
96
269
  };
97
270
  }
271
+ function isRecoverableZeroStalePokeMessage(message) {
272
+ return message.includes("Server returned unexpected base cookie during sync") || message.includes("Received cookie") && message.includes("is < than last snapshot cookie") && message.includes("ignoring client view");
273
+ }
98
274
  function resetRecoveryStateForTests() {
99
275
  reloadScheduled = false;
276
+ reloadInProgress = false;
277
+ if (reloadLatchTimer) {
278
+ clearTimeout(reloadLatchTimer);
279
+ reloadLatchTimer = void 0;
280
+ }
100
281
  pendingDeletes.length = 0;
282
+ lastStoreClosedAtMs = 0;
283
+ inMemoryGuard.clear();
101
284
  }
@@ -24,36 +24,111 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
24
24
  }), mod);
25
25
  var recoverZeroClient_exports = {};
26
26
  __export(recoverZeroClient_exports, {
27
+ classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
27
28
  composeRecoveryLogSink: () => composeRecoveryLogSink,
29
+ isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
28
30
  makeZeroRecovery: () => makeZeroRecovery,
29
31
  resetRecoveryStateForTests: () => resetRecoveryStateForTests
30
32
  });
31
33
  module.exports = __toCommonJS(recoverZeroClient_exports);
34
+ function _instanceof(left, right) {
35
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
36
+ return !!right[Symbol.hasInstance](left);
37
+ } else {
38
+ return left instanceof right;
39
+ }
40
+ }
32
41
  function _type_of(obj) {
33
42
  "@swc/helpers - typeof";
34
43
 
35
44
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
36
45
  }
37
46
  var RECOVER_GUARD_MS = 6e4;
47
+ var RELOAD_LATCH_TIMEOUT_MS = 15e3;
38
48
  var LOCAL_STORE_LOST = "Expected IndexedDB not found";
49
+ var SQLITE_ERROR_NAME = "SqliteError";
50
+ var SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
51
+ var STORE_CLOSED = "Store is closed";
52
+ var STORE_CLOSED_REPEAT_MIN_MS = 2e3;
53
+ var STORE_CLOSED_REPEAT_MAX_MS = 6e4;
39
54
  var reloadScheduled = false;
55
+ var reloadInProgress = false;
56
+ var reloadLatchTimer;
40
57
  var pendingDeletes = [];
41
- function recoveryGuardOpen(reasonKey) {
58
+ var inMemoryGuard = /* @__PURE__ */new Map();
59
+ function defaultGuardStorage() {
42
60
  try {
43
- var key = `on-zero-recover-${reasonKey}`;
44
- var last = Number(window.sessionStorage.getItem(key) || 0);
45
- if (Date.now() - last < RECOVER_GUARD_MS) return false;
46
- window.sessionStorage.setItem(key, String(Date.now()));
47
- } catch (e) {}
61
+ if (typeof window === "undefined" || !window.sessionStorage) return void 0;
62
+ return window.sessionStorage;
63
+ } catch (e) {
64
+ return void 0;
65
+ }
66
+ }
67
+ function recoveryGuardOpen(reasonKey, guardStorage) {
68
+ var key = `on-zero-recover-${reasonKey}`;
69
+ var now = Date.now();
70
+ var _inMemoryGuard_get;
71
+ var memLast = (_inMemoryGuard_get = inMemoryGuard.get(key)) !== null && _inMemoryGuard_get !== void 0 ? _inMemoryGuard_get : 0;
72
+ if (memLast > 0 && now - memLast < RECOVER_GUARD_MS) return false;
73
+ var storage = guardStorage !== null && guardStorage !== void 0 ? guardStorage : defaultGuardStorage();
74
+ if (storage) {
75
+ try {
76
+ var rawLast = storage.getItem(key);
77
+ var last = rawLast ? Number(rawLast) : 0;
78
+ if (last > 0 && now - last < RECOVER_GUARD_MS) return false;
79
+ storage.setItem(key, String(now));
80
+ } catch (e) {}
81
+ }
82
+ inMemoryGuard.set(key, now);
48
83
  return true;
49
84
  }
85
+ var lastStoreClosedAtMs = 0;
86
+ function armReloadLatchTimeout() {
87
+ if (typeof setTimeout !== "function") return;
88
+ if (reloadLatchTimer) clearTimeout(reloadLatchTimer);
89
+ reloadLatchTimer = setTimeout(function () {
90
+ reloadLatchTimer = void 0;
91
+ reloadScheduled = false;
92
+ }, RELOAD_LATCH_TIMEOUT_MS);
93
+ if (reloadLatchTimer && (typeof reloadLatchTimer === "undefined" ? "undefined" : _type_of(reloadLatchTimer)) === "object" && "unref" in reloadLatchTimer) {
94
+ reloadLatchTimer.unref();
95
+ }
96
+ }
97
+ function disarmReloadLatchTimeout() {
98
+ if (reloadLatchTimer) {
99
+ clearTimeout(reloadLatchTimer);
100
+ reloadLatchTimer = void 0;
101
+ }
102
+ }
103
+ function performReload(deps) {
104
+ if (reloadInProgress) return Promise.resolve();
105
+ reloadInProgress = true;
106
+ disarmReloadLatchTimeout();
107
+ var _deps_reload;
108
+ var doReload = (_deps_reload = deps.reload) !== null && _deps_reload !== void 0 ? _deps_reload : function () {
109
+ var _globalThis_location_reload, _globalThis_location;
110
+ return (_globalThis_location = globalThis.location) === null || _globalThis_location === void 0 ? void 0 : (_globalThis_location_reload = _globalThis_location.reload) === null || _globalThis_location_reload === void 0 ? void 0 : _globalThis_location_reload.call(_globalThis_location);
111
+ };
112
+ return Promise.resolve().then(function () {
113
+ return Promise.allSettled(pendingDeletes.splice(0).map(function (run) {
114
+ return run();
115
+ }));
116
+ }).then(function () {
117
+ var _deps_beforeReload;
118
+ return (_deps_beforeReload = deps.beforeReload) === null || _deps_beforeReload === void 0 ? void 0 : _deps_beforeReload.call(deps);
119
+ }).catch(function () {}).then(function () {
120
+ doReload();
121
+ });
122
+ }
50
123
  function recover(deps, reasonKey, message, dropLocalState) {
51
124
  if (typeof window === "undefined") return;
52
125
  if (dropLocalState) {
53
- pendingDeletes.push(Promise.resolve().then(deps.deleteLocalState).catch(function () {}));
126
+ pendingDeletes.push(function () {
127
+ return Promise.resolve().then(deps.deleteLocalState);
128
+ });
54
129
  }
55
130
  if (reloadScheduled) return;
56
- if (!recoveryGuardOpen(reasonKey)) {
131
+ if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
57
132
  console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
58
133
  deps.zeroEvents.emit({
59
134
  type: "fatal",
@@ -62,22 +137,25 @@ function recover(deps, reasonKey, message, dropLocalState) {
62
137
  return;
63
138
  }
64
139
  reloadScheduled = true;
140
+ armReloadLatchTimeout();
65
141
  console.warn(`[on-zero] ${message} \u2014 recovering`);
66
142
  deps.zeroEvents.emit({
67
143
  type: "recovering",
68
144
  reason: message
69
145
  });
70
- var _deps_reload;
71
- var doReload = (_deps_reload = deps.reload) !== null && _deps_reload !== void 0 ? _deps_reload : function () {
72
- var _globalThis_location_reload, _globalThis_location;
73
- return (_globalThis_location = globalThis.location) === null || _globalThis_location === void 0 ? void 0 : (_globalThis_location_reload = _globalThis_location.reload) === null || _globalThis_location_reload === void 0 ? void 0 : _globalThis_location_reload.call(_globalThis_location);
146
+ var runReload = function () {
147
+ return performReload(deps);
74
148
  };
75
- Promise.resolve().then(function () {
76
- return Promise.allSettled(pendingDeletes);
77
- }).then(function () {
78
- var _deps_beforeReload;
79
- return (_deps_beforeReload = deps.beforeReload) === null || _deps_beforeReload === void 0 ? void 0 : _deps_beforeReload.call(deps);
80
- }).catch(function () {}).finally(doReload);
149
+ if (deps.scheduleReload) {
150
+ deps.scheduleReload({
151
+ reason: message,
152
+ reasonKey,
153
+ dropLocalState,
154
+ performReload: runReload
155
+ });
156
+ } else {
157
+ void runReload();
158
+ }
81
159
  }
82
160
  function makeZeroRecovery(deps) {
83
161
  return {
@@ -101,6 +179,114 @@ function logToConsole(level, context) {
101
179
  var method = level === "debug" ? "debug" : level;
102
180
  console[method](...(prefix ? [prefix] : []), ...args);
103
181
  }
182
+ function logArgText(arg) {
183
+ if (typeof arg === "string") return arg;
184
+ if (_instanceof(arg, Error)) return `${arg.name} ${arg.message} ${arg.stack || ""}`;
185
+ if (arg && (typeof arg === "undefined" ? "undefined" : _type_of(arg)) === "object") {
186
+ var message = "message" in arg ? arg.message : void 0;
187
+ var name = "name" in arg ? arg.name : void 0;
188
+ if (typeof message === "string") return `${typeof name === "string" ? name : ""} ${message}`;
189
+ }
190
+ return "";
191
+ }
192
+ function isBenignStoreClosedLog(text) {
193
+ if (/Mutator\s+".*"\s+error on server/i.test(text)) return true;
194
+ if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true;
195
+ return false;
196
+ }
197
+ function classifyMutationDesync(text) {
198
+ if (text.includes("sent mutation ID") && text.includes("but expected")) {
199
+ return {
200
+ reason: "mutation-desync",
201
+ reasonKey: "mutation-desync",
202
+ message: "mutation id desync"
203
+ };
204
+ }
205
+ if (text.includes("oooMutation") || text.includes("Server reported an out-of-order mutation")) {
206
+ return {
207
+ reason: "mutation-desync",
208
+ reasonKey: "mutation-desync",
209
+ message: "out-of-order mutation"
210
+ };
211
+ }
212
+ if (text.includes("already processed")) {
213
+ return {
214
+ reason: "mutation-desync",
215
+ reasonKey: "mutation-desync",
216
+ message: "mutation already processed"
217
+ };
218
+ }
219
+ if (text.includes("InvalidConnectionRequestLastMutationID")) {
220
+ return {
221
+ reason: "mutation-desync",
222
+ reasonKey: "mutation-desync",
223
+ message: "invalid connection last mutation id"
224
+ };
225
+ }
226
+ if (text.includes("InvalidConnectionRequestBaseCookie")) {
227
+ return {
228
+ reason: "connection-cookie-invalid",
229
+ reasonKey: "connection-cookie-invalid",
230
+ message: "invalid connection base cookie"
231
+ };
232
+ }
233
+ if (text.includes("ClientNotFound") || text.includes("Client not found")) {
234
+ return {
235
+ reason: "client-not-found",
236
+ reasonKey: "client-not-found",
237
+ message: "client not found"
238
+ };
239
+ }
240
+ if (text.includes("connection userID mismatch")) {
241
+ return {
242
+ reason: "connection-userid-mismatch",
243
+ reasonKey: "connection-userid-mismatch",
244
+ message: "connection user id mismatch"
245
+ };
246
+ }
247
+ return void 0;
248
+ }
249
+ function classifyZeroRecoveryLog(level, args) {
250
+ var nowMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
251
+ if (level !== "error") return void 0;
252
+ var text = args.map(logArgText).join(" ");
253
+ if (text.includes(LOCAL_STORE_LOST)) {
254
+ return {
255
+ reason: "indexeddb-not-found",
256
+ reasonKey: "local-store",
257
+ message: "local store lost",
258
+ dropLocalState: true
259
+ };
260
+ }
261
+ if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
262
+ return {
263
+ reason: "sqlite-statement-finalized",
264
+ reasonKey: "sqlite-statement-finalized",
265
+ message: "sqlite statement finalized",
266
+ dropLocalState: true
267
+ };
268
+ }
269
+ var desync = classifyMutationDesync(text);
270
+ if (desync) {
271
+ return {
272
+ ...desync,
273
+ dropLocalState: true
274
+ };
275
+ }
276
+ if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
277
+ var prevMs = lastStoreClosedAtMs;
278
+ lastStoreClosedAtMs = nowMs;
279
+ if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
280
+ return {
281
+ reason: "store-closed-repeat",
282
+ reasonKey: "store-closed-repeat",
283
+ message: "local store closed repeatedly",
284
+ dropLocalState: true
285
+ };
286
+ }
287
+ }
288
+ return void 0;
289
+ }
104
290
  function composeRecoveryLogSink(deps, consumerLogSink) {
105
291
  var consumerFlush = consumerLogSink === null || consumerLogSink === void 0 ? void 0 : consumerLogSink.flush;
106
292
  return {
@@ -109,13 +295,13 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
109
295
  args[_key - 2] = arguments[_key];
110
296
  }
111
297
  if (consumerLogSink) consumerLogSink.log(level, context, ...args);else logToConsole(level, context, ...args);
112
- if (level !== "error") return;
113
- var text = args.map(function (arg) {
114
- return typeof arg === "string" ? arg : arg && (typeof arg === "undefined" ? "undefined" : _type_of(arg)) === "object" && "message" in arg ? String(arg.message) : "";
115
- }).join(" ");
116
- if (text.includes(LOCAL_STORE_LOST)) {
117
- recover(deps, "local-store", "local store lost", true);
298
+ var recovery = classifyZeroRecoveryLog(level, args);
299
+ if (!recovery) return;
300
+ if (deps.benignLogFilter) {
301
+ var text = args.map(logArgText).join(" ");
302
+ if (deps.benignLogFilter(text)) return;
118
303
  }
304
+ recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState);
119
305
  },
120
306
  // call through the consumer sink so a class-based sink keeps its `this`,
121
307
  // rather than handing Zero a detached method reference.
@@ -124,8 +310,18 @@ function composeRecoveryLogSink(deps, consumerLogSink) {
124
310
  } : void 0
125
311
  };
126
312
  }
313
+ function isRecoverableZeroStalePokeMessage(message) {
314
+ return message.includes("Server returned unexpected base cookie during sync") || message.includes("Received cookie") && message.includes("is < than last snapshot cookie") && message.includes("ignoring client view");
315
+ }
127
316
  function resetRecoveryStateForTests() {
128
317
  reloadScheduled = false;
318
+ reloadInProgress = false;
319
+ if (reloadLatchTimer) {
320
+ clearTimeout(reloadLatchTimer);
321
+ reloadLatchTimer = void 0;
322
+ }
129
323
  pendingDeletes.length = 0;
324
+ lastStoreClosedAtMs = 0;
325
+ inMemoryGuard.clear();
130
326
  }
131
327
  //# sourceMappingURL=recoverZeroClient.native.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","composeRecoveryLogSink","makeZeroRecovery","resetRecoveryStateForTests","module","exports","_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","_globalThis_location_reload","_globalThis_location","globalThis","location","call","allSettled","_deps_beforeReload","beforeReload","finally","onUpdateNeeded","onClientStateNotFound","logToConsole","level","context","_len","arguments","length","args","Array","_key","prefix","Object","entries","map","param","join","method","consumerLogSink","consumerFlush","flush"],"sources":["../../../src/helpers/recoverZeroClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","recoverZeroClient_exports","__export","classifyZeroRecoveryLog","composeRecoveryLogSink","isRecoverableZeroStalePokeMessage","makeZeroRecovery","resetRecoveryStateForTests","module","exports","_instanceof","left","right","Symbol","hasInstance","_type_of","obj","constructor","RECOVER_GUARD_MS","RELOAD_LATCH_TIMEOUT_MS","LOCAL_STORE_LOST","SQLITE_ERROR_NAME","SQLITE_STATEMENT_FINALIZED","STORE_CLOSED","STORE_CLOSED_REPEAT_MIN_MS","STORE_CLOSED_REPEAT_MAX_MS","reloadScheduled","reloadInProgress","reloadLatchTimer","pendingDeletes","inMemoryGuard","Map","defaultGuardStorage","window","sessionStorage","e","recoveryGuardOpen","reasonKey","guardStorage","key","now","Date","_inMemoryGuard_get","memLast","get","storage","rawLast","getItem","last","Number","setItem","String","set","lastStoreClosedAtMs","armReloadLatchTimeout","setTimeout","clearTimeout","unref","disarmReloadLatchTimeout","performReload","deps","Promise","resolve","_deps_reload","doReload","reload","_globalThis_location_reload","_globalThis_location","globalThis","location","call","then","allSettled","splice","map","run","_deps_beforeReload","beforeReload","catch","recover","message","dropLocalState","push","deleteLocalState","console","error","zeroEvents","emit","type","reason","warn","runReload","scheduleReload","onUpdateNeeded","onClientStateNotFound","logToConsole","level","context","_len","arguments","length","args","Array","_key","prefix","Object","entries","param","join","method","logArgText","arg","Error","name","stack","isBenignStoreClosedLog","text","test","classifyMutationDesync","includes","nowMs","desync","prevMs"],"sources":["../../../src/helpers/recoverZeroClient.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}