sibujs 4.4.0 → 4.6.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 (112) hide show
  1. package/README.md +11 -0
  2. package/dist/browser.cjs +339 -130
  3. package/dist/browser.d.cts +61 -16
  4. package/dist/browser.d.ts +61 -16
  5. package/dist/browser.js +8 -6
  6. package/dist/build.cjs +273 -82
  7. package/dist/build.js +15 -16
  8. package/dist/cdn.dev.global.js +12 -12
  9. package/dist/cdn.full.dev.global.js +11 -11
  10. package/dist/cdn.full.global.js +10 -10
  11. package/dist/cdn.global.js +12 -12
  12. package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
  13. package/dist/chunk-3ISI6ACU.js +44 -0
  14. package/dist/{chunk-VCTAEPSB.js → chunk-47M47FOM.js} +11 -3
  15. package/dist/chunk-5HZXGZ6T.js +24 -0
  16. package/dist/{chunk-KKLW7YWL.js → chunk-5MT6SJ3P.js} +275 -144
  17. package/dist/{chunk-3BTTCZ5J.js → chunk-5Q4R7HCL.js} +42 -4
  18. package/dist/{chunk-ADM46X22.js → chunk-7GQCWFOE.js} +157 -61
  19. package/dist/{chunk-4Z3SPQ67.js → chunk-7NCARGJW.js} +16 -8
  20. package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
  21. package/dist/{chunk-LQFGQNMV.js → chunk-AIF3Z2T7.js} +302 -39
  22. package/dist/{chunk-UCALUKB5.js → chunk-BAAG6ZTI.js} +98 -29
  23. package/dist/{chunk-NVNJH22U.js → chunk-D33YTSX5.js} +2 -2
  24. package/dist/{chunk-M2F7TZHH.js → chunk-DKGBBKOF.js} +136 -80
  25. package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
  26. package/dist/{chunk-HFCOH2GN.js → chunk-HYXDKS4N.js} +153 -110
  27. package/dist/chunk-J6FW5TV6.js +233 -0
  28. package/dist/{chunk-36S2YPP4.js → chunk-JSXPZCET.js} +1 -1
  29. package/dist/chunk-NYNYSPK7.js +318 -0
  30. package/dist/{chunk-HQSEH5F6.js → chunk-ORMZXBKQ.js} +108 -45
  31. package/dist/{chunk-LYVUX7NT.js → chunk-OXUY2A6L.js} +287 -130
  32. package/dist/{chunk-6GSIXTWX.js → chunk-PK6FK2G2.js} +187 -66
  33. package/dist/{chunk-W2EQ7X2L.js → chunk-QE4TTDU3.js} +47 -9
  34. package/dist/{chunk-XLO7SLIX.js → chunk-SXXVZMKZ.js} +262 -70
  35. package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
  36. package/dist/{chunk-RR7M3FHM.js → chunk-UZQ6ALFS.js} +3 -3
  37. package/dist/{chunk-PNIRUQ4C.js → chunk-VVWPJ543.js} +6 -8
  38. package/dist/{chunk-7GIHSAWB.js → chunk-XC4MEKGA.js} +3 -3
  39. package/dist/{chunk-SKPTERHP.js → chunk-XRRZKZYX.js} +55 -31
  40. package/dist/{contracts-DBdg9J_a.d.cts → contracts-DRIuclVT.d.cts} +10 -2
  41. package/dist/{contracts-DBdg9J_a.d.ts → contracts-DRIuclVT.d.ts} +10 -2
  42. package/dist/{customElement-CNZxEB9G.d.ts → customElement-MmInOW1U.d.cts} +59 -10
  43. package/dist/{customElement-CNZxEB9G.d.cts → customElement-MmInOW1U.d.ts} +59 -10
  44. package/dist/data.cjs +293 -125
  45. package/dist/data.d.cts +47 -9
  46. package/dist/data.d.ts +47 -9
  47. package/dist/data.js +12 -9
  48. package/dist/devtools.cjs +121 -58
  49. package/dist/devtools.js +7 -8
  50. package/dist/dispose-GEIG2KOF.js +28 -0
  51. package/dist/ecosystem.cjs +391 -112
  52. package/dist/ecosystem.d.cts +31 -7
  53. package/dist/ecosystem.d.ts +31 -7
  54. package/dist/ecosystem.js +12 -12
  55. package/dist/extras.cjs +2250 -879
  56. package/dist/extras.d.cts +10 -9
  57. package/dist/extras.d.ts +10 -9
  58. package/dist/extras.js +39 -28
  59. package/dist/index.cjs +273 -82
  60. package/dist/index.d.cts +44 -154
  61. package/dist/index.d.ts +44 -154
  62. package/dist/index.js +24 -27
  63. package/dist/motion.cjs +137 -42
  64. package/dist/motion.js +5 -5
  65. package/dist/patterns.cjs +397 -48
  66. package/dist/patterns.d.cts +32 -9
  67. package/dist/patterns.d.ts +32 -9
  68. package/dist/patterns.js +8 -8
  69. package/dist/performance.cjs +338 -217
  70. package/dist/performance.d.cts +2 -2
  71. package/dist/performance.d.ts +2 -2
  72. package/dist/performance.js +8 -9
  73. package/dist/plugin-DVgSnTfK.d.cts +112 -0
  74. package/dist/plugin-DVgSnTfK.d.ts +112 -0
  75. package/dist/plugins.cjs +587 -203
  76. package/dist/plugins.d.cts +3 -3
  77. package/dist/plugins.d.ts +3 -3
  78. package/dist/plugins.js +35 -23
  79. package/dist/signal-EotCj4hS.d.cts +110 -0
  80. package/dist/signal-EotCj4hS.d.ts +110 -0
  81. package/dist/{ssr-BiPRdZ6n.d.cts → ssr-Bli9XRW5.d.cts} +5 -0
  82. package/dist/{ssr-BiPRdZ6n.d.ts → ssr-Bli9XRW5.d.ts} +5 -0
  83. package/dist/{ssr-Y7XOEPEN.js → ssr-XOTUASDO.js} +4 -5
  84. package/dist/ssr.cjs +214 -73
  85. package/dist/ssr.d.cts +9 -3
  86. package/dist/ssr.d.ts +9 -3
  87. package/dist/ssr.js +11 -12
  88. package/dist/{startup-BMpaiMhP.d.ts → startup-BLfSeL15.d.cts} +73 -22
  89. package/dist/{startup-BMpaiMhP.d.cts → startup-BLfSeL15.d.ts} +73 -22
  90. package/dist/tagFactory-DFstCLQV.d.cts +117 -0
  91. package/dist/tagFactory-DkaNVUNV.d.ts +117 -0
  92. package/dist/testing.cjs +2481 -2153
  93. package/dist/testing.d.cts +56 -5
  94. package/dist/testing.d.ts +56 -5
  95. package/dist/testing.js +580 -307
  96. package/dist/ui.cjs +798 -328
  97. package/dist/ui.d.cts +40 -7
  98. package/dist/ui.d.ts +40 -7
  99. package/dist/ui.js +151 -56
  100. package/dist/widgets.cjs +319 -285
  101. package/dist/widgets.js +9 -10
  102. package/package.json +2 -2
  103. package/dist/chunk-2WLZ6757.js +0 -149
  104. package/dist/chunk-7NBDXVHS.js +0 -60
  105. package/dist/chunk-CCSJMTRN.js +0 -15
  106. package/dist/chunk-QKRPLZ2V.js +0 -108
  107. package/dist/chunk-WWV3SJ3L.js +0 -131
  108. package/dist/dispose-46BOMMQJ.js +0 -19
  109. package/dist/plugin-D30wlGW5.d.cts +0 -71
  110. package/dist/plugin-D30wlGW5.d.ts +0 -71
  111. package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
  112. package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
@@ -1,25 +1,25 @@
1
- import {
2
- context
3
- } from "./chunk-7NBDXVHS.js";
4
1
  import {
5
2
  derived
6
- } from "./chunk-W2EQ7X2L.js";
3
+ } from "./chunk-QE4TTDU3.js";
7
4
  import {
8
5
  sanitizeUrl
9
- } from "./chunk-IXKSNWV5.js";
6
+ } from "./chunk-2INLLLMZ.js";
10
7
  import {
11
8
  globalSingleton
12
9
  } from "./chunk-7ZHH77QA.js";
13
10
  import {
14
11
  effect
15
- } from "./chunk-7GIHSAWB.js";
12
+ } from "./chunk-XC4MEKGA.js";
16
13
  import {
17
14
  getRequestScopedCache
18
- } from "./chunk-5DXA2J44.js";
15
+ } from "./chunk-7XHATCIH.js";
19
16
  import {
20
17
  batch,
21
18
  signal
22
- } from "./chunk-NVNJH22U.js";
19
+ } from "./chunk-D33YTSX5.js";
20
+ import {
21
+ reportError
22
+ } from "./chunk-NYNYSPK7.js";
23
23
 
24
24
  // src/data/abort.ts
25
25
  function isAbortError(error) {
@@ -389,6 +389,8 @@ function query(key, fetcher, options = {}) {
389
389
  if (disposed) return;
390
390
  disposed = true;
391
391
  effectCleanup();
392
+ loading.dispose();
393
+ isStale.dispose();
392
394
  if (intervalTimer) clearInterval(intervalTimer);
393
395
  detachFromEntry();
394
396
  if (focusHandler && typeof globalThis.removeEventListener === "function") {
@@ -474,7 +476,7 @@ function mutation(mutationFn, options = {}) {
474
476
  abortController = new AbortController();
475
477
  const signal2 = abortController.signal;
476
478
  const myRun = ++runId;
477
- let context2;
479
+ let context;
478
480
  batch(() => {
479
481
  setLoading(true);
480
482
  setError(void 0);
@@ -482,7 +484,7 @@ function mutation(mutationFn, options = {}) {
482
484
  });
483
485
  try {
484
486
  if (options.onMutate) {
485
- context2 = await options.onMutate(variables);
487
+ context = await options.onMutate(variables);
486
488
  }
487
489
  const result = await withRetry(() => mutationFn(variables, signal2), options.retry, void 0, signal2);
488
490
  if (myRun !== runId) return result;
@@ -493,8 +495,8 @@ function mutation(mutationFn, options = {}) {
493
495
  setLoading(false);
494
496
  setStatus("success");
495
497
  });
496
- runCallback("mutation onSuccess", () => options.onSuccess?.(result, variables, context2));
497
- runCallback("mutation onSettled", () => options.onSettled?.(result, void 0, variables, context2));
498
+ runCallback("mutation onSuccess", () => options.onSuccess?.(result, variables, context));
499
+ runCallback("mutation onSettled", () => options.onSettled?.(result, void 0, variables, context));
498
500
  return result;
499
501
  } catch (err) {
500
502
  if (isAbortError(err)) {
@@ -516,8 +518,8 @@ function mutation(mutationFn, options = {}) {
516
518
  setLoading(false);
517
519
  setStatus("error");
518
520
  });
519
- runCallback("mutation onError", () => options.onError?.(errorObj, variables, context2));
520
- runCallback("mutation onSettled", () => options.onSettled?.(void 0, errorObj, variables, context2));
521
+ runCallback("mutation onError", () => options.onError?.(errorObj, variables, context));
522
+ runCallback("mutation onSettled", () => options.onSettled?.(void 0, errorObj, variables, context));
521
523
  throw errorObj;
522
524
  }
523
525
  }
@@ -655,18 +657,21 @@ function infiniteQuery(key, fetcher, options) {
655
657
  }
656
658
  });
657
659
  function fetchNextPage() {
660
+ if (disposed) return Promise.resolve();
658
661
  if (inFlight) return inFlight;
659
662
  const param = nextPageParam();
660
663
  if (param === void 0) return Promise.resolve();
661
664
  return fetchPage(param, "next");
662
665
  }
663
666
  function fetchPreviousPage() {
667
+ if (disposed) return Promise.resolve();
664
668
  if (inFlight) return inFlight;
665
669
  const param = prevPageParam();
666
670
  if (param === void 0) return Promise.resolve();
667
671
  return fetchPage(param, "prev");
668
672
  }
669
673
  async function refetch() {
674
+ if (disposed) return;
670
675
  batch(() => {
671
676
  setPages([]);
672
677
  setNextPageParam(initialPageParam);
@@ -678,6 +683,10 @@ function infiniteQuery(key, fetcher, options) {
678
683
  disposed = true;
679
684
  abortController?.abort();
680
685
  effectCleanup();
686
+ data.dispose();
687
+ loading.dispose();
688
+ hasNextPage.dispose();
689
+ hasPreviousPage.dispose();
681
690
  }
682
691
  return {
683
692
  data,
@@ -746,25 +755,26 @@ function throttle(getter, interval) {
746
755
  let pending = null;
747
756
  let lastEmitted = getter();
748
757
  let timer = null;
758
+ function emit(value) {
759
+ setThrottled(value);
760
+ lastEmitted = value;
761
+ cooldown = true;
762
+ pending = null;
763
+ timer = setTimeout(endWindow, interval);
764
+ }
765
+ function endWindow() {
766
+ timer = null;
767
+ if (pending !== null && !Object.is(pending.value, lastEmitted)) {
768
+ emit(pending.value);
769
+ return;
770
+ }
771
+ pending = null;
772
+ cooldown = false;
773
+ }
749
774
  const stop = effect(() => {
750
775
  const value = getter();
751
776
  if (!cooldown) {
752
- if (!Object.is(value, lastEmitted)) {
753
- setThrottled(value);
754
- lastEmitted = value;
755
- cooldown = true;
756
- pending = null;
757
- timer = setTimeout(() => {
758
- timer = null;
759
- cooldown = false;
760
- if (pending !== null) {
761
- const trailingValue = pending.value;
762
- pending = null;
763
- setThrottled(trailingValue);
764
- lastEmitted = trailingValue;
765
- }
766
- }, interval);
767
- }
777
+ if (!Object.is(value, lastEmitted)) emit(value);
768
778
  } else {
769
779
  pending = { value };
770
780
  }
@@ -838,7 +848,7 @@ function resource(sourceOrFetcher, fetcherOrOptions, maybeOptions) {
838
848
  });
839
849
  runCallback("resource onError", () => options.onError?.(errorObj));
840
850
  } finally {
841
- if (version === fetchVersion) {
851
+ if (!disposed && version === fetchVersion) {
842
852
  runCallback("resource onSettled", () => options.onSettled?.());
843
853
  }
844
854
  }
@@ -1145,15 +1155,54 @@ function syncAdapter(config) {
1145
1155
  }
1146
1156
 
1147
1157
  // src/data/routeLoader.ts
1148
- var LoaderContext = context(null);
1149
- function executeLoader(loader, context2, options) {
1150
- const res = resource(({ signal: signal2 }) => loader(context2, { signal: signal2 }), options);
1151
- LoaderContext.provide(res);
1158
+ var _clientScope = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.routeLoader.v2"), () => ({ stack: [] }));
1159
+ var _disposed = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.routeLoader.disposed.v1"), () => /* @__PURE__ */ new WeakSet());
1160
+ function currentScope() {
1161
+ const cache = getRequestScopedCache("routeLoader");
1162
+ if (!cache) return _clientScope;
1163
+ let scope = cache.get("scope");
1164
+ if (!scope) {
1165
+ scope = { stack: [] };
1166
+ cache.set("scope", scope);
1167
+ }
1168
+ return scope;
1169
+ }
1170
+ function executeLoader(loader, context, options) {
1171
+ const res = resource(({ signal: signal2 }) => loader(context, { signal: signal2 }), options);
1172
+ const disposeResource = res.dispose;
1173
+ res.dispose = () => {
1174
+ _disposed.add(res);
1175
+ disposeResource();
1176
+ };
1152
1177
  return res;
1153
1178
  }
1179
+ function renderWithLoader(loader, render) {
1180
+ if (_disposed.has(loader)) {
1181
+ throw new Error("renderWithLoader: the loader resource has been disposed");
1182
+ }
1183
+ const scope = currentScope();
1184
+ const entry = loader;
1185
+ scope.stack.push(entry);
1186
+ try {
1187
+ return render();
1188
+ } finally {
1189
+ const index = scope.stack.lastIndexOf(entry);
1190
+ if (index !== -1) scope.stack.splice(index, 1);
1191
+ }
1192
+ }
1193
+ function withLoader(loader, context, render, options) {
1194
+ const res = executeLoader(loader, context, options);
1195
+ try {
1196
+ return { view: renderWithLoader(res, render), resource: res };
1197
+ } catch (err) {
1198
+ res.dispose();
1199
+ throw err;
1200
+ }
1201
+ }
1154
1202
  function loaderData() {
1155
- const resource2 = LoaderContext.get();
1156
- if (!resource2) {
1203
+ const scope = currentScope();
1204
+ const resource2 = scope.stack[scope.stack.length - 1];
1205
+ if (!resource2 || _disposed.has(resource2)) {
1157
1206
  throw new Error("loaderData must be used inside a route with a loader");
1158
1207
  }
1159
1208
  return {
@@ -1162,7 +1211,7 @@ function loaderData() {
1162
1211
  error: resource2.error
1163
1212
  };
1164
1213
  }
1165
- async function preloadRoute(route, context2, callerSignal) {
1214
+ async function preloadRoute(route, context, callerSignal) {
1166
1215
  if (!route.loader) return void 0;
1167
1216
  const controller = new AbortController();
1168
1217
  let onAbort = null;
@@ -1175,7 +1224,7 @@ async function preloadRoute(route, context2, callerSignal) {
1175
1224
  }
1176
1225
  }
1177
1226
  try {
1178
- return await route.loader(context2, { signal: controller.signal });
1227
+ return await route.loader(context, { signal: controller.signal });
1179
1228
  } finally {
1180
1229
  if (onAbort) callerSignal?.removeEventListener("abort", onAbort);
1181
1230
  }
@@ -1203,34 +1252,73 @@ function socket(url, options) {
1203
1252
  let heartbeatTimer = null;
1204
1253
  let disposed = false;
1205
1254
  let manuallyClosed = false;
1255
+ let lifecycle = 0;
1206
1256
  function getUrl() {
1207
1257
  return typeof url === "function" ? url() : url;
1208
1258
  }
1209
1259
  function connect() {
1210
1260
  if (disposed) return;
1261
+ const generation = lifecycle;
1262
+ const invalidated = () => disposed || generation !== lifecycle;
1211
1263
  if (typeof WebSocket === "undefined") {
1212
1264
  setStatus("closed");
1213
1265
  return;
1214
1266
  }
1215
- const safeUrl = validateWsUrl(getUrl());
1267
+ let rawUrl;
1268
+ try {
1269
+ rawUrl = getUrl();
1270
+ } catch (error) {
1271
+ setStatus("closed");
1272
+ reportError(error, { phase: "async", name: "socket" });
1273
+ return;
1274
+ }
1275
+ if (invalidated()) {
1276
+ setStatus("closed");
1277
+ return;
1278
+ }
1279
+ const safeUrl = validateWsUrl(rawUrl);
1216
1280
  if (safeUrl === null) {
1217
1281
  setStatus("closed");
1218
1282
  return;
1219
1283
  }
1220
1284
  setStatus("connecting");
1221
- ws = new WebSocket(safeUrl, protocols);
1222
- ws.onopen = () => {
1285
+ if (invalidated()) {
1286
+ setStatus("closed");
1287
+ return;
1288
+ }
1289
+ let instance;
1290
+ try {
1291
+ instance = new WebSocket(safeUrl, protocols);
1292
+ } catch (error) {
1293
+ setStatus("closed");
1294
+ reportError(error, { phase: "async", name: "socket" });
1295
+ return;
1296
+ }
1297
+ if (invalidated()) {
1298
+ instance.close();
1299
+ setStatus("closed");
1300
+ return;
1301
+ }
1302
+ ws = instance;
1303
+ instance.onopen = () => {
1304
+ if (ws !== instance) return;
1305
+ const openGeneration = lifecycle;
1223
1306
  setStatus("open");
1307
+ if (disposed || openGeneration !== lifecycle || ws !== instance) return;
1224
1308
  reconnectCount = 0;
1225
1309
  startHeartbeat();
1226
1310
  };
1227
- ws.onmessage = (event) => {
1311
+ instance.onmessage = (event) => {
1312
+ if (ws !== instance) return;
1228
1313
  setData(event.data);
1229
1314
  };
1230
- ws.onclose = () => {
1315
+ instance.onclose = () => {
1316
+ if (ws !== instance) return;
1317
+ ws = null;
1318
+ const closeGeneration = lifecycle;
1231
1319
  setStatus("closed");
1232
1320
  stopHeartbeat();
1233
- const wasManual = manuallyClosed;
1321
+ const wasManual = manuallyClosed || closeGeneration !== lifecycle;
1234
1322
  manuallyClosed = false;
1235
1323
  if (autoReconnect && !disposed && !wasManual && reconnectCount < maxReconnects) {
1236
1324
  const cap = 3e4;
@@ -1244,7 +1332,7 @@ function socket(url, options) {
1244
1332
  }, jittered);
1245
1333
  }
1246
1334
  };
1247
- ws.onerror = () => {
1335
+ instance.onerror = () => {
1248
1336
  };
1249
1337
  }
1250
1338
  function startHeartbeat() {
@@ -1268,13 +1356,23 @@ function socket(url, options) {
1268
1356
  }
1269
1357
  }
1270
1358
  function close() {
1359
+ lifecycle++;
1271
1360
  manuallyClosed = true;
1272
1361
  if (reconnectTimer !== null) {
1273
1362
  clearTimeout(reconnectTimer);
1274
1363
  reconnectTimer = null;
1275
1364
  }
1276
1365
  stopHeartbeat();
1277
- if (ws) {
1366
+ if (!ws) {
1367
+ setStatus("closed");
1368
+ return;
1369
+ }
1370
+ if (ws.readyState === WebSocket.CLOSED) {
1371
+ ws = null;
1372
+ setStatus("closed");
1373
+ return;
1374
+ }
1375
+ if (ws.readyState !== WebSocket.CLOSING) {
1278
1376
  setStatus("closing");
1279
1377
  ws.close();
1280
1378
  }
@@ -1305,6 +1403,7 @@ function stream(url, options) {
1305
1403
  let disposed = false;
1306
1404
  let reconnectTimer = null;
1307
1405
  let attempts = 0;
1406
+ let closeGeneration = 0;
1308
1407
  function connect() {
1309
1408
  if (disposed) return;
1310
1409
  if (typeof EventSource === "undefined") {
@@ -1316,44 +1415,64 @@ function stream(url, options) {
1316
1415
  setStatus("closed");
1317
1416
  return;
1318
1417
  }
1418
+ const generation = closeGeneration;
1319
1419
  setStatus("connecting");
1320
- source = new EventSource(safeUrl, {
1420
+ if (disposed || generation !== closeGeneration) return;
1421
+ const instance = new EventSource(safeUrl, {
1321
1422
  withCredentials: options?.withCredentials ?? false
1322
1423
  });
1323
- source.onopen = () => {
1424
+ if (disposed || generation !== closeGeneration) {
1425
+ instance.close();
1426
+ return;
1427
+ }
1428
+ source = instance;
1429
+ const live = () => !disposed && source === instance;
1430
+ instance.onopen = () => {
1431
+ if (!live()) return;
1324
1432
  setStatus("open");
1325
1433
  attempts = 0;
1326
1434
  };
1327
- source.onmessage = (evt) => {
1435
+ instance.onmessage = (evt) => {
1436
+ if (!live()) return;
1328
1437
  setData(evt.data);
1329
1438
  setEvent(evt.type);
1330
1439
  };
1331
- source.onerror = () => {
1332
- if (source && source.readyState === EventSource.CLOSED) {
1333
- setStatus("closed");
1334
- source = null;
1335
- if (autoReconnect && !disposed && attempts < maxReconnects) {
1336
- const delay = Math.min(maxMs, baseMs * 2 ** attempts);
1337
- const jittered = delay * (0.5 + Math.random() * 0.5);
1338
- attempts++;
1339
- reconnectTimer = setTimeout(() => {
1340
- reconnectTimer = null;
1341
- connect();
1342
- }, jittered);
1343
- }
1440
+ instance.onerror = () => {
1441
+ if (!live() || instance.readyState !== EventSource.CLOSED) return;
1442
+ detach(instance);
1443
+ source = null;
1444
+ const generation2 = closeGeneration;
1445
+ setStatus("closed");
1446
+ if (disposed || generation2 !== closeGeneration) return;
1447
+ if (autoReconnect && attempts < maxReconnects) {
1448
+ const delay = Math.min(maxMs, baseMs * 2 ** attempts);
1449
+ const jittered = delay * (0.5 + Math.random() * 0.5);
1450
+ attempts++;
1451
+ reconnectTimer = setTimeout(() => {
1452
+ reconnectTimer = null;
1453
+ connect();
1454
+ }, jittered);
1344
1455
  }
1345
1456
  };
1346
1457
  }
1458
+ function detach(instance) {
1459
+ instance.onopen = null;
1460
+ instance.onmessage = null;
1461
+ instance.onerror = null;
1462
+ }
1347
1463
  function close() {
1464
+ closeGeneration++;
1348
1465
  if (reconnectTimer !== null) {
1349
1466
  clearTimeout(reconnectTimer);
1350
1467
  reconnectTimer = null;
1351
1468
  }
1352
- if (source) {
1353
- source.close();
1354
- setStatus("closed");
1469
+ const instance = source;
1470
+ if (instance) {
1355
1471
  source = null;
1472
+ detach(instance);
1473
+ instance.close();
1356
1474
  }
1475
+ setStatus("closed");
1357
1476
  }
1358
1477
  function dispose() {
1359
1478
  disposed = true;
@@ -1381,6 +1500,8 @@ export {
1381
1500
  offlineStore,
1382
1501
  syncAdapter,
1383
1502
  executeLoader,
1503
+ renderWithLoader,
1504
+ withLoader,
1384
1505
  loaderData,
1385
1506
  preloadRoute,
1386
1507
  socket,
@@ -1,12 +1,13 @@
1
1
  import {
2
+ cleanup,
2
3
  isTrackingSuspended,
3
4
  recordDependency,
4
5
  retrack,
5
6
  track
6
- } from "./chunk-3BTTCZ5J.js";
7
+ } from "./chunk-5Q4R7HCL.js";
7
8
  import {
8
9
  devAssert
9
- } from "./chunk-2WLZ6757.js";
10
+ } from "./chunk-NYNYSPK7.js";
10
11
 
11
12
  // src/core/signals/derived.ts
12
13
  function derived(getter, options) {
@@ -16,10 +17,14 @@ function derived(getter, options) {
16
17
  const cs = {};
17
18
  cs._d = false;
18
19
  cs._init = false;
20
+ cs._f = false;
19
21
  cs._g = getter;
20
22
  cs.__v = 0;
23
+ let evaluating = false;
24
+ let disposed = false;
25
+ let pendingError;
21
26
  const markDirty = () => {
22
- if (cs._d) return;
27
+ if (cs._d || disposed) return;
23
28
  cs._d = true;
24
29
  };
25
30
  markDirty._c = 1;
@@ -42,33 +47,53 @@ function derived(getter, options) {
42
47
  }
43
48
  }, markDirty);
44
49
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
45
- let evaluating = false;
46
50
  const validate = () => {
47
- if (!cs._d) return;
51
+ if (!cs._d || disposed || pendingError !== void 0) return;
48
52
  const oldValue = cs._v;
49
53
  evaluating = true;
50
54
  try {
51
55
  retrack(recompute, markDirty);
52
56
  if (!Object.is(oldValue, cs._v)) cs.__v++;
57
+ } catch (err) {
58
+ pendingError = { error: err };
59
+ cs.__v++;
60
+ if (disposed) cs._d = true;
61
+ else cs._f = true;
53
62
  } finally {
54
63
  evaluating = false;
64
+ if (disposed) cleanup(markDirty);
55
65
  }
56
- if (hook && !Object.is(oldValue, cs._v)) {
66
+ if (hook && !disposed && !Object.is(oldValue, cs._v)) {
57
67
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
58
68
  }
59
69
  };
60
70
  cs._validate = validate;
71
+ const throwPending = () => {
72
+ const { error } = pendingError;
73
+ pendingError = void 0;
74
+ if (disposed) cs._d = false;
75
+ throw error;
76
+ };
61
77
  function computedGetter() {
62
78
  if (evaluating) {
63
79
  throw new Error(
64
80
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
65
81
  );
66
82
  }
67
- if (isTrackingSuspended()) {
68
- if (cs._d) validate();
83
+ if (isTrackingSuspended() || disposed) {
84
+ if (cs._d) {
85
+ validate();
86
+ if (pendingError !== void 0) throwPending();
87
+ }
69
88
  return cs._v;
70
89
  }
71
- if (cs._d) validate();
90
+ if (cs._d) {
91
+ validate();
92
+ if (pendingError !== void 0) {
93
+ recordDependency(cs);
94
+ throwPending();
95
+ }
96
+ }
72
97
  recordDependency(cs);
73
98
  return cs._v;
74
99
  }
@@ -77,6 +102,19 @@ function derived(getter, options) {
77
102
  cs.__name = debugName;
78
103
  }
79
104
  computedGetter.__signal = cs;
105
+ computedGetter.dispose = () => {
106
+ if (disposed) return;
107
+ disposed = true;
108
+ cs._d = pendingError !== void 0;
109
+ cleanup(markDirty);
110
+ const h = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
111
+ if (h) {
112
+ try {
113
+ h.emit("computed:destroy", { signal: cs, getter: computedGetter });
114
+ } catch {
115
+ }
116
+ }
117
+ };
80
118
  if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
81
119
  return computedGetter;
82
120
  }