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