on-zero 0.16.19 → 0.16.20

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 (120) hide show
  1. package/dist/cjs/createUseQuery.cjs +2 -1
  2. package/dist/cjs/createUseQuery.native.js +2 -1
  3. package/dist/cjs/createUseQuery.native.js.map +1 -1
  4. package/dist/cjs/createUseQueryDirect.cjs +2 -1
  5. package/dist/cjs/createUseQueryDirect.native.js +2 -1
  6. package/dist/cjs/createUseQueryDirect.native.js.map +1 -1
  7. package/dist/cjs/createZeroClient.cjs +75 -9
  8. package/dist/cjs/createZeroClient.native.js +151 -81
  9. package/dist/cjs/createZeroClient.native.js.map +1 -1
  10. package/dist/cjs/createZeroClient.recovery.test.cjs +351 -10
  11. package/dist/cjs/createZeroClient.recovery.test.native.js +412 -12
  12. package/dist/cjs/createZeroClient.recovery.test.native.js.map +1 -1
  13. package/dist/cjs/generate.cjs +16 -11
  14. package/dist/cjs/generate.native.js +16 -11
  15. package/dist/cjs/generate.native.js.map +1 -1
  16. package/dist/cjs/generate.test.cjs +22 -0
  17. package/dist/cjs/generate.test.native.js +22 -0
  18. package/dist/cjs/generate.test.native.js.map +1 -1
  19. package/dist/cjs/helpers/recoverZeroClient.cjs +542 -52
  20. package/dist/cjs/helpers/recoverZeroClient.native.js +721 -59
  21. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
  22. package/dist/cjs/helpers/recoverZeroClient.test.cjs +318 -0
  23. package/dist/cjs/helpers/recoverZeroClient.test.native.js +361 -0
  24. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
  25. package/dist/cjs/kvStore.cjs +30 -0
  26. package/dist/cjs/kvStore.native.js +34 -0
  27. package/dist/cjs/kvStore.native.js.map +1 -0
  28. package/dist/cjs/queryJson.cjs +58 -0
  29. package/dist/cjs/queryJson.native.js +86 -0
  30. package/dist/cjs/queryJson.native.js.map +1 -0
  31. package/dist/cjs/resolveQuery.cjs +2 -0
  32. package/dist/cjs/resolveQuery.native.js +2 -0
  33. package/dist/cjs/resolveQuery.native.js.map +1 -1
  34. package/dist/cjs/useQuery.empty.test.cjs +11 -1
  35. package/dist/cjs/useQuery.empty.test.native.js +23 -1
  36. package/dist/cjs/useQuery.empty.test.native.js.map +1 -1
  37. package/dist/cjs/useQuery.ssr.test.cjs +22 -1
  38. package/dist/cjs/useQuery.ssr.test.native.js +30 -1
  39. package/dist/cjs/useQuery.ssr.test.native.js.map +1 -1
  40. package/dist/esm/createUseQuery.mjs +2 -1
  41. package/dist/esm/createUseQuery.mjs.map +1 -1
  42. package/dist/esm/createUseQuery.native.js +2 -1
  43. package/dist/esm/createUseQuery.native.js.map +1 -1
  44. package/dist/esm/createUseQueryDirect.mjs +2 -1
  45. package/dist/esm/createUseQueryDirect.mjs.map +1 -1
  46. package/dist/esm/createUseQueryDirect.native.js +2 -1
  47. package/dist/esm/createUseQueryDirect.native.js.map +1 -1
  48. package/dist/esm/createZeroClient.mjs +76 -10
  49. package/dist/esm/createZeroClient.mjs.map +1 -1
  50. package/dist/esm/createZeroClient.native.js +152 -82
  51. package/dist/esm/createZeroClient.native.js.map +1 -1
  52. package/dist/esm/createZeroClient.recovery.test.mjs +352 -11
  53. package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
  54. package/dist/esm/createZeroClient.recovery.test.native.js +413 -13
  55. package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
  56. package/dist/esm/generate.mjs +16 -11
  57. package/dist/esm/generate.mjs.map +1 -1
  58. package/dist/esm/generate.native.js +16 -11
  59. package/dist/esm/generate.native.js.map +1 -1
  60. package/dist/esm/generate.test.mjs +22 -0
  61. package/dist/esm/generate.test.mjs.map +1 -1
  62. package/dist/esm/generate.test.native.js +22 -0
  63. package/dist/esm/generate.test.native.js.map +1 -1
  64. package/dist/esm/helpers/recoverZeroClient.mjs +542 -54
  65. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
  66. package/dist/esm/helpers/recoverZeroClient.native.js +721 -61
  67. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
  68. package/dist/esm/helpers/recoverZeroClient.test.mjs +319 -1
  69. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
  70. package/dist/esm/helpers/recoverZeroClient.test.native.js +362 -1
  71. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
  72. package/dist/esm/kvStore.mjs +5 -0
  73. package/dist/esm/kvStore.mjs.map +1 -0
  74. package/dist/esm/kvStore.native.js +6 -0
  75. package/dist/esm/kvStore.native.js.map +1 -0
  76. package/dist/esm/queryJson.mjs +32 -0
  77. package/dist/esm/queryJson.mjs.map +1 -0
  78. package/dist/esm/queryJson.native.js +57 -0
  79. package/dist/esm/queryJson.native.js.map +1 -0
  80. package/dist/esm/resolveQuery.mjs +2 -0
  81. package/dist/esm/resolveQuery.mjs.map +1 -1
  82. package/dist/esm/resolveQuery.native.js +2 -0
  83. package/dist/esm/resolveQuery.native.js.map +1 -1
  84. package/dist/esm/useQuery.empty.test.mjs +12 -2
  85. package/dist/esm/useQuery.empty.test.mjs.map +1 -1
  86. package/dist/esm/useQuery.empty.test.native.js +24 -2
  87. package/dist/esm/useQuery.empty.test.native.js.map +1 -1
  88. package/dist/esm/useQuery.ssr.test.mjs +23 -2
  89. package/dist/esm/useQuery.ssr.test.mjs.map +1 -1
  90. package/dist/esm/useQuery.ssr.test.native.js +31 -2
  91. package/dist/esm/useQuery.ssr.test.native.js.map +1 -1
  92. package/package.json +11 -3
  93. package/src/createUseQuery.tsx +2 -1
  94. package/src/createUseQueryDirect.tsx +2 -1
  95. package/src/createZeroClient.recovery.test.tsx +370 -7
  96. package/src/createZeroClient.tsx +100 -10
  97. package/src/generate.test.ts +31 -0
  98. package/src/generate.ts +22 -10
  99. package/src/helpers/recoverZeroClient.test.ts +323 -0
  100. package/src/helpers/recoverZeroClient.ts +896 -78
  101. package/src/kvStore.native.ts +7 -0
  102. package/src/kvStore.ts +7 -0
  103. package/src/queryJson.ts +46 -0
  104. package/src/resolveQuery.ts +2 -0
  105. package/src/useQuery.empty.test.tsx +16 -2
  106. package/src/useQuery.ssr.test.ts +23 -2
  107. package/types/createUseQuery.d.ts.map +1 -1
  108. package/types/createUseQueryDirect.d.ts.map +1 -1
  109. package/types/createZeroClient.d.ts.map +1 -1
  110. package/types/createZeroClient.recovery.test.d.ts.map +1 -1
  111. package/types/generate.d.ts.map +1 -1
  112. package/types/helpers/recoverZeroClient.d.ts +6 -0
  113. package/types/helpers/recoverZeroClient.d.ts.map +1 -1
  114. package/types/kvStore.d.ts +2 -0
  115. package/types/kvStore.d.ts.map +1 -0
  116. package/types/kvStore.native.d.ts +3 -0
  117. package/types/kvStore.native.d.ts.map +1 -0
  118. package/types/queryJson.d.ts +3 -0
  119. package/types/queryJson.d.ts.map +1 -0
  120. package/types/resolveQuery.d.ts.map +1 -1
@@ -26,11 +26,14 @@ var recoverZeroClient_exports = {};
26
26
  __export(recoverZeroClient_exports, {
27
27
  classifyZeroRecoveryLog: () => classifyZeroRecoveryLog,
28
28
  composeRecoveryLogSink: () => composeRecoveryLogSink,
29
+ isGroupTransitionOpen: () => isGroupTransitionOpen,
29
30
  isRecoverableZeroStalePokeMessage: () => isRecoverableZeroStalePokeMessage,
30
31
  makeZeroRecovery: () => makeZeroRecovery,
32
+ primeGroupCache: () => primeGroupCache,
31
33
  resetRecoveryStateForTests: () => resetRecoveryStateForTests
32
34
  });
33
35
  module.exports = __toCommonJS(recoverZeroClient_exports);
36
+ var import_globalValue = require("./globalValue.native.js");
34
37
  function _instanceof(left, right) {
35
38
  "@swc/helpers - instanceof";
36
39
 
@@ -45,18 +48,45 @@ function _type_of(obj) {
45
48
  }
46
49
  var RECOVER_GUARD_MS = 6e4;
47
50
  var RELOAD_LATCH_TIMEOUT_MS = 15e3;
51
+ var GROUP_TRANSITION_REASONS = /* @__PURE__ */new Set(["NewClientGroup", "VersionNotSupported", "SchemaVersionNotSupported"]);
48
52
  var LOCAL_STORE_LOST = "Expected IndexedDB not found";
49
53
  var SQLITE_ERROR_NAME = "SqliteError";
50
54
  var SQLITE_STATEMENT_FINALIZED = "This statement has been finalized";
51
55
  var STORE_CLOSED = "Store is closed";
52
56
  var STORE_CLOSED_REPEAT_MIN_MS = 2e3;
53
57
  var STORE_CLOSED_REPEAT_MAX_MS = 6e4;
54
- var reloadScheduled = false;
55
- var reloadInProgress = false;
56
- var reloadLatchTimer;
57
- var pendingDeletes = [];
58
- var pendingInPlaceRecoveries = [];
59
- var inMemoryGuard = /* @__PURE__ */new Map();
58
+ function sharedRecoveryState() {
59
+ return (0, import_globalValue.globalValue)("on-zero:recovery-shared", function () {
60
+ return {
61
+ reloadScheduled: false,
62
+ reloadInProgress: false,
63
+ reloadLatchTimer: void 0,
64
+ pendingDeletes: [],
65
+ pendingInPlaceRecoveries: [],
66
+ inMemoryGuard: /* @__PURE__ */new Map(),
67
+ constructionSeq: 0,
68
+ constructionSeqByDeps: /* @__PURE__ */new WeakMap(),
69
+ groupByDeps: /* @__PURE__ */new WeakMap(),
70
+ transitions: /* @__PURE__ */new Map(),
71
+ terminalMemory: /* @__PURE__ */new Map(),
72
+ terminalEmitted: /* @__PURE__ */new Map(),
73
+ unknownPostSignals: /* @__PURE__ */new Map(),
74
+ lastStoreClosedAtMs: 0
75
+ };
76
+ });
77
+ }
78
+ function documentScope() {
79
+ try {
80
+ var _ref;
81
+ var _globalThis_location;
82
+ return (_ref = (_globalThis_location = globalThis.location) === null || _globalThis_location === void 0 ? void 0 : _globalThis_location.href) !== null && _ref !== void 0 ? _ref : "";
83
+ } catch (unused) {
84
+ return "";
85
+ }
86
+ }
87
+ function guardStorageKey(reasonKey) {
88
+ return `on-zero-recover-${documentScope()}-${reasonKey}`;
89
+ }
60
90
  function defaultGuardStorage() {
61
91
  try {
62
92
  if (typeof window === "undefined" || !window.sessionStorage) return void 0;
@@ -66,16 +96,10 @@ function defaultGuardStorage() {
66
96
  }
67
97
  }
68
98
  function recoveryGuardOpen(reasonKey, guardStorage) {
69
- var _inMemoryGuard_get;
70
- var documentScope = "";
71
- try {
72
- var _ref;
73
- var _globalThis_location;
74
- documentScope = (_ref = (_globalThis_location = globalThis.location) === null || _globalThis_location === void 0 ? void 0 : _globalThis_location.href) !== null && _ref !== void 0 ? _ref : "";
75
- } catch (unused) {}
76
- var key = `on-zero-recover-${documentScope}-${reasonKey}`;
99
+ var _sharedRecoveryState_inMemoryGuard_get;
100
+ var key = guardStorageKey(reasonKey);
77
101
  var now = Date.now();
78
- var memLast = (_inMemoryGuard_get = inMemoryGuard.get(key)) !== null && _inMemoryGuard_get !== void 0 ? _inMemoryGuard_get : 0;
102
+ var memLast = (_sharedRecoveryState_inMemoryGuard_get = sharedRecoveryState().inMemoryGuard.get(key)) !== null && _sharedRecoveryState_inMemoryGuard_get !== void 0 ? _sharedRecoveryState_inMemoryGuard_get : 0;
79
103
  if (memLast > 0 && now - memLast < RECOVER_GUARD_MS) return false;
80
104
  var storage = guardStorage !== null && guardStorage !== void 0 ? guardStorage : defaultGuardStorage();
81
105
  if (storage) {
@@ -86,31 +110,503 @@ function recoveryGuardOpen(reasonKey, guardStorage) {
86
110
  storage.setItem(key, String(now));
87
111
  } catch (unused) {}
88
112
  }
89
- inMemoryGuard.set(key, now);
113
+ sharedRecoveryState().inMemoryGuard.set(key, now);
90
114
  return true;
91
115
  }
92
- var lastStoreClosedAtMs = 0;
116
+ function readRecoveryMarker(reasonKey, guardStorage) {
117
+ var storage = guardStorage !== null && guardStorage !== void 0 ? guardStorage : defaultGuardStorage();
118
+ if (!storage) return null;
119
+ var raw = null;
120
+ try {
121
+ raw = storage.getItem(guardStorageKey(reasonKey));
122
+ } catch (unused) {
123
+ return null;
124
+ }
125
+ if (!raw) return null;
126
+ if (/^\d+$/.test(raw)) return {
127
+ t: Number(raw)
128
+ };
129
+ try {
130
+ var parsed = JSON.parse(raw);
131
+ if (!parsed || typeof parsed.t !== "number") return null;
132
+ return parsed;
133
+ } catch (unused) {
134
+ return null;
135
+ }
136
+ }
137
+ function writeRecoveryMarker(reasonKey, marker, guardStorage) {
138
+ var storage = guardStorage !== null && guardStorage !== void 0 ? guardStorage : defaultGuardStorage();
139
+ if (!storage) return;
140
+ try {
141
+ storage.setItem(guardStorageKey(reasonKey), JSON.stringify(marker));
142
+ } catch (unused) {}
143
+ }
144
+ function clearRecoveryMarker(reasonKey, guardStorage) {
145
+ var storage = guardStorage !== null && guardStorage !== void 0 ? guardStorage : defaultGuardStorage();
146
+ if (!storage) return;
147
+ try {
148
+ if (typeof storage.removeItem === "function") {
149
+ storage.removeItem(guardStorageKey(reasonKey));
150
+ } else {
151
+ storage.setItem(guardStorageKey(reasonKey), JSON.stringify({
152
+ t: 0
153
+ }));
154
+ }
155
+ } catch (unused) {}
156
+ }
93
157
  function armReloadLatchTimeout() {
158
+ var shared = sharedRecoveryState();
94
159
  if (typeof setTimeout !== "function") return;
95
- if (reloadLatchTimer) clearTimeout(reloadLatchTimer);
96
- reloadLatchTimer = setTimeout(function () {
97
- reloadLatchTimer = void 0;
98
- reloadScheduled = false;
160
+ if (shared.reloadLatchTimer) clearTimeout(shared.reloadLatchTimer);
161
+ shared.reloadLatchTimer = setTimeout(function () {
162
+ shared.reloadLatchTimer = void 0;
163
+ shared.reloadScheduled = false;
99
164
  }, RELOAD_LATCH_TIMEOUT_MS);
100
- if (reloadLatchTimer && (typeof reloadLatchTimer === "undefined" ? "undefined" : _type_of(reloadLatchTimer)) === "object" && "unref" in reloadLatchTimer) {
101
- reloadLatchTimer.unref();
165
+ if (shared.reloadLatchTimer && _type_of(shared.reloadLatchTimer) === "object" && "unref" in shared.reloadLatchTimer) {
166
+ shared.reloadLatchTimer.unref();
102
167
  }
103
168
  }
104
169
  function disarmReloadLatchTimeout() {
105
- if (reloadLatchTimer) {
106
- clearTimeout(reloadLatchTimer);
107
- reloadLatchTimer = void 0;
170
+ var shared = sharedRecoveryState();
171
+ if (shared.reloadLatchTimer) {
172
+ clearTimeout(shared.reloadLatchTimer);
173
+ shared.reloadLatchTimer = void 0;
174
+ }
175
+ }
176
+ function pushGlobalDelete(deps) {
177
+ var shared = sharedRecoveryState();
178
+ if (shared.pendingDeletes.some(function (entry) {
179
+ return entry.owner === deps.deleteLocalState;
180
+ })) {
181
+ return;
182
+ }
183
+ shared.pendingDeletes.push({
184
+ owner: deps.deleteLocalState,
185
+ run: function run() {
186
+ return Promise.resolve().then(deps.deleteLocalState);
187
+ }
188
+ });
189
+ }
190
+ function removeGlobalDelete(owner) {
191
+ var pending = sharedRecoveryState().pendingDeletes;
192
+ var index = pending.findIndex(function (entry) {
193
+ return entry.owner === owner;
194
+ });
195
+ if (index !== -1) pending.splice(index, 1);
196
+ }
197
+ function removeGlobalRemint(fn) {
198
+ if (!fn) return;
199
+ var pending = sharedRecoveryState().pendingInPlaceRecoveries;
200
+ var index = pending.indexOf(fn);
201
+ if (index !== -1) pending.splice(index, 1);
202
+ }
203
+ function seqOf(deps) {
204
+ var shared = sharedRecoveryState();
205
+ var seq = shared.constructionSeqByDeps.get(deps);
206
+ if (seq === void 0) {
207
+ seq = ++shared.constructionSeq;
208
+ shared.constructionSeqByDeps.set(deps, seq);
209
+ }
210
+ return seq;
211
+ }
212
+ function refreshGroupCache(deps) {
213
+ if (!deps.getGroupID) return;
214
+ var result;
215
+ try {
216
+ result = deps.getGroupID();
217
+ } catch (unused) {
218
+ return;
219
+ }
220
+ if (typeof result === "string") {
221
+ if (result) sharedRecoveryState().groupByDeps.set(deps, result);
222
+ return;
223
+ }
224
+ void Promise.resolve(result).then(function (id) {
225
+ if (typeof id === "string" && id) sharedRecoveryState().groupByDeps.set(deps, id);
226
+ }, function () {});
227
+ }
228
+ function cachedGroupID(deps) {
229
+ return sharedRecoveryState().groupByDeps.get(deps);
230
+ }
231
+ function primeGroupCache(deps) {
232
+ refreshGroupCache(deps);
233
+ }
234
+ function participantKey(deps) {
235
+ var _deps_recoverInPlace;
236
+ return (_deps_recoverInPlace = deps.recoverInPlace) !== null && _deps_recoverInPlace !== void 0 ? _deps_recoverInPlace : deps.deleteLocalState;
237
+ }
238
+ function transitionKey(deps) {
239
+ var _deps_clientIdentity;
240
+ return `${documentScope()}\0${(_deps_clientIdentity = deps.clientIdentity) !== null && _deps_clientIdentity !== void 0 ? _deps_clientIdentity : ""}`;
241
+ }
242
+ function findOpenTransitionParticipant(deps) {
243
+ var transition = sharedRecoveryState().transitions.get(transitionKey(deps));
244
+ if (!transition || transition.settled) return void 0;
245
+ if (seqOf(deps) > transition.startSeq) return void 0;
246
+ return transition.participants.get(participantKey(deps));
247
+ }
248
+ function isGroupTransitionOpen() {
249
+ return sharedRecoveryState().transitions.size > 0;
250
+ }
251
+ function terminalKey(key, reasonKey) {
252
+ return `${key}\0${reasonKey}`;
253
+ }
254
+ function stampTerminal(key, reasonKey, guardStorage, message, groups) {
255
+ sharedRecoveryState().terminalMemory.set(terminalKey(key, reasonKey), {
256
+ t: Date.now(),
257
+ groups
258
+ });
259
+ writeRecoveryMarker(reasonKey, {
260
+ t: Date.now(),
261
+ terminal: true,
262
+ groups,
263
+ msg: message
264
+ }, guardStorage);
265
+ }
266
+ function emitTerminalOnce(deps, key, reasonKey, message) {
267
+ var _shared_terminalEmitted_get;
268
+ var shared = sharedRecoveryState();
269
+ var now = Date.now();
270
+ var emitKey = terminalKey(key, reasonKey);
271
+ var lastEmitted = (_shared_terminalEmitted_get = shared.terminalEmitted.get(emitKey)) !== null && _shared_terminalEmitted_get !== void 0 ? _shared_terminalEmitted_get : 0;
272
+ if (lastEmitted > 0 && now - lastEmitted < RECOVER_GUARD_MS) return;
273
+ shared.terminalEmitted.set(emitKey, now);
274
+ try {
275
+ console.error(`[on-zero] ${message}`);
276
+ deps.zeroEvents.emit({
277
+ type: "fatal",
278
+ reasonKey,
279
+ reason: message
280
+ });
281
+ } catch (unused) {}
282
+ try {
283
+ var _globalThis_dispatchEvent, _globalThis;
284
+ (_globalThis_dispatchEvent = (_globalThis = globalThis).dispatchEvent) === null || _globalThis_dispatchEvent === void 0 ? void 0 : _globalThis_dispatchEvent.call(_globalThis, new CustomEvent("on-zero-fatal", {
285
+ detail: {
286
+ reasonKey,
287
+ reason: message
288
+ }
289
+ }));
290
+ } catch (unused) {}
291
+ }
292
+ function settleTransition(transition, outcome) {
293
+ if (transition.settled) return;
294
+ transition.settled = true;
295
+ transition.outcome = outcome;
296
+ sharedRecoveryState().transitions.delete(transition.key);
297
+ transition.notifySettled();
298
+ }
299
+ function checkTransitionComplete(transition) {
300
+ if (transition.settled) return;
301
+ var _iteratorNormalCompletion = true,
302
+ _didIteratorError = false,
303
+ _iteratorError = void 0;
304
+ try {
305
+ for (var _iterator = transition.participants.values()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
306
+ var participant = _step.value;
307
+ if (!participant.reminted && !participant.skipped) return;
308
+ }
309
+ } catch (err) {
310
+ _didIteratorError = true;
311
+ _iteratorError = err;
312
+ } finally {
313
+ try {
314
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
315
+ _iterator.return();
316
+ }
317
+ } finally {
318
+ if (_didIteratorError) {
319
+ throw _iteratorError;
320
+ }
321
+ }
322
+ }
323
+ if (transition.pendingWaits > 0) return;
324
+ settleTransition(transition, "completed");
325
+ }
326
+ function failTransition(transition, input) {
327
+ if (transition.settled) return;
328
+ var groups = [...new Set([...transition.participants.values()].map(function (participant) {
329
+ return participant.oldGroupID;
330
+ }).filter(function (group) {
331
+ return typeof group === "string";
332
+ }))];
333
+ settleTransition(transition, "terminal");
334
+ var _iteratorNormalCompletion = true,
335
+ _didIteratorError = false,
336
+ _iteratorError = void 0;
337
+ try {
338
+ for (var _iterator = (/* @__PURE__ */new Set([...transition.reasons, input.reasonKey]))[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
339
+ var reasonKey = _step.value;
340
+ stampTerminal(transition.key, reasonKey, input.signalDeps.guardStorage, input.message, groups);
341
+ }
342
+ } catch (err) {
343
+ _didIteratorError = true;
344
+ _iteratorError = err;
345
+ } finally {
346
+ try {
347
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
348
+ _iterator.return();
349
+ }
350
+ } finally {
351
+ if (_didIteratorError) {
352
+ throw _iteratorError;
353
+ }
354
+ }
355
+ }
356
+ emitTerminalOnce(input.signalDeps, transition.key, input.reasonKey, input.message);
357
+ }
358
+ function makeWrappedRemint(transition, participant) {
359
+ return async function () {
360
+ if (participant.skipped || participant.reminted) return true;
361
+ var remint = participant.deps.recoverInPlace;
362
+ if (!remint) {
363
+ participant.skipped = true;
364
+ checkTransitionComplete(transition);
365
+ return false;
366
+ }
367
+ var ok;
368
+ try {
369
+ ok = await remint();
370
+ } catch (error) {
371
+ var [firstReason] = transition.reasons;
372
+ failTransition(transition, {
373
+ reasonKey: firstReason !== null && firstReason !== void 0 ? firstReason : "NewClientGroup",
374
+ message: `in-place recovery threw (${_instanceof(error, Error) ? error.message : String(error)})`,
375
+ signalDeps: participant.deps
376
+ });
377
+ return false;
378
+ }
379
+ if (!ok) {
380
+ participant.skipped = true;
381
+ checkTransitionComplete(transition);
382
+ return false;
383
+ }
384
+ participant.reminted = true;
385
+ var awaitReconnected = participant.deps.awaitReconnected;
386
+ if (awaitReconnected) {
387
+ transition.pendingWaits += 1;
388
+ try {
389
+ await Promise.race([awaitReconnected(), transition.settledPromise]);
390
+ } catch (unused) {} finally {
391
+ transition.pendingWaits -= 1;
392
+ }
393
+ }
394
+ checkTransitionComplete(transition);
395
+ return true;
396
+ };
397
+ }
398
+ async function runParticipantImmediate(transition, participant) {
399
+ var doDelete = participant.dropLocalState && !participant.deleteExecuted;
400
+ var doRemint = !participant.remintExecuted;
401
+ participant.deleteExecuted = true;
402
+ participant.remintExecuted = true;
403
+ if (doDelete) {
404
+ try {
405
+ await participant.deps.deleteLocalState();
406
+ } catch (unused) {}
108
407
  }
408
+ if (doRemint) {
409
+ if (participant.wrappedRemint) await participant.wrappedRemint();else {
410
+ participant.skipped = true;
411
+ checkTransitionComplete(transition);
412
+ }
413
+ }
414
+ }
415
+ function joinTransition(transition, deps, reasonKey, dropLocalState) {
416
+ transition.reasons.add(reasonKey);
417
+ var key = participantKey(deps);
418
+ var existing = transition.participants.get(key);
419
+ if (existing) {
420
+ if (dropLocalState && !existing.dropLocalState) {
421
+ existing.dropLocalState = true;
422
+ if (existing.deleteExecuted) pushGlobalDelete(deps);
423
+ }
424
+ return;
425
+ }
426
+ removeGlobalDelete(deps.deleteLocalState);
427
+ removeGlobalRemint(deps.recoverInPlace);
428
+ var participant = {
429
+ deps,
430
+ dropLocalState,
431
+ deleteExecuted: false,
432
+ remintExecuted: false,
433
+ reminted: false,
434
+ skipped: false,
435
+ oldGroupID: cachedGroupID(deps),
436
+ wrappedRemint: null
437
+ };
438
+ participant.wrappedRemint = makeWrappedRemint(transition, participant);
439
+ transition.participants.set(key, participant);
440
+ if (transition.remintsExecuted) void runParticipantImmediate(transition, participant);
441
+ }
442
+ function startTransition(deps, reasonKey, message, dropLocalState) {
443
+ var shared = sharedRecoveryState();
444
+ var key = transitionKey(deps);
445
+ var notifySettled;
446
+ var settledPromise = new Promise(function (resolve) {
447
+ notifySettled = resolve;
448
+ });
449
+ var transition = {
450
+ key,
451
+ reasons: /* @__PURE__ */new Set([reasonKey]),
452
+ participants: /* @__PURE__ */new Map(),
453
+ startSeq: shared.constructionSeq,
454
+ startedAtMs: Date.now(),
455
+ remintsExecuted: false,
456
+ pendingWaits: 0,
457
+ settled: false,
458
+ outcome: null,
459
+ settledPromise,
460
+ notifySettled
461
+ };
462
+ shared.transitions.set(key, transition);
463
+ joinTransition(transition, deps, reasonKey, dropLocalState);
464
+ console.warn(`[on-zero] ${message} \u2014 recovering`);
465
+ deps.zeroEvents.emit({
466
+ type: "recovering",
467
+ reasonKey,
468
+ reason: message
469
+ });
470
+ if (shared.reloadScheduled && !shared.reloadInProgress) return;
471
+ if (shared.reloadInProgress) {
472
+ transition.remintsExecuted = true;
473
+ var _iteratorNormalCompletion = true,
474
+ _didIteratorError = false,
475
+ _iteratorError = void 0;
476
+ try {
477
+ for (var _iterator = transition.participants.values()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
478
+ var participant = _step.value;
479
+ void runParticipantImmediate(transition, participant);
480
+ }
481
+ } catch (err) {
482
+ _didIteratorError = true;
483
+ _iteratorError = err;
484
+ } finally {
485
+ try {
486
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
487
+ _iterator.return();
488
+ }
489
+ } finally {
490
+ if (_didIteratorError) {
491
+ throw _iteratorError;
492
+ }
493
+ }
494
+ }
495
+ return;
496
+ }
497
+ shared.reloadScheduled = true;
498
+ armReloadLatchTimeout();
499
+ var runReload = function runReload2() {
500
+ return performReload(deps);
501
+ };
502
+ if (deps.scheduleReload) {
503
+ deps.scheduleReload({
504
+ reason: message,
505
+ reasonKey,
506
+ dropLocalState,
507
+ performReload: runReload
508
+ });
509
+ } else {
510
+ void runReload();
511
+ }
512
+ }
513
+ function checkTransitionGuard(deps, reasonKey) {
514
+ var shared = sharedRecoveryState();
515
+ var key = transitionKey(deps);
516
+ var now = Date.now();
517
+ var myGroup = cachedGroupID(deps);
518
+ var memory = shared.terminalMemory.get(terminalKey(key, reasonKey));
519
+ if (memory && memory.t > 0 && now - memory.t < RECOVER_GUARD_MS) {
520
+ if (myGroup !== void 0 && memory.groups.length > 0 && !memory.groups.includes(myGroup)) {
521
+ shared.terminalMemory.delete(terminalKey(key, reasonKey));
522
+ } else {
523
+ return "silent";
524
+ }
525
+ }
526
+ var marker = readRecoveryMarker(reasonKey, deps.guardStorage);
527
+ if (marker && marker.t > 0 && now - marker.t < RECOVER_GUARD_MS) {
528
+ var markerGroups = marker.groups && marker.groups.length > 0 ? marker.groups : void 0;
529
+ if (myGroup !== void 0 && markerGroups !== void 0 && !markerGroups.includes(myGroup)) {
530
+ clearRecoveryMarker(reasonKey, deps.guardStorage);
531
+ return "allow";
532
+ }
533
+ if (marker.terminal) {
534
+ var _marker_msg;
535
+ emitTerminalOnce(deps, key, reasonKey, (_marker_msg = marker.msg) !== null && _marker_msg !== void 0 ? _marker_msg : `update needed (${reasonKey}) \u2014 recovery already failed, not retrying`);
536
+ return "silent";
537
+ }
538
+ if (myGroup !== void 0 && markerGroups !== void 0 && markerGroups.includes(myGroup)) {
539
+ var message = `update needed (${reasonKey}) \u2014 client group ${myGroup} \u2192 ${myGroup} (unchanged after reload), not reloading`;
540
+ stampTerminal(key, reasonKey, deps.guardStorage, message, markerGroups);
541
+ emitTerminalOnce(deps, key, reasonKey, message);
542
+ return "silent";
543
+ }
544
+ var message1 = `update needed (${reasonKey}) \u2014 already recovered once, not reloading`;
545
+ stampTerminal(key, reasonKey, deps.guardStorage, message1, markerGroups !== null && markerGroups !== void 0 ? markerGroups : []);
546
+ emitTerminalOnce(deps, key, reasonKey, message1);
547
+ return "silent";
548
+ }
549
+ return "allow";
550
+ }
551
+ function handlePostTransitionSignal(transition, deps, reasonKey, message, dropLocalState) {
552
+ var _ref, _ref1;
553
+ var shared = sharedRecoveryState();
554
+ var newGroup = cachedGroupID(deps);
555
+ var oldGroups = [...new Set([...transition.participants.values()].map(function (participant) {
556
+ return participant.oldGroupID;
557
+ }).filter(function (group) {
558
+ return typeof group === "string";
559
+ }))];
560
+ if (newGroup !== void 0 && oldGroups.length > 0) {
561
+ if (!oldGroups.includes(newGroup)) {
562
+ settleTransition(transition, "superseded");
563
+ startTransition(deps, reasonKey, message, dropLocalState);
564
+ return;
565
+ }
566
+ failTransition(transition, {
567
+ reasonKey,
568
+ message: `${message} \u2014 client group ${newGroup} did not change after recovery (still ${oldGroups.join(", ")}), not retrying`,
569
+ signalDeps: deps
570
+ });
571
+ return;
572
+ }
573
+ var now = Date.now();
574
+ var budget = shared.unknownPostSignals.get(transition.key);
575
+ var freshBudget = budget && now - budget.windowStartMs < RECOVER_GUARD_MS ? budget : null;
576
+ if (freshBudget && freshBudget.count >= 1) {
577
+ failTransition(transition, {
578
+ reasonKey,
579
+ message: `${message} \u2014 recovery did not resolve the client group, not retrying`,
580
+ signalDeps: deps
581
+ });
582
+ return;
583
+ }
584
+ shared.unknownPostSignals.set(transition.key, {
585
+ count: ((_ref = freshBudget === null || freshBudget === void 0 ? void 0 : freshBudget.count) !== null && _ref !== void 0 ? _ref : 0) + 1,
586
+ windowStartMs: (_ref1 = freshBudget === null || freshBudget === void 0 ? void 0 : freshBudget.windowStartMs) !== null && _ref1 !== void 0 ? _ref1 : now
587
+ });
588
+ settleTransition(transition, "superseded");
589
+ startTransition(deps, reasonKey, message, dropLocalState);
590
+ }
591
+ function recoverViaGroupTransition(deps, reasonKey, message, dropLocalState) {
592
+ var key = transitionKey(deps);
593
+ var open = sharedRecoveryState().transitions.get(key);
594
+ if (open && !open.settled) {
595
+ if (seqOf(deps) > open.startSeq) {
596
+ handlePostTransitionSignal(open, deps, reasonKey, message, dropLocalState);
597
+ return;
598
+ }
599
+ joinTransition(open, deps, reasonKey, dropLocalState);
600
+ return;
601
+ }
602
+ if (checkTransitionGuard(deps, reasonKey) !== "allow") return;
603
+ startTransition(deps, reasonKey, message, dropLocalState);
109
604
  }
110
605
  function performReload(deps) {
111
606
  var _deps_reload;
112
- if (reloadInProgress) return Promise.resolve();
113
- reloadInProgress = true;
607
+ var shared = sharedRecoveryState();
608
+ if (shared.reloadInProgress) return Promise.resolve();
609
+ shared.reloadInProgress = true;
114
610
  disarmReloadLatchTimeout();
115
611
  var doReload = (_deps_reload = deps.reload) !== null && _deps_reload !== void 0 ? _deps_reload : function () {
116
612
  var _globalThis_location;
@@ -119,23 +615,116 @@ function performReload(deps) {
119
615
  reload.call(globalThis.location);
120
616
  return true;
121
617
  };
122
- var inPlaceRecoveries = [];
618
+ var globalDeletes = [];
619
+ var globalRemints = [];
620
+ var openTransitions = [];
621
+ var transitionDeletes = [];
622
+ var transitionRemints = [];
123
623
  return Promise.resolve().then(function () {
124
- inPlaceRecoveries = pendingInPlaceRecoveries.splice(0);
125
- return Promise.allSettled(pendingDeletes.splice(0).map(function (run) {
624
+ globalDeletes = shared.pendingDeletes.splice(0);
625
+ globalRemints = shared.pendingInPlaceRecoveries.splice(0);
626
+ openTransitions = [...shared.transitions.values()].filter(function (transition2) {
627
+ return !transition2.settled;
628
+ });
629
+ var _iteratorNormalCompletion = true,
630
+ _didIteratorError = false,
631
+ _iteratorError = void 0;
632
+ try {
633
+ for (var _iterator = openTransitions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
634
+ var transition = _step.value;
635
+ transition.remintsExecuted = true;
636
+ var _iteratorNormalCompletion1 = true,
637
+ _didIteratorError1 = false,
638
+ _iteratorError1 = void 0;
639
+ try {
640
+ var _loop = function () {
641
+ var participant = _step1.value;
642
+ if (participant.dropLocalState && !participant.deleteExecuted) {
643
+ participant.deleteExecuted = true;
644
+ var runDelete = participant.deps.deleteLocalState;
645
+ transitionDeletes.push(function () {
646
+ return Promise.resolve().then(runDelete);
647
+ });
648
+ }
649
+ if (!participant.remintExecuted) {
650
+ participant.remintExecuted = true;
651
+ if (participant.wrappedRemint) {
652
+ transitionRemints.push({
653
+ transition,
654
+ run: participant.wrappedRemint
655
+ });
656
+ } else {
657
+ participant.skipped = true;
658
+ checkTransitionComplete(transition);
659
+ }
660
+ }
661
+ };
662
+ for (var _iterator1 = transition.participants.values()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) _loop();
663
+ } catch (err) {
664
+ _didIteratorError1 = true;
665
+ _iteratorError1 = err;
666
+ } finally {
667
+ try {
668
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
669
+ _iterator1.return();
670
+ }
671
+ } finally {
672
+ if (_didIteratorError1) {
673
+ throw _iteratorError1;
674
+ }
675
+ }
676
+ }
677
+ }
678
+ } catch (err) {
679
+ _didIteratorError = true;
680
+ _iteratorError = err;
681
+ } finally {
682
+ try {
683
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
684
+ _iterator.return();
685
+ }
686
+ } finally {
687
+ if (_didIteratorError) {
688
+ throw _iteratorError;
689
+ }
690
+ }
691
+ }
692
+ return Promise.allSettled([...globalDeletes.map(function (entry) {
693
+ return entry.run();
694
+ }), ...transitionDeletes.map(function (run) {
126
695
  return run();
127
- }));
696
+ })]);
128
697
  }).then(function () {
129
698
  var _deps_beforeReload;
130
699
  return (_deps_beforeReload = deps.beforeReload) === null || _deps_beforeReload === void 0 ? void 0 : _deps_beforeReload.call(deps);
131
700
  }).catch(function () {}).then(async function () {
132
- var reloadStarted = doReload();
133
- if (reloadStarted !== false) return;
701
+ var reloadStarted = false;
134
702
  try {
135
- var results = await Promise.all(inPlaceRecoveries.map(function (recover2) {
703
+ reloadStarted = doReload();
704
+ } catch (unused) {
705
+ reloadStarted = false;
706
+ }
707
+ if (reloadStarted !== false) {
708
+ noteTransitionsReloading(openTransitions);
709
+ return;
710
+ }
711
+ try {
712
+ var liveRemints = transitionRemints.filter(function (param) {
713
+ var {
714
+ transition
715
+ } = param;
716
+ return !transition.settled;
717
+ });
718
+ var results = await Promise.all([...globalRemints.map(function (recover2) {
136
719
  return recover2();
137
- }));
138
- if (inPlaceRecoveries.length > 0 && results.some(function (recovered) {
720
+ }), ...liveRemints.map(function (param) {
721
+ var {
722
+ run
723
+ } = param;
724
+ return run();
725
+ })]);
726
+ var globalResults = results.slice(0, globalRemints.length);
727
+ if (globalRemints.length > 0 && globalResults.some(function (recovered) {
139
728
  return !recovered;
140
729
  })) {
141
730
  console.error("[on-zero] recovery could not reload or reconstruct the client");
@@ -143,24 +732,90 @@ function performReload(deps) {
143
732
  } catch (error) {
144
733
  console.error("[on-zero] in-place recovery failed", error);
145
734
  } finally {
146
- reloadInProgress = false;
147
- reloadScheduled = false;
735
+ shared.reloadInProgress = false;
736
+ shared.reloadScheduled = false;
148
737
  }
149
738
  });
150
739
  }
740
+ function noteTransitionsReloading(transitions) {
741
+ var _iteratorNormalCompletion = true,
742
+ _didIteratorError = false,
743
+ _iteratorError = void 0;
744
+ try {
745
+ for (var _iterator = transitions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
746
+ var transition = _step.value;
747
+ if (transition.settled) continue;
748
+ var groups = [...new Set([...transition.participants.values()].map(function (participant) {
749
+ return participant.oldGroupID;
750
+ }).filter(function (group) {
751
+ return typeof group === "string";
752
+ }))];
753
+ var [firstParticipant] = transition.participants.values();
754
+ var _iteratorNormalCompletion1 = true,
755
+ _didIteratorError1 = false,
756
+ _iteratorError1 = void 0;
757
+ try {
758
+ for (var _iterator1 = transition.reasons[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
759
+ var reasonKey = _step1.value;
760
+ writeRecoveryMarker(reasonKey, {
761
+ t: Date.now(),
762
+ groups
763
+ }, firstParticipant === null || firstParticipant === void 0 ? void 0 : firstParticipant.deps.guardStorage);
764
+ }
765
+ } catch (err) {
766
+ _didIteratorError1 = true;
767
+ _iteratorError1 = err;
768
+ } finally {
769
+ try {
770
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
771
+ _iterator1.return();
772
+ }
773
+ } finally {
774
+ if (_didIteratorError1) {
775
+ throw _iteratorError1;
776
+ }
777
+ }
778
+ }
779
+ settleTransition(transition, "reloading");
780
+ }
781
+ } catch (err) {
782
+ _didIteratorError = true;
783
+ _iteratorError = err;
784
+ } finally {
785
+ try {
786
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
787
+ _iterator.return();
788
+ }
789
+ } finally {
790
+ if (_didIteratorError) {
791
+ throw _iteratorError;
792
+ }
793
+ }
794
+ }
795
+ }
151
796
  function recover(deps, reasonKey, message, dropLocalState) {
152
797
  var _deps_onRecovery;
153
798
  if (typeof window === "undefined") return;
154
799
  (_deps_onRecovery = deps.onRecovery) === null || _deps_onRecovery === void 0 ? void 0 : _deps_onRecovery.call(deps, reasonKey);
155
- if (dropLocalState) {
156
- pendingDeletes.push(function () {
157
- return Promise.resolve().then(deps.deleteLocalState);
158
- });
800
+ refreshGroupCache(deps);
801
+ if (GROUP_TRANSITION_REASONS.has(reasonKey)) {
802
+ recoverViaGroupTransition(deps, reasonKey, message, dropLocalState);
803
+ return;
159
804
  }
160
- if (deps.recoverInPlace && !pendingInPlaceRecoveries.includes(deps.recoverInPlace)) {
161
- pendingInPlaceRecoveries.push(deps.recoverInPlace);
805
+ var shared = sharedRecoveryState();
806
+ var participant = findOpenTransitionParticipant(deps);
807
+ if (!participant) {
808
+ if (dropLocalState) {
809
+ pushGlobalDelete(deps);
810
+ }
811
+ if (deps.recoverInPlace && !shared.pendingInPlaceRecoveries.includes(deps.recoverInPlace)) {
812
+ shared.pendingInPlaceRecoveries.push(deps.recoverInPlace);
813
+ }
814
+ } else if (dropLocalState && !participant.dropLocalState) {
815
+ participant.dropLocalState = true;
816
+ if (participant.deleteExecuted) pushGlobalDelete(deps);
162
817
  }
163
- if (reloadScheduled) return;
818
+ if (shared.reloadScheduled) return;
164
819
  if (!recoveryGuardOpen(reasonKey, deps.guardStorage)) {
165
820
  console.error(`[on-zero] ${message} \u2014 already recovered once, not reloading`);
166
821
  deps.zeroEvents.emit({
@@ -179,7 +834,7 @@ function recover(deps, reasonKey, message, dropLocalState) {
179
834
  } catch (unused) {}
180
835
  return;
181
836
  }
182
- reloadScheduled = true;
837
+ shared.reloadScheduled = true;
183
838
  armReloadLatchTimeout();
184
839
  console.warn(`[on-zero] ${message} \u2014 recovering`);
185
840
  deps.zeroEvents.emit({
@@ -202,6 +857,7 @@ function recover(deps, reasonKey, message, dropLocalState) {
202
857
  }
203
858
  }
204
859
  function makeZeroRecovery(deps) {
860
+ seqOf(deps);
205
861
  return {
206
862
  onUpdateNeeded(reason) {
207
863
  var dropLocalState = reason.type === "SchemaVersionNotSupported";
@@ -309,8 +965,9 @@ function classifyZeroRecoveryLog(level, args) {
309
965
  };
310
966
  }
311
967
  if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
312
- var prevMs = lastStoreClosedAtMs;
313
- lastStoreClosedAtMs = nowMs;
968
+ var shared = sharedRecoveryState();
969
+ var prevMs = shared.lastStoreClosedAtMs;
970
+ shared.lastStoreClosedAtMs = nowMs;
314
971
  if (prevMs > 0 && nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS && nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS) {
315
972
  return {
316
973
  reasonKey: "store-closed-repeat",
@@ -354,15 +1011,20 @@ function isRecoverableZeroStalePokeMessage(message) {
354
1011
  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");
355
1012
  }
356
1013
  function resetRecoveryStateForTests() {
357
- reloadScheduled = false;
358
- reloadInProgress = false;
359
- if (reloadLatchTimer) {
360
- clearTimeout(reloadLatchTimer);
361
- reloadLatchTimer = void 0;
362
- }
363
- pendingDeletes.length = 0;
364
- pendingInPlaceRecoveries.length = 0;
365
- lastStoreClosedAtMs = 0;
366
- inMemoryGuard.clear();
1014
+ var shared = sharedRecoveryState();
1015
+ shared.reloadScheduled = false;
1016
+ shared.reloadInProgress = false;
1017
+ if (shared.reloadLatchTimer) {
1018
+ clearTimeout(shared.reloadLatchTimer);
1019
+ shared.reloadLatchTimer = void 0;
1020
+ }
1021
+ shared.pendingDeletes.length = 0;
1022
+ shared.pendingInPlaceRecoveries.length = 0;
1023
+ shared.lastStoreClosedAtMs = 0;
1024
+ shared.inMemoryGuard.clear();
1025
+ shared.transitions.clear();
1026
+ shared.terminalMemory.clear();
1027
+ shared.terminalEmitted.clear();
1028
+ shared.unknownPostSignals.clear();
367
1029
  }
368
1030
  //# sourceMappingURL=recoverZeroClient.native.js.map