sibujs 1.4.0 → 2.0.0

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 (190) hide show
  1. package/README.md +105 -119
  2. package/dist/browser.cjs +288 -80
  3. package/dist/browser.d.cts +19 -9
  4. package/dist/browser.d.ts +19 -9
  5. package/dist/browser.js +6 -6
  6. package/dist/build.cjs +1019 -313
  7. package/dist/build.d.cts +1 -1
  8. package/dist/build.d.ts +1 -1
  9. package/dist/build.js +15 -13
  10. package/dist/cdn.global.js +17 -16
  11. package/dist/chunk-2RA7SHDA.js +65 -0
  12. package/dist/chunk-2UPRY23K.js +80 -0
  13. package/dist/chunk-3JHCYHWN.js +125 -0
  14. package/dist/{chunk-ZWKZCBO6.js → chunk-3LR7GLWQ.js} +154 -33
  15. package/dist/{chunk-3AIRKM3B.js → chunk-3NSGB5JN.js} +115 -34
  16. package/dist/{chunk-3ARAQO7B.js → chunk-52YJLLRO.js} +29 -6
  17. package/dist/chunk-54EDRCEF.js +93 -0
  18. package/dist/chunk-7JDB7I65.js +1327 -0
  19. package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
  20. package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
  21. package/dist/{chunk-WR5D4EGH.js → chunk-GTBNNBJ6.js} +14 -2
  22. package/dist/chunk-HB24TBAF.js +121 -0
  23. package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
  24. package/dist/{chunk-JAKHTMQU.js → chunk-JA6667UN.js} +206 -46
  25. package/dist/{chunk-77L6NL3X.js → chunk-JXMMDLBY.js} +306 -183
  26. package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
  27. package/dist/{chunk-F3FA4F32.js → chunk-KLRMB5ZS.js} +135 -79
  28. package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
  29. package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
  30. package/dist/{chunk-TSOKIX5Z.js → chunk-MIUAXB7K.js} +126 -74
  31. package/dist/{chunk-QWZG56ET.js → chunk-ND2664SF.js} +558 -190
  32. package/dist/{chunk-JCI5M6U6.js → chunk-O2MNQFLP.js} +261 -79
  33. package/dist/{chunk-EWFVA3TJ.js → chunk-R73P76YZ.js} +1 -1
  34. package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
  35. package/dist/chunk-UCS6AMJ7.js +79 -0
  36. package/dist/{chunk-ZD6OAMTH.js → chunk-VLPPXTYG.js} +90 -35
  37. package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
  38. package/dist/{contracts-xo5ckdRP.d.cts → contracts-ey_Qh8ef.d.cts} +7 -8
  39. package/dist/{contracts-xo5ckdRP.d.ts → contracts-ey_Qh8ef.d.ts} +7 -8
  40. package/dist/{customElement-D2DJp_xn.d.cts → customElement-CPfIrbvg.d.cts} +18 -9
  41. package/dist/{customElement-D2DJp_xn.d.ts → customElement-CPfIrbvg.d.ts} +18 -9
  42. package/dist/data.cjs +452 -100
  43. package/dist/data.d.cts +20 -2
  44. package/dist/data.d.ts +20 -2
  45. package/dist/data.js +11 -9
  46. package/dist/devtools.cjs +535 -247
  47. package/dist/devtools.d.cts +1 -1
  48. package/dist/devtools.d.ts +1 -1
  49. package/dist/devtools.js +34 -30
  50. package/dist/ecosystem.cjs +499 -143
  51. package/dist/ecosystem.d.cts +13 -11
  52. package/dist/ecosystem.d.ts +13 -11
  53. package/dist/ecosystem.js +12 -11
  54. package/dist/extras.cjs +3639 -1629
  55. package/dist/extras.d.cts +11 -11
  56. package/dist/extras.d.ts +11 -11
  57. package/dist/extras.js +58 -45
  58. package/dist/index.cjs +1023 -313
  59. package/dist/index.d.cts +128 -55
  60. package/dist/index.d.ts +128 -55
  61. package/dist/index.js +28 -16
  62. package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
  63. package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
  64. package/dist/motion.cjs +90 -36
  65. package/dist/motion.d.cts +1 -1
  66. package/dist/motion.d.ts +1 -1
  67. package/dist/motion.js +4 -4
  68. package/dist/patterns.cjs +414 -81
  69. package/dist/patterns.d.cts +53 -20
  70. package/dist/patterns.d.ts +53 -20
  71. package/dist/patterns.js +7 -7
  72. package/dist/performance.cjs +364 -108
  73. package/dist/performance.d.cts +29 -17
  74. package/dist/performance.d.ts +29 -17
  75. package/dist/performance.js +13 -6
  76. package/dist/plugin-D30wlGW5.d.cts +71 -0
  77. package/dist/plugin-D30wlGW5.d.ts +71 -0
  78. package/dist/plugins.cjs +652 -271
  79. package/dist/plugins.d.cts +13 -6
  80. package/dist/plugins.d.ts +13 -6
  81. package/dist/plugins.js +116 -50
  82. package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
  83. package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
  84. package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
  85. package/dist/ssr.cjs +648 -219
  86. package/dist/ssr.d.cts +27 -7
  87. package/dist/ssr.d.ts +27 -7
  88. package/dist/ssr.js +12 -11
  89. package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.cts} +9 -1
  90. package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.ts} +9 -1
  91. package/dist/testing.cjs +252 -63
  92. package/dist/testing.d.cts +17 -4
  93. package/dist/testing.d.ts +17 -4
  94. package/dist/testing.js +100 -44
  95. package/dist/ui.cjs +576 -168
  96. package/dist/ui.d.cts +13 -16
  97. package/dist/ui.d.ts +13 -16
  98. package/dist/ui.js +20 -17
  99. package/dist/widgets.cjs +1001 -93
  100. package/dist/widgets.d.cts +104 -2
  101. package/dist/widgets.d.ts +104 -2
  102. package/dist/widgets.js +9 -7
  103. package/package.json +8 -2
  104. package/dist/chunk-32DY64NT.js +0 -282
  105. package/dist/chunk-3CRQALYP.js +0 -877
  106. package/dist/chunk-4EI4AG32.js +0 -482
  107. package/dist/chunk-4MYMUBRS.js +0 -21
  108. package/dist/chunk-6HLLIF3K.js +0 -398
  109. package/dist/chunk-6LSNVCS2.js +0 -937
  110. package/dist/chunk-6SA3QQES.js +0 -61
  111. package/dist/chunk-7BF6TK55.js +0 -1097
  112. package/dist/chunk-7TQKR4PP.js +0 -294
  113. package/dist/chunk-7V26P53V.js +0 -712
  114. package/dist/chunk-AZ3ISID5.js +0 -298
  115. package/dist/chunk-B7SWRFUT.js +0 -332
  116. package/dist/chunk-BGN5ZMP4.js +0 -26
  117. package/dist/chunk-BTU3TJDS.js +0 -365
  118. package/dist/chunk-BW3WT46K.js +0 -937
  119. package/dist/chunk-C6KFWOFV.js +0 -616
  120. package/dist/chunk-CHF5OHIA.js +0 -61
  121. package/dist/chunk-CHJ27IGK.js +0 -26
  122. package/dist/chunk-CMBFNA7L.js +0 -27
  123. package/dist/chunk-DAHRH4ON.js +0 -331
  124. package/dist/chunk-DKOHBI74.js +0 -924
  125. package/dist/chunk-DTCOOBMX.js +0 -725
  126. package/dist/chunk-EBGIRKQY.js +0 -616
  127. package/dist/chunk-EUZND3CB.js +0 -27
  128. package/dist/chunk-EVCZO745.js +0 -365
  129. package/dist/chunk-FGOEVHY3.js +0 -60
  130. package/dist/chunk-G3BOQPVO.js +0 -365
  131. package/dist/chunk-GCOK2LC3.js +0 -282
  132. package/dist/chunk-HGMJFBC7.js +0 -654
  133. package/dist/chunk-K5ZUMYVS.js +0 -89
  134. package/dist/chunk-KQPDEVVS.js +0 -398
  135. package/dist/chunk-L6JRBDNS.js +0 -60
  136. package/dist/chunk-LA6KQEDU.js +0 -712
  137. package/dist/chunk-MDVXJWFN.js +0 -304
  138. package/dist/chunk-MEZVEBPN.js +0 -2008
  139. package/dist/chunk-MK4ERFYL.js +0 -2249
  140. package/dist/chunk-MLKGABMK.js +0 -9
  141. package/dist/chunk-MQ5GOYPH.js +0 -2249
  142. package/dist/chunk-N6IZB6KJ.js +0 -567
  143. package/dist/chunk-NEKUBFPT.js +0 -60
  144. package/dist/chunk-NHUC2QWH.js +0 -282
  145. package/dist/chunk-NMRUZALC.js +0 -1097
  146. package/dist/chunk-NYVAC6P5.js +0 -37
  147. package/dist/chunk-OF7UZIVB.js +0 -725
  148. package/dist/chunk-P6W3STU4.js +0 -2249
  149. package/dist/chunk-PBHF5WKN.js +0 -616
  150. package/dist/chunk-PTQJDMRT.js +0 -146
  151. package/dist/chunk-PZEGYCF5.js +0 -61
  152. package/dist/chunk-QBMDLBU2.js +0 -975
  153. package/dist/chunk-RQGQSLQK.js +0 -725
  154. package/dist/chunk-SDLZDHKP.js +0 -107
  155. package/dist/chunk-TNQWPPE6.js +0 -37
  156. package/dist/chunk-UHNL42EF.js +0 -2730
  157. package/dist/chunk-UNXCEF6S.js +0 -21
  158. package/dist/chunk-V2XTI523.js +0 -347
  159. package/dist/chunk-VAU366PN.js +0 -2241
  160. package/dist/chunk-VMVDTCXB.js +0 -712
  161. package/dist/chunk-VRW3FULF.js +0 -725
  162. package/dist/chunk-WADYRCO2.js +0 -304
  163. package/dist/chunk-WILQZRO4.js +0 -282
  164. package/dist/chunk-WUHJISPP.js +0 -298
  165. package/dist/chunk-XYU6TZOW.js +0 -182
  166. package/dist/chunk-Y6GP4QGG.js +0 -276
  167. package/dist/chunk-YECR7UIA.js +0 -347
  168. package/dist/chunk-YUTWTI4B.js +0 -654
  169. package/dist/chunk-Z65KYU7I.js +0 -26
  170. package/dist/chunk-Z6POF5YC.js +0 -975
  171. package/dist/chunk-ZBJP6WFL.js +0 -482
  172. package/dist/contracts-DDrwxvJ-.d.cts +0 -245
  173. package/dist/contracts-DDrwxvJ-.d.ts +0 -245
  174. package/dist/contracts-DOrhwbke.d.cts +0 -245
  175. package/dist/contracts-DOrhwbke.d.ts +0 -245
  176. package/dist/customElement-BKQfbSZQ.d.cts +0 -262
  177. package/dist/customElement-BKQfbSZQ.d.ts +0 -262
  178. package/dist/customElement-yz8uyk-0.d.cts +0 -308
  179. package/dist/customElement-yz8uyk-0.d.ts +0 -308
  180. package/dist/introspect-Cb0zgpi2.d.cts +0 -477
  181. package/dist/introspect-Y2xNXGSf.d.ts +0 -477
  182. package/dist/plugin-Bek4RhJY.d.cts +0 -43
  183. package/dist/plugin-Bek4RhJY.d.ts +0 -43
  184. package/dist/ssr-3RXHP5ES.js +0 -38
  185. package/dist/ssr-6GIMY5MX.js +0 -38
  186. package/dist/ssr-BA6sxxUd.d.cts +0 -135
  187. package/dist/ssr-BA6sxxUd.d.ts +0 -135
  188. package/dist/ssr-WKUPVSSK.js +0 -36
  189. package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
  190. package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  context
3
- } from "./chunk-BGN5ZMP4.js";
3
+ } from "./chunk-GTBNNBJ6.js";
4
4
  import {
5
5
  derived
6
- } from "./chunk-NEKUBFPT.js";
6
+ } from "./chunk-54EDRCEF.js";
7
7
  import {
8
8
  sanitizeUrl
9
- } from "./chunk-CMBFNA7L.js";
9
+ } from "./chunk-UCS6AMJ7.js";
10
10
  import {
11
11
  effect
12
- } from "./chunk-CHF5OHIA.js";
12
+ } from "./chunk-HB24TBAF.js";
13
13
  import {
14
14
  batch,
15
15
  signal
16
- } from "./chunk-WZSPOOER.js";
16
+ } from "./chunk-CC65Y57T.js";
17
17
 
18
18
  // src/data/retry.ts
19
19
  function calculateDelay(attempt, strategy, baseDelay, maxDelay, jitter) {
@@ -30,10 +30,12 @@ function calculateDelay(attempt, strategy, baseDelay, maxDelay, jitter) {
30
30
  break;
31
31
  }
32
32
  delay = Math.min(delay, maxDelay);
33
+ if (!Number.isFinite(delay)) delay = Number.MAX_SAFE_INTEGER;
33
34
  if (jitter > 0) {
34
35
  const jitterRange = delay * jitter;
35
36
  delay += (Math.random() * 2 - 1) * jitterRange;
36
37
  }
38
+ if (!Number.isFinite(delay) || Number.isNaN(delay)) delay = 0;
37
39
  return Math.max(0, delay);
38
40
  }
39
41
  async function withRetry(fn, options, onRetry, signal2) {
@@ -47,6 +49,7 @@ async function withRetry(fn, options, onRetry, signal2) {
47
49
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
48
50
  if (signal2?.aborted) throw new DOMException("Aborted", "AbortError");
49
51
  try {
52
+ if (signal2?.aborted) throw new DOMException("Aborted", "AbortError");
50
53
  return await fn();
51
54
  } catch (error) {
52
55
  lastError = error;
@@ -54,9 +57,13 @@ async function withRetry(fn, options, onRetry, signal2) {
54
57
  const delay = calculateDelay(attempt, strategy, baseDelay, maxDelay, jitter);
55
58
  onRetry?.(error, attempt, delay);
56
59
  await new Promise((resolve, reject) => {
57
- const timer = setTimeout(resolve, delay);
60
+ let onAbort = null;
61
+ const timer = setTimeout(() => {
62
+ if (onAbort && signal2) signal2.removeEventListener("abort", onAbort);
63
+ resolve();
64
+ }, delay);
58
65
  if (signal2) {
59
- const onAbort = () => {
66
+ onAbort = () => {
60
67
  clearTimeout(timer);
61
68
  reject(new DOMException("Aborted", "AbortError"));
62
69
  };
@@ -124,24 +131,46 @@ function query(key, fetcher, options = {}) {
124
131
  let entry = queryCache.get(key2);
125
132
  if (!entry) {
126
133
  entry = getOrCreateEntry(key2);
127
- entry.subscribers++;
128
134
  entry.listeners.add(onCacheUpdate);
129
135
  entry.refetchers.add(doFetch);
130
136
  }
131
137
  if (entry.promise) {
132
138
  setIsFetching(true);
139
+ const captured = entry.promise;
133
140
  try {
134
- await entry.promise;
141
+ await captured;
142
+ if (disposed || currentKey !== key2) return;
143
+ if (entry.promise === captured) {
144
+ onCacheUpdate();
145
+ if (entry.error) onError?.(entry.error);
146
+ else if (entry.data !== void 0) onSuccess?.(entry.data);
147
+ }
135
148
  } catch {
149
+ if (disposed || currentKey !== key2) return;
150
+ if (entry.promise === captured) {
151
+ onCacheUpdate();
152
+ if (entry.error) onError?.(entry.error);
153
+ }
154
+ } finally {
155
+ if (!disposed && currentKey === key2) onSettled?.();
136
156
  }
137
- onCacheUpdate();
138
157
  return;
139
158
  }
140
159
  abortController?.abort();
141
160
  abortController = new AbortController();
142
161
  const signal2 = abortController.signal;
143
162
  setIsFetching(true);
144
- const promise = withRetry(() => fetcher({ signal: signal2, key: key2 }), retryOptions, void 0, signal2);
163
+ let promise;
164
+ try {
165
+ promise = withRetry(() => fetcher({ signal: signal2, key: key2 }), retryOptions, void 0, signal2);
166
+ } catch (err) {
167
+ setIsFetching(false);
168
+ const errorObj = err instanceof Error ? err : new Error(String(err));
169
+ entry.error = errorObj;
170
+ onError?.(errorObj);
171
+ onSettled?.();
172
+ return;
173
+ }
145
174
  entry.promise = promise;
146
175
  try {
147
176
  const result = await promise;
@@ -203,13 +232,15 @@ function query(key, fetcher, options = {}) {
203
232
  oldEntry.subscribers--;
204
233
  if (oldEntry.subscribers <= 0 && cacheTime >= 0) {
205
234
  const oldKey = currentKey;
235
+ if (oldEntry.gcTimer !== null) clearTimeout(oldEntry.gcTimer);
206
236
  oldEntry.gcTimer = setTimeout(() => queryCache.delete(oldKey), cacheTime);
207
237
  }
208
238
  }
209
239
  }
240
+ const keyChanged = currentKey !== key2;
210
241
  currentKey = key2;
211
242
  const entry = getOrCreateEntry(key2, initialData);
212
- entry.subscribers++;
243
+ if (keyChanged) entry.subscribers++;
213
244
  if (entry.gcTimer !== null) {
214
245
  clearTimeout(entry.gcTimer);
215
246
  entry.gcTimer = null;
@@ -224,6 +255,11 @@ function query(key, fetcher, options = {}) {
224
255
  setError(entry.error);
225
256
  });
226
257
  }
258
+ if (!keyChanged && currentKey === key2 && entry.data !== void 0) {
259
+ const isDataStale2 = entry.dataUpdatedAt === 0 || Date.now() - entry.dataUpdatedAt >= staleTime;
260
+ if (enabled && isDataStale2 && !entry.promise) doFetch();
261
+ return;
262
+ }
227
263
  const isDataStale = entry.dataUpdatedAt === 0 || Date.now() - entry.dataUpdatedAt >= staleTime;
228
264
  if (enabled && (entry.data === void 0 || isDataStale)) {
229
265
  doFetch();
@@ -251,6 +287,7 @@ function query(key, fetcher, options = {}) {
251
287
  }
252
288
  }
253
289
  function dispose() {
290
+ if (disposed) return;
254
291
  disposed = true;
255
292
  abortController?.abort();
256
293
  effectCleanup();
@@ -263,12 +300,17 @@ function query(key, fetcher, options = {}) {
263
300
  entry.subscribers--;
264
301
  if (entry.subscribers <= 0 && cacheTime >= 0) {
265
302
  const key2 = currentKey;
303
+ if (entry.gcTimer !== null) clearTimeout(entry.gcTimer);
266
304
  entry.gcTimer = setTimeout(() => queryCache.delete(key2), cacheTime);
267
305
  }
268
306
  }
269
307
  }
270
- if (focusHandler) globalThis.removeEventListener("focus", focusHandler);
271
- if (onlineHandler) globalThis.removeEventListener("online", onlineHandler);
308
+ if (focusHandler && typeof globalThis.removeEventListener === "function") {
309
+ globalThis.removeEventListener("focus", focusHandler);
310
+ }
311
+ if (onlineHandler && typeof globalThis.removeEventListener === "function") {
312
+ globalThis.removeEventListener("online", onlineHandler);
313
+ }
272
314
  }
273
315
  return {
274
316
  data,
@@ -312,7 +354,19 @@ function clearQueryCache() {
312
354
  }
313
355
  queryCache.clear();
314
356
  for (const listener of activeListeners) listener();
315
- for (const refetcher of activeRefetchers) refetcher();
357
+ for (const refetcher of activeRefetchers) {
358
+ refetcher().catch((err) => {
359
+ if (typeof console !== "undefined") {
360
+ console.warn("[SibuJS query] refetch after clearQueryCache failed:", err);
361
+ }
362
+ });
363
+ }
364
+ }
365
+ function __resetQueryCache() {
366
+ for (const entry of queryCache.values()) {
367
+ if (entry.gcTimer) clearTimeout(entry.gcTimer);
368
+ }
369
+ queryCache.clear();
316
370
  }
317
371
 
318
372
  // src/data/mutation.ts
@@ -323,7 +377,9 @@ function mutation(mutationFn, options = {}) {
323
377
  const [status, setStatus] = signal("idle");
324
378
  const isSuccess = derived(() => status() === "success");
325
379
  const isIdle = derived(() => status() === "idle");
380
+ let runId = 0;
326
381
  async function execute(variables) {
382
+ const myRun = ++runId;
327
383
  let context2;
328
384
  batch(() => {
329
385
  setLoading(true);
@@ -335,6 +391,7 @@ function mutation(mutationFn, options = {}) {
335
391
  context2 = await options.onMutate(variables);
336
392
  }
337
393
  const result = await withRetry(() => mutationFn(variables), options.retry);
394
+ if (myRun !== runId) return result;
338
395
  batch(() => {
339
396
  setData(result);
340
397
  setLoading(false);
@@ -345,6 +402,7 @@ function mutation(mutationFn, options = {}) {
345
402
  return result;
346
403
  } catch (err) {
347
404
  const errorObj = err instanceof Error ? err : new Error(String(err));
405
+ if (myRun !== runId) throw errorObj;
348
406
  batch(() => {
349
407
  setError(errorObj);
350
408
  setLoading(false);
@@ -356,6 +414,7 @@ function mutation(mutationFn, options = {}) {
356
414
  }
357
415
  }
358
416
  function reset() {
417
+ runId++;
359
418
  batch(() => {
360
419
  setData(void 0);
361
420
  setError(void 0);
@@ -370,7 +429,10 @@ function mutation(mutationFn, options = {}) {
370
429
  isSuccess,
371
430
  isIdle,
372
431
  mutate: (variables) => {
373
- execute(variables).catch(() => {
432
+ execute(variables).catch((err) => {
433
+ if (typeof console !== "undefined") {
434
+ console.warn("[SibuJS mutation] mutate() failed; check `.error()` signal or onError option.", err);
435
+ }
374
436
  });
375
437
  },
376
438
  mutateAsync: execute,
@@ -406,11 +468,13 @@ function infiniteQuery(key, fetcher, options) {
406
468
  const hasPreviousPage = derived(() => prevPageParam() !== void 0);
407
469
  let abortController = null;
408
470
  let disposed = false;
471
+ let runId = 0;
409
472
  async function fetchPage(pageParam, direction) {
410
473
  if (disposed) return;
411
474
  abortController?.abort();
412
475
  abortController = new AbortController();
413
476
  const signal2 = abortController.signal;
477
+ const myRun = ++runId;
414
478
  batch(() => {
415
479
  setIsFetching(true);
416
480
  if (direction === "next") setIsFetchingNext(true);
@@ -419,7 +483,7 @@ function infiniteQuery(key, fetcher, options) {
419
483
  });
420
484
  try {
421
485
  const page = await withRetry(() => fetcher({ signal: signal2, pageParam }), retryOptions, void 0, signal2);
422
- if (disposed) return;
486
+ if (disposed || myRun !== runId) return;
423
487
  const currentPages = pages();
424
488
  let newPages;
425
489
  if (direction === "prev") {
@@ -439,7 +503,7 @@ function infiniteQuery(key, fetcher, options) {
439
503
  });
440
504
  onSuccess?.(newPages);
441
505
  } catch (err) {
442
- if (disposed) return;
506
+ if (disposed || myRun !== runId) return;
443
507
  if (err instanceof DOMException && err.name === "AbortError") return;
444
508
  const errorObj = err instanceof Error ? err : new Error(String(err));
445
509
  batch(() => {
@@ -454,9 +518,12 @@ function infiniteQuery(key, fetcher, options) {
454
518
  const effectCleanup = effect(() => {
455
519
  resolveKey();
456
520
  if (enabled) {
457
- setPages([]);
458
- setNextPageParam(initialPageParam);
459
- setPrevPageParam(void 0);
521
+ abortController?.abort();
522
+ batch(() => {
523
+ setPages([]);
524
+ setNextPageParam(initialPageParam);
525
+ setPrevPageParam(void 0);
526
+ });
460
527
  fetchPage(initialPageParam, "initial");
461
528
  }
462
529
  });
@@ -605,7 +672,10 @@ function resource(sourceOrFetcher, fetcherOrOptions, maybeOptions) {
605
672
  options.onSuccess?.(result);
606
673
  } catch (err) {
607
674
  if (version !== fetchVersion || disposed) return;
608
- if (err instanceof DOMException && err.name === "AbortError") return;
675
+ if (err instanceof DOMException && err.name === "AbortError") {
676
+ if (version === fetchVersion) setLoading(false);
677
+ return;
678
+ }
609
679
  const errorObj = err instanceof Error ? err : new Error(String(err));
610
680
  batch(() => {
611
681
  setError(errorObj);
@@ -690,18 +760,57 @@ function idbPut(db, store, item) {
690
760
  tx.onerror = () => reject(tx.error);
691
761
  });
692
762
  }
693
- function idbDelete(db, store, key) {
763
+ function idbPutWithChange(db, item, change) {
764
+ return new Promise((resolve, reject) => {
765
+ const tx = db.transaction(["items", "_changes"], "readwrite");
766
+ tx.objectStore("items").put(item);
767
+ tx.objectStore("_changes").put(change);
768
+ tx.oncomplete = () => resolve();
769
+ tx.onerror = () => reject(tx.error);
770
+ });
771
+ }
772
+ function idbDeleteWithChange(db, key, change) {
773
+ return new Promise((resolve, reject) => {
774
+ const tx = db.transaction(["items", "_changes"], "readwrite");
775
+ tx.objectStore("items").delete(key);
776
+ tx.objectStore("_changes").put(change);
777
+ tx.oncomplete = () => resolve();
778
+ tx.onerror = () => reject(tx.error);
779
+ });
780
+ }
781
+ function idbGetAllWithKeys(db, store) {
782
+ return new Promise((resolve, reject) => {
783
+ const tx = db.transaction(store, "readonly");
784
+ const out = [];
785
+ const req = tx.objectStore(store).openCursor();
786
+ req.onsuccess = () => {
787
+ const cursor = req.result;
788
+ if (cursor) {
789
+ out.push({ key: cursor.primaryKey, value: cursor.value });
790
+ cursor.continue();
791
+ } else {
792
+ resolve(out);
793
+ }
794
+ };
795
+ req.onerror = () => reject(req.error);
796
+ });
797
+ }
798
+ function idbDeleteKeys(db, store, keys) {
799
+ if (keys.length === 0) return Promise.resolve();
694
800
  return new Promise((resolve, reject) => {
695
801
  const tx = db.transaction(store, "readwrite");
696
- tx.objectStore(store).delete(key);
802
+ const objStore = tx.objectStore(store);
803
+ for (const k of keys) objStore.delete(k);
697
804
  tx.oncomplete = () => resolve();
698
805
  tx.onerror = () => reject(tx.error);
699
806
  });
700
807
  }
701
- function idbClear(db, store) {
808
+ function idbPutMany(db, store, items) {
809
+ if (items.length === 0) return Promise.resolve();
702
810
  return new Promise((resolve, reject) => {
703
811
  const tx = db.transaction(store, "readwrite");
704
- tx.objectStore(store).clear();
812
+ const objStore = tx.objectStore(store);
813
+ for (const item of items) objStore.put(item);
705
814
  tx.oncomplete = () => resolve();
706
815
  tx.onerror = () => reject(tx.error);
707
816
  });
@@ -724,15 +833,13 @@ async function offlineStore(options) {
724
833
  setPendingCount(changes.length);
725
834
  }
726
835
  async function put(item) {
727
- await idbPut(db, "items", item);
728
- await idbPut(db, "_changes", { type: "put", item, timestamp: Date.now() });
836
+ await idbPutWithChange(db, item, { type: "put", item, timestamp: Date.now() });
729
837
  await refreshData();
730
838
  }
731
839
  async function remove(key) {
732
840
  const existing = await idbGet(db, "items", key);
733
841
  if (existing) {
734
- await idbDelete(db, "items", key);
735
- await idbPut(db, "_changes", { type: "delete", item: existing, timestamp: Date.now() });
842
+ await idbDeleteWithChange(db, key, { type: "delete", item: existing, timestamp: Date.now() });
736
843
  await refreshData();
737
844
  }
738
845
  }
@@ -743,25 +850,45 @@ async function offlineStore(options) {
743
850
  return data().filter(filter);
744
851
  }
745
852
  async function sync() {
746
- if (!adapter || isSyncing()) return;
853
+ if (!adapter || isSyncing() || closed) return;
747
854
  setIsSyncing(true);
748
855
  try {
749
- const changes = await idbGetAll(db, "_changes");
750
- if (changes.length > 0) {
751
- const result = await adapter.push(changes);
856
+ const snapshot = await idbGetAllWithKeys(db, "_changes");
857
+ if (closed) return;
858
+ if (snapshot.length > 0) {
859
+ const result = await adapter.push(snapshot.map((e) => e.value));
860
+ if (closed) return;
752
861
  if (result.ok) {
753
- await idbClear(db, "_changes");
862
+ await idbDeleteKeys(
863
+ db,
864
+ "_changes",
865
+ snapshot.map((e) => e.key)
866
+ );
867
+ if (closed) return;
754
868
  }
755
869
  }
756
870
  const remoteItems = await adapter.pull(lastSynced());
757
- for (const item of remoteItems) {
758
- await idbPut(db, "items", item);
871
+ if (closed) return;
872
+ const pendingChanges = await idbGetAll(db, "_changes");
873
+ if (closed) return;
874
+ const pendingKeys = /* @__PURE__ */ new Set();
875
+ for (const c of pendingChanges) {
876
+ const k = c.item[keyPath];
877
+ if (k != null) pendingKeys.add(k);
759
878
  }
879
+ const safeRemote = remoteItems.filter((item) => {
880
+ const k = item[keyPath];
881
+ return k == null || !pendingKeys.has(k);
882
+ });
883
+ await idbPutMany(db, "items", safeRemote);
884
+ if (closed) return;
760
885
  const now = Date.now();
761
886
  await idbPut(db, "_meta", now);
887
+ if (closed) return;
762
888
  setLastSynced(now);
763
889
  await refreshData();
764
- } catch {
890
+ } catch (err) {
891
+ if (typeof console !== "undefined") console.warn("[offlineStore] sync failed", err);
765
892
  } finally {
766
893
  setIsSyncing(false);
767
894
  }
@@ -769,13 +896,21 @@ async function offlineStore(options) {
769
896
  function attach(newAdapter) {
770
897
  adapter = newAdapter;
771
898
  }
899
+ let onlineHandler = null;
900
+ let closed = false;
772
901
  function close() {
902
+ closed = true;
903
+ if (onlineHandler && typeof window !== "undefined") {
904
+ window.removeEventListener("online", onlineHandler);
905
+ onlineHandler = null;
906
+ }
773
907
  db.close();
774
908
  }
775
909
  if (autoSync && typeof window !== "undefined") {
776
- window.addEventListener("online", () => {
910
+ onlineHandler = () => {
777
911
  sync();
778
- });
912
+ };
913
+ window.addEventListener("online", onlineHandler);
779
914
  }
780
915
  return {
781
916
  data,
@@ -813,9 +948,16 @@ function loaderData() {
813
948
  error: resource2.error
814
949
  };
815
950
  }
816
- async function preloadRoute(route, context2) {
951
+ async function preloadRoute(route, context2, callerSignal) {
817
952
  if (!route.loader) return void 0;
818
953
  const controller = new AbortController();
954
+ if (callerSignal) {
955
+ if (callerSignal.aborted) {
956
+ controller.abort();
957
+ } else {
958
+ callerSignal.addEventListener("abort", () => controller.abort(), { once: true });
959
+ }
960
+ }
819
961
  return route.loader(context2, { signal: controller.signal });
820
962
  }
821
963
 
@@ -830,7 +972,7 @@ function validateWsUrl(raw) {
830
972
  function socket(url, options) {
831
973
  const autoReconnect = options?.autoReconnect ?? false;
832
974
  const reconnectDelay = options?.reconnectDelay ?? 1e3;
833
- const maxReconnects = options?.maxReconnects ?? Infinity;
975
+ const maxReconnects = options?.maxReconnects ?? 10;
834
976
  const heartbeat = options?.heartbeat;
835
977
  const protocols = options?.protocols;
836
978
  const [data, setData] = signal(null);
@@ -840,6 +982,7 @@ function socket(url, options) {
840
982
  let reconnectTimer = null;
841
983
  let heartbeatTimer = null;
842
984
  let disposed = false;
985
+ let manuallyClosed = false;
843
986
  function getUrl() {
844
987
  return typeof url === "function" ? url() : url;
845
988
  }
@@ -863,11 +1006,18 @@ function socket(url, options) {
863
1006
  ws.onclose = () => {
864
1007
  setStatus("closed");
865
1008
  stopHeartbeat();
866
- if (autoReconnect && !disposed && reconnectCount < maxReconnects) {
1009
+ const wasManual = manuallyClosed;
1010
+ manuallyClosed = false;
1011
+ if (autoReconnect && !disposed && !wasManual && reconnectCount < maxReconnects) {
1012
+ const cap = 3e4;
1013
+ const delay = Math.min(cap, reconnectDelay * 2 ** reconnectCount);
1014
+ const jittered = delay * (0.5 + Math.random() * 0.5);
867
1015
  reconnectCount++;
868
1016
  reconnectTimer = setTimeout(() => {
1017
+ reconnectTimer = null;
1018
+ if (disposed || manuallyClosed) return;
869
1019
  connect();
870
- }, reconnectDelay);
1020
+ }, jittered);
871
1021
  }
872
1022
  };
873
1023
  ws.onerror = () => {
@@ -894,6 +1044,7 @@ function socket(url, options) {
894
1044
  }
895
1045
  }
896
1046
  function close() {
1047
+ manuallyClosed = true;
897
1048
  if (reconnectTimer !== null) {
898
1049
  clearTimeout(reconnectTimer);
899
1050
  reconnectTimer = null;
@@ -920,12 +1071,16 @@ function validateSseUrl(raw) {
920
1071
  }
921
1072
  function stream(url, options) {
922
1073
  const autoReconnect = options?.autoReconnect ?? false;
1074
+ const maxReconnects = options?.maxReconnects ?? 10;
1075
+ const baseMs = options?.reconnectBaseMs ?? 1e3;
1076
+ const maxMs = options?.reconnectMaxMs ?? 3e4;
923
1077
  const [data, setData] = signal(null);
924
1078
  const [event, setEvent] = signal(null);
925
1079
  const [status, setStatus] = signal("connecting");
926
1080
  let source = null;
927
1081
  let disposed = false;
928
1082
  let reconnectTimer = null;
1083
+ let attempts = 0;
929
1084
  function connect() {
930
1085
  if (disposed) return;
931
1086
  const safeUrl = validateSseUrl(url);
@@ -939,6 +1094,7 @@ function stream(url, options) {
939
1094
  });
940
1095
  source.onopen = () => {
941
1096
  setStatus("open");
1097
+ attempts = 0;
942
1098
  };
943
1099
  source.onmessage = (evt) => {
944
1100
  setData(evt.data);
@@ -948,11 +1104,14 @@ function stream(url, options) {
948
1104
  if (source && source.readyState === EventSource.CLOSED) {
949
1105
  setStatus("closed");
950
1106
  source = null;
951
- if (autoReconnect && !disposed) {
1107
+ if (autoReconnect && !disposed && attempts < maxReconnects) {
1108
+ const delay = Math.min(maxMs, baseMs * 2 ** attempts);
1109
+ const jittered = delay * (0.5 + Math.random() * 0.5);
1110
+ attempts++;
952
1111
  reconnectTimer = setTimeout(() => {
953
1112
  reconnectTimer = null;
954
1113
  connect();
955
- }, 1e3);
1114
+ }, jittered);
956
1115
  }
957
1116
  }
958
1117
  };
@@ -984,6 +1143,7 @@ export {
984
1143
  getQueryData,
985
1144
  setQueryData,
986
1145
  clearQueryCache,
1146
+ __resetQueryCache,
987
1147
  mutation,
988
1148
  infiniteQuery,
989
1149
  previous,