sibujs 1.5.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.
- package/dist/browser.cjs +238 -69
- package/dist/browser.d.cts +5 -0
- package/dist/browser.d.ts +5 -0
- package/dist/browser.js +6 -6
- package/dist/build.cjs +916 -292
- package/dist/build.js +15 -13
- package/dist/cdn.global.js +17 -16
- package/dist/chunk-2RA7SHDA.js +65 -0
- package/dist/chunk-2UPRY23K.js +80 -0
- package/dist/chunk-3JHCYHWN.js +125 -0
- package/dist/{chunk-VAPYJN4X.js → chunk-3LR7GLWQ.js} +93 -23
- package/dist/{chunk-RJ46C3CS.js → chunk-3NSGB5JN.js} +71 -20
- package/dist/{chunk-XUEEGU5O.js → chunk-52YJLLRO.js} +16 -4
- package/dist/{chunk-XHK6BDAJ.js → chunk-54EDRCEF.js} +25 -8
- package/dist/chunk-7JDB7I65.js +1327 -0
- package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
- package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
- package/dist/{chunk-BGN5ZMP4.js → chunk-GTBNNBJ6.js} +14 -2
- package/dist/chunk-HB24TBAF.js +121 -0
- package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
- package/dist/{chunk-BGTHZHJ5.js → chunk-JA6667UN.js} +188 -44
- package/dist/{chunk-7GRNSCFT.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-SFKNRVCU.js → chunk-KLRMB5ZS.js} +135 -79
- package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
- package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
- package/dist/{chunk-BMPL52BF.js → chunk-MIUAXB7K.js} +118 -66
- package/dist/{chunk-JCDUJN2F.js → chunk-ND2664SF.js} +486 -153
- package/dist/{chunk-VQDZK23A.js → chunk-O2MNQFLP.js} +181 -66
- package/dist/{chunk-NHUC2QWH.js → chunk-R73P76YZ.js} +1 -1
- package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
- package/dist/chunk-UCS6AMJ7.js +79 -0
- package/dist/{chunk-K4G4ZQNR.js → chunk-VLPPXTYG.js} +84 -38
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- package/dist/{customElement-BL3Uo8dL.d.cts → customElement-CPfIrbvg.d.cts} +14 -10
- package/dist/{customElement-BL3Uo8dL.d.ts → customElement-CPfIrbvg.d.ts} +14 -10
- package/dist/data.cjs +410 -99
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +513 -223
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +12 -6
- package/dist/ecosystem.cjs +475 -144
- package/dist/ecosystem.d.cts +9 -7
- package/dist/ecosystem.d.ts +9 -7
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3355 -1541
- package/dist/extras.d.cts +9 -9
- package/dist/extras.d.ts +9 -9
- package/dist/extras.js +58 -45
- package/dist/index.cjs +920 -292
- package/dist/index.d.cts +71 -8
- package/dist/index.d.ts +71 -8
- package/dist/index.js +28 -16
- package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
- package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
- package/dist/motion.cjs +77 -34
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +335 -69
- package/dist/patterns.d.cts +11 -12
- package/dist/patterns.d.ts +11 -12
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +279 -108
- package/dist/performance.d.cts +23 -16
- package/dist/performance.d.ts +23 -16
- package/dist/performance.js +13 -8
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +635 -260
- package/dist/plugins.d.cts +10 -3
- package/dist/plugins.d.ts +10 -3
- package/dist/plugins.js +106 -38
- package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
- package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
- package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
- package/dist/ssr.cjs +642 -222
- package/dist/ssr.d.cts +26 -6
- package/dist/ssr.d.ts +26 -6
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.ts} +9 -1
- package/dist/testing.cjs +252 -63
- package/dist/testing.d.cts +17 -4
- package/dist/testing.d.ts +17 -4
- package/dist/testing.js +100 -44
- package/dist/ui.cjs +463 -137
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +977 -94
- package/dist/widgets.d.cts +104 -2
- package/dist/widgets.d.ts +104 -2
- package/dist/widgets.js +9 -7
- package/package.json +8 -2
- package/dist/chunk-32DY64NT.js +0 -282
- package/dist/chunk-3AIRKM3B.js +0 -1263
- package/dist/chunk-3ARAQO7B.js +0 -398
- package/dist/chunk-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-5ZYQ6KDD.js +0 -154
- package/dist/chunk-6BMPXPUW.js +0 -26
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- package/dist/chunk-77L6NL3X.js +0 -1097
- package/dist/chunk-7BF6TK55.js +0 -1097
- package/dist/chunk-7TQKR4PP.js +0 -294
- package/dist/chunk-7V26P53V.js +0 -712
- package/dist/chunk-AZ3ISID5.js +0 -298
- package/dist/chunk-B7SWRFUT.js +0 -332
- package/dist/chunk-BTU3TJDS.js +0 -365
- package/dist/chunk-BW3WT46K.js +0 -937
- package/dist/chunk-C6KFWOFV.js +0 -616
- package/dist/chunk-CHF5OHIA.js +0 -61
- package/dist/chunk-CHJ27IGK.js +0 -26
- package/dist/chunk-CMBFNA7L.js +0 -27
- package/dist/chunk-DAHRH4ON.js +0 -331
- package/dist/chunk-DKOHBI74.js +0 -924
- package/dist/chunk-DTCOOBMX.js +0 -725
- package/dist/chunk-EBGIRKQY.js +0 -616
- package/dist/chunk-EUZND3CB.js +0 -27
- package/dist/chunk-EVCZO745.js +0 -365
- package/dist/chunk-EWFVA3TJ.js +0 -282
- package/dist/chunk-F3FA4F32.js +0 -292
- package/dist/chunk-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-GJPXRJ45.js +0 -37
- package/dist/chunk-HGMJFBC7.js +0 -654
- package/dist/chunk-JAKHTMQU.js +0 -1000
- package/dist/chunk-JCI5M6U6.js +0 -956
- package/dist/chunk-K5ZUMYVS.js +0 -89
- package/dist/chunk-KQPDEVVS.js +0 -398
- package/dist/chunk-L6JRBDNS.js +0 -60
- package/dist/chunk-LA6KQEDU.js +0 -712
- package/dist/chunk-MB6QFH3I.js +0 -2776
- package/dist/chunk-MDVXJWFN.js +0 -304
- package/dist/chunk-MEZVEBPN.js +0 -2008
- package/dist/chunk-MK4ERFYL.js +0 -2249
- package/dist/chunk-MLKGABMK.js +0 -9
- package/dist/chunk-MQ5GOYPH.js +0 -2249
- package/dist/chunk-MYRV7VDM.js +0 -742
- package/dist/chunk-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-NZIIMDWI.js +0 -84
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P3XWXJZU.js +0 -282
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.js +0 -616
- package/dist/chunk-PDZQY43A.js +0 -616
- package/dist/chunk-PTQJDMRT.js +0 -146
- package/dist/chunk-PZEGYCF5.js +0 -61
- package/dist/chunk-QBMDLBU2.js +0 -975
- package/dist/chunk-QWZG56ET.js +0 -2744
- package/dist/chunk-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TDGZL5CU.js +0 -365
- package/dist/chunk-TNQWPPE6.js +0 -37
- package/dist/chunk-TSOKIX5Z.js +0 -654
- package/dist/chunk-UHNL42EF.js +0 -2730
- package/dist/chunk-UNXCEF6S.js +0 -21
- package/dist/chunk-V2XTI523.js +0 -347
- package/dist/chunk-VAU366PN.js +0 -2241
- package/dist/chunk-VMVDTCXB.js +0 -712
- package/dist/chunk-VQNQZCWJ.js +0 -61
- package/dist/chunk-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- package/dist/chunk-WR5D4EGH.js +0 -26
- package/dist/chunk-WUHJISPP.js +0 -298
- package/dist/chunk-XYU6TZOW.js +0 -182
- package/dist/chunk-Y6GP4QGG.js +0 -276
- package/dist/chunk-YECR7UIA.js +0 -347
- package/dist/chunk-YUTWTI4B.js +0 -654
- package/dist/chunk-Z65KYU7I.js +0 -26
- package/dist/chunk-Z6POF5YC.js +0 -975
- package/dist/chunk-ZBJP6WFL.js +0 -482
- package/dist/chunk-ZD6OAMTH.js +0 -277
- package/dist/chunk-ZWKZCBO6.js +0 -317
- package/dist/contracts-DDrwxvJ-.d.cts +0 -245
- package/dist/contracts-DDrwxvJ-.d.ts +0 -245
- package/dist/contracts-DOrhwbke.d.cts +0 -245
- package/dist/contracts-DOrhwbke.d.ts +0 -245
- package/dist/contracts-xo5ckdRP.d.cts +0 -240
- package/dist/contracts-xo5ckdRP.d.ts +0 -240
- package/dist/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- package/dist/customElement-D2DJp_xn.d.cts +0 -313
- package/dist/customElement-D2DJp_xn.d.ts +0 -313
- package/dist/customElement-yz8uyk-0.d.cts +0 -308
- package/dist/customElement-yz8uyk-0.d.ts +0 -308
- package/dist/introspect-Cb0zgpi2.d.cts +0 -477
- package/dist/introspect-Y2xNXGSf.d.ts +0 -477
- package/dist/plugin-Bek4RhJY.d.cts +0 -43
- package/dist/plugin-Bek4RhJY.d.ts +0 -43
- package/dist/ssr-3RXHP5ES.js +0 -38
- package/dist/ssr-6GIMY5MX.js +0 -38
- package/dist/ssr-BA6sxxUd.d.cts +0 -135
- package/dist/ssr-BA6sxxUd.d.ts +0 -135
- package/dist/ssr-WKUPVSSK.js +0 -36
- package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
- package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
package/dist/data.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// data.ts
|
|
21
21
|
var data_exports = {};
|
|
22
22
|
__export(data_exports, {
|
|
23
|
+
__resetQueryCache: () => __resetQueryCache,
|
|
23
24
|
calculateDelay: () => calculateDelay,
|
|
24
25
|
clearQueryCache: () => clearQueryCache,
|
|
25
26
|
debounce: () => debounce,
|
|
@@ -50,12 +51,12 @@ function isDev() {
|
|
|
50
51
|
var _isDev = isDev();
|
|
51
52
|
function devAssert(condition, message) {
|
|
52
53
|
if (_isDev && !condition) {
|
|
53
|
-
throw new Error(`[
|
|
54
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
function devWarn(message) {
|
|
57
58
|
if (_isDev) {
|
|
58
|
-
console.warn(`[
|
|
59
|
+
console.warn(`[SibuJS] ${message}`);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -65,11 +66,11 @@ var subscriberStack = new Array(32);
|
|
|
65
66
|
var stackCapacity = 32;
|
|
66
67
|
var stackTop = -1;
|
|
67
68
|
var currentSubscriber = null;
|
|
68
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
69
69
|
var SUBS = "__s";
|
|
70
70
|
var notifyDepth = 0;
|
|
71
71
|
var pendingQueue = [];
|
|
72
72
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
73
|
+
var propagateStack = [];
|
|
73
74
|
function safeInvoke(sub) {
|
|
74
75
|
try {
|
|
75
76
|
sub();
|
|
@@ -78,6 +79,15 @@ function safeInvoke(sub) {
|
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
var trackingSuspended = false;
|
|
82
|
+
function retrack(effectFn, subscriber) {
|
|
83
|
+
const prev = currentSubscriber;
|
|
84
|
+
currentSubscriber = subscriber;
|
|
85
|
+
try {
|
|
86
|
+
effectFn();
|
|
87
|
+
} finally {
|
|
88
|
+
currentSubscriber = prev;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
81
91
|
function track(effectFn, subscriber) {
|
|
82
92
|
if (!subscriber) subscriber = effectFn;
|
|
83
93
|
cleanup(subscriber);
|
|
@@ -116,7 +126,6 @@ function recordDependency(signal2) {
|
|
|
116
126
|
let subs = signal2[SUBS];
|
|
117
127
|
if (!subs) {
|
|
118
128
|
subs = /* @__PURE__ */ new Set();
|
|
119
|
-
signalSubscribers.set(signal2, subs);
|
|
120
129
|
signal2[SUBS] = subs;
|
|
121
130
|
}
|
|
122
131
|
subs.add(currentSubscriber);
|
|
@@ -138,17 +147,17 @@ function queueSignalNotification(signal2) {
|
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
}
|
|
141
|
-
var
|
|
150
|
+
var maxDrainIterations = 1e5;
|
|
142
151
|
function drainNotificationQueue() {
|
|
143
152
|
if (notifyDepth > 0) return;
|
|
144
153
|
notifyDepth++;
|
|
145
154
|
try {
|
|
146
155
|
let i = 0;
|
|
147
156
|
while (i < pendingQueue.length) {
|
|
148
|
-
if (i >=
|
|
157
|
+
if (i >= maxDrainIterations) {
|
|
149
158
|
if (typeof console !== "undefined") {
|
|
150
159
|
console.error(
|
|
151
|
-
`[SibuJS] Notification queue exceeded ${
|
|
160
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
152
161
|
);
|
|
153
162
|
}
|
|
154
163
|
break;
|
|
@@ -157,47 +166,52 @@ function drainNotificationQueue() {
|
|
|
157
166
|
i++;
|
|
158
167
|
}
|
|
159
168
|
} finally {
|
|
160
|
-
pendingQueue.length = 0;
|
|
161
|
-
pendingSet.clear();
|
|
162
169
|
notifyDepth--;
|
|
170
|
+
if (notifyDepth === 0) {
|
|
171
|
+
pendingQueue.length = 0;
|
|
172
|
+
pendingSet.clear();
|
|
173
|
+
}
|
|
163
174
|
}
|
|
164
175
|
}
|
|
165
176
|
function propagateDirty(sub) {
|
|
166
177
|
sub();
|
|
167
|
-
|
|
168
|
-
|
|
178
|
+
const rootSig = sub._sig;
|
|
179
|
+
if (!rootSig) return;
|
|
180
|
+
const stack = propagateStack;
|
|
181
|
+
const baseLen = stack.length;
|
|
182
|
+
stack.push(rootSig);
|
|
183
|
+
while (stack.length > baseLen) {
|
|
184
|
+
const sig = stack.pop();
|
|
169
185
|
const first = sig.__f;
|
|
170
186
|
if (first) {
|
|
171
187
|
if (first._c) {
|
|
172
188
|
const nSig = first._sig;
|
|
173
|
-
nSig._d
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (!pendingSet.has(first)) {
|
|
189
|
+
if (!nSig._d) {
|
|
190
|
+
nSig._d = true;
|
|
191
|
+
stack.push(nSig);
|
|
192
|
+
}
|
|
193
|
+
} else if (!pendingSet.has(first)) {
|
|
178
194
|
pendingSet.add(first);
|
|
179
195
|
pendingQueue.push(first);
|
|
180
196
|
}
|
|
181
|
-
|
|
197
|
+
continue;
|
|
182
198
|
}
|
|
183
199
|
const subs = sig[SUBS];
|
|
184
|
-
if (!subs)
|
|
185
|
-
let nextSig;
|
|
200
|
+
if (!subs) continue;
|
|
186
201
|
for (const s of subs) {
|
|
187
202
|
if (s._c) {
|
|
188
|
-
s();
|
|
189
203
|
const nSig = s._sig;
|
|
190
|
-
if (nSig && !
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
204
|
+
if (nSig && !nSig._d) {
|
|
205
|
+
nSig._d = true;
|
|
206
|
+
stack.push(nSig);
|
|
207
|
+
} else if (!nSig) {
|
|
208
|
+
s();
|
|
194
209
|
}
|
|
195
210
|
} else if (!pendingSet.has(s)) {
|
|
196
211
|
pendingSet.add(s);
|
|
197
212
|
pendingQueue.push(s);
|
|
198
213
|
}
|
|
199
214
|
}
|
|
200
|
-
sig = nextSig;
|
|
201
215
|
}
|
|
202
216
|
}
|
|
203
217
|
function notifySubscribers(signal2) {
|
|
@@ -221,13 +235,23 @@ function notifySubscribers(signal2) {
|
|
|
221
235
|
}
|
|
222
236
|
let i = 0;
|
|
223
237
|
while (i < pendingQueue.length) {
|
|
238
|
+
if (i >= maxDrainIterations) {
|
|
239
|
+
if (typeof console !== "undefined") {
|
|
240
|
+
console.error(
|
|
241
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
224
246
|
safeInvoke(pendingQueue[i]);
|
|
225
247
|
i++;
|
|
226
248
|
}
|
|
227
249
|
} finally {
|
|
228
|
-
pendingQueue.length = 0;
|
|
229
|
-
pendingSet.clear();
|
|
230
250
|
notifyDepth--;
|
|
251
|
+
if (notifyDepth === 0) {
|
|
252
|
+
pendingQueue.length = 0;
|
|
253
|
+
pendingSet.clear();
|
|
254
|
+
}
|
|
231
255
|
}
|
|
232
256
|
return;
|
|
233
257
|
}
|
|
@@ -247,30 +271,48 @@ function notifySubscribers(signal2) {
|
|
|
247
271
|
notifyDepth++;
|
|
248
272
|
try {
|
|
249
273
|
let directCount = 0;
|
|
274
|
+
let hasComputedSub = false;
|
|
250
275
|
for (const sub of subs) {
|
|
276
|
+
if (sub._c) hasComputedSub = true;
|
|
251
277
|
pendingQueue[directCount++] = sub;
|
|
252
278
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
279
|
+
if (!hasComputedSub) {
|
|
280
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
281
|
+
safeInvoke(pendingQueue[i2]);
|
|
256
282
|
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
283
|
+
} else {
|
|
284
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
285
|
+
if (pendingQueue[i2]._c) {
|
|
286
|
+
propagateDirty(pendingQueue[i2]);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
290
|
+
const sub = pendingQueue[i2];
|
|
291
|
+
if (!sub._c && !pendingSet.has(sub)) {
|
|
292
|
+
pendingSet.add(sub);
|
|
293
|
+
safeInvoke(sub);
|
|
262
294
|
}
|
|
263
295
|
}
|
|
264
296
|
}
|
|
265
297
|
let i = directCount;
|
|
266
298
|
while (i < pendingQueue.length) {
|
|
299
|
+
if (i - directCount >= maxDrainIterations) {
|
|
300
|
+
if (typeof console !== "undefined") {
|
|
301
|
+
console.error(
|
|
302
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
267
307
|
safeInvoke(pendingQueue[i]);
|
|
268
308
|
i++;
|
|
269
309
|
}
|
|
270
310
|
} finally {
|
|
271
|
-
pendingQueue.length = 0;
|
|
272
|
-
pendingSet.clear();
|
|
273
311
|
notifyDepth--;
|
|
312
|
+
if (notifyDepth === 0) {
|
|
313
|
+
pendingQueue.length = 0;
|
|
314
|
+
pendingSet.clear();
|
|
315
|
+
}
|
|
274
316
|
}
|
|
275
317
|
}
|
|
276
318
|
function cleanup(subscriber) {
|
|
@@ -281,7 +323,9 @@ function cleanup(subscriber) {
|
|
|
281
323
|
if (subs) {
|
|
282
324
|
subs.delete(subscriber);
|
|
283
325
|
if (singleDep.__f === subscriber) {
|
|
284
|
-
singleDep.__f = void 0;
|
|
326
|
+
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
327
|
+
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
328
|
+
singleDep.__f = subs.values().next().value;
|
|
285
329
|
}
|
|
286
330
|
}
|
|
287
331
|
sub._dep = void 0;
|
|
@@ -294,7 +338,9 @@ function cleanup(subscriber) {
|
|
|
294
338
|
if (subs) {
|
|
295
339
|
subs.delete(subscriber);
|
|
296
340
|
if (signal2.__f === subscriber) {
|
|
297
|
-
signal2.__f = void 0;
|
|
341
|
+
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
342
|
+
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
343
|
+
signal2.__f = subs.values().next().value;
|
|
298
344
|
}
|
|
299
345
|
}
|
|
300
346
|
}
|
|
@@ -305,6 +351,7 @@ function cleanup(subscriber) {
|
|
|
305
351
|
function derived(getter, options) {
|
|
306
352
|
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
307
353
|
const debugName = options?.name;
|
|
354
|
+
const equals = options?.equals;
|
|
308
355
|
const cs = {};
|
|
309
356
|
cs._d = false;
|
|
310
357
|
cs._g = getter;
|
|
@@ -315,8 +362,14 @@ function derived(getter, options) {
|
|
|
315
362
|
markDirty._c = 1;
|
|
316
363
|
markDirty._sig = cs;
|
|
317
364
|
track(() => {
|
|
318
|
-
|
|
319
|
-
|
|
365
|
+
let threw = true;
|
|
366
|
+
try {
|
|
367
|
+
cs._v = getter();
|
|
368
|
+
cs._d = false;
|
|
369
|
+
threw = false;
|
|
370
|
+
} finally {
|
|
371
|
+
if (threw) cs._d = true;
|
|
372
|
+
}
|
|
320
373
|
}, markDirty);
|
|
321
374
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
322
375
|
let evaluating = false;
|
|
@@ -329,11 +382,16 @@ function derived(getter, options) {
|
|
|
329
382
|
if (trackingSuspended) {
|
|
330
383
|
if (cs._d) {
|
|
331
384
|
evaluating = true;
|
|
385
|
+
let threw = true;
|
|
332
386
|
try {
|
|
333
|
-
|
|
334
|
-
|
|
387
|
+
retrack(() => {
|
|
388
|
+
cs._v = getter();
|
|
389
|
+
cs._d = false;
|
|
390
|
+
threw = false;
|
|
391
|
+
}, markDirty);
|
|
335
392
|
} finally {
|
|
336
393
|
evaluating = false;
|
|
394
|
+
if (threw) cs._d = true;
|
|
337
395
|
}
|
|
338
396
|
}
|
|
339
397
|
return cs._v;
|
|
@@ -342,13 +400,17 @@ function derived(getter, options) {
|
|
|
342
400
|
if (cs._d) {
|
|
343
401
|
const oldValue = cs._v;
|
|
344
402
|
evaluating = true;
|
|
403
|
+
let threw = true;
|
|
345
404
|
try {
|
|
346
|
-
|
|
405
|
+
retrack(() => {
|
|
406
|
+
const next = getter();
|
|
407
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
347
408
|
cs._d = false;
|
|
348
|
-
|
|
409
|
+
threw = false;
|
|
349
410
|
}, markDirty);
|
|
350
411
|
} finally {
|
|
351
412
|
evaluating = false;
|
|
413
|
+
if (threw) cs._d = true;
|
|
352
414
|
}
|
|
353
415
|
if (hook && oldValue !== cs._v) {
|
|
354
416
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
@@ -366,9 +428,28 @@ function derived(getter, options) {
|
|
|
366
428
|
}
|
|
367
429
|
|
|
368
430
|
// src/core/ssr-context.ts
|
|
369
|
-
var
|
|
431
|
+
var als = null;
|
|
432
|
+
try {
|
|
433
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
434
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
435
|
+
if (req) {
|
|
436
|
+
const mod = req("node:async_hooks");
|
|
437
|
+
als = new mod.AsyncLocalStorage();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
} catch {
|
|
441
|
+
als = null;
|
|
442
|
+
}
|
|
443
|
+
var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
444
|
+
function getSSRStore() {
|
|
445
|
+
if (als) {
|
|
446
|
+
const s = als.getStore();
|
|
447
|
+
if (s) return s;
|
|
448
|
+
}
|
|
449
|
+
return fallbackStore;
|
|
450
|
+
}
|
|
370
451
|
function isSSR() {
|
|
371
|
-
return
|
|
452
|
+
return getSSRStore().ssr;
|
|
372
453
|
}
|
|
373
454
|
|
|
374
455
|
// src/core/signals/effect.ts
|
|
@@ -378,26 +459,86 @@ function effect(effectFn, options) {
|
|
|
378
459
|
if (isSSR()) return () => {
|
|
379
460
|
};
|
|
380
461
|
const onError = options?.onError;
|
|
462
|
+
let userCleanups = [];
|
|
463
|
+
const onCleanup = (fn) => {
|
|
464
|
+
userCleanups.push(fn);
|
|
465
|
+
};
|
|
466
|
+
const runUserCleanups = () => {
|
|
467
|
+
if (userCleanups.length === 0) return;
|
|
468
|
+
const list = userCleanups;
|
|
469
|
+
userCleanups = [];
|
|
470
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
471
|
+
try {
|
|
472
|
+
list[i]();
|
|
473
|
+
} catch (err) {
|
|
474
|
+
if (typeof console !== "undefined") {
|
|
475
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
const invokeBody = () => effectFn(onCleanup);
|
|
381
481
|
const wrappedFn = onError ? () => {
|
|
382
482
|
try {
|
|
383
|
-
|
|
483
|
+
invokeBody();
|
|
384
484
|
} catch (err) {
|
|
385
485
|
onError(err);
|
|
386
486
|
}
|
|
387
|
-
} :
|
|
487
|
+
} : invokeBody;
|
|
388
488
|
let cleanupHandle = () => {
|
|
389
489
|
};
|
|
490
|
+
let running = false;
|
|
390
491
|
const subscriber = () => {
|
|
391
|
-
|
|
392
|
-
|
|
492
|
+
if (running) {
|
|
493
|
+
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
494
|
+
console.warn(
|
|
495
|
+
"[SibuJS] effect re-entered itself while running \u2014 the triggering update will be ignored. Wrap mutual writes in `batch()` or split the effect to avoid this."
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
running = true;
|
|
501
|
+
try {
|
|
502
|
+
runUserCleanups();
|
|
503
|
+
cleanupHandle();
|
|
504
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
505
|
+
} finally {
|
|
506
|
+
running = false;
|
|
507
|
+
}
|
|
393
508
|
};
|
|
394
|
-
|
|
509
|
+
running = true;
|
|
510
|
+
try {
|
|
511
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
512
|
+
} finally {
|
|
513
|
+
running = false;
|
|
514
|
+
}
|
|
395
515
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
396
516
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
517
|
+
let disposed = false;
|
|
397
518
|
return () => {
|
|
519
|
+
if (disposed) return;
|
|
520
|
+
disposed = true;
|
|
398
521
|
const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
399
|
-
if (h)
|
|
400
|
-
|
|
522
|
+
if (h) {
|
|
523
|
+
try {
|
|
524
|
+
h.emit("effect:destroy", { effectFn });
|
|
525
|
+
} catch {
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
try {
|
|
529
|
+
runUserCleanups();
|
|
530
|
+
} catch (err) {
|
|
531
|
+
if (typeof console !== "undefined") {
|
|
532
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
cleanupHandle();
|
|
537
|
+
} catch (err) {
|
|
538
|
+
if (typeof console !== "undefined") {
|
|
539
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
401
542
|
};
|
|
402
543
|
}
|
|
403
544
|
|
|
@@ -421,10 +562,13 @@ function enqueueBatchedSignal(signal2) {
|
|
|
421
562
|
return true;
|
|
422
563
|
}
|
|
423
564
|
function flushBatch() {
|
|
424
|
-
|
|
425
|
-
|
|
565
|
+
try {
|
|
566
|
+
for (const signal2 of pendingSignals) {
|
|
567
|
+
queueSignalNotification(signal2);
|
|
568
|
+
}
|
|
569
|
+
} finally {
|
|
570
|
+
pendingSignals.clear();
|
|
426
571
|
}
|
|
427
|
-
pendingSignals.clear();
|
|
428
572
|
drainNotificationQueue();
|
|
429
573
|
}
|
|
430
574
|
|
|
@@ -481,10 +625,12 @@ function calculateDelay(attempt, strategy, baseDelay, maxDelay, jitter) {
|
|
|
481
625
|
break;
|
|
482
626
|
}
|
|
483
627
|
delay = Math.min(delay, maxDelay);
|
|
628
|
+
if (!Number.isFinite(delay)) delay = Number.MAX_SAFE_INTEGER;
|
|
484
629
|
if (jitter > 0) {
|
|
485
630
|
const jitterRange = delay * jitter;
|
|
486
631
|
delay += (Math.random() * 2 - 1) * jitterRange;
|
|
487
632
|
}
|
|
633
|
+
if (!Number.isFinite(delay) || Number.isNaN(delay)) delay = 0;
|
|
488
634
|
return Math.max(0, delay);
|
|
489
635
|
}
|
|
490
636
|
async function withRetry(fn, options, onRetry, signal2) {
|
|
@@ -498,6 +644,7 @@ async function withRetry(fn, options, onRetry, signal2) {
|
|
|
498
644
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
499
645
|
if (signal2?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
500
646
|
try {
|
|
647
|
+
if (signal2?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
501
648
|
return await fn();
|
|
502
649
|
} catch (error) {
|
|
503
650
|
lastError = error;
|
|
@@ -579,24 +726,46 @@ function query(key, fetcher, options = {}) {
|
|
|
579
726
|
let entry = queryCache.get(key2);
|
|
580
727
|
if (!entry) {
|
|
581
728
|
entry = getOrCreateEntry(key2);
|
|
582
|
-
entry.subscribers++;
|
|
583
729
|
entry.listeners.add(onCacheUpdate);
|
|
584
730
|
entry.refetchers.add(doFetch);
|
|
585
731
|
}
|
|
586
732
|
if (entry.promise) {
|
|
587
733
|
setIsFetching(true);
|
|
734
|
+
const captured = entry.promise;
|
|
588
735
|
try {
|
|
589
|
-
await
|
|
736
|
+
await captured;
|
|
737
|
+
if (disposed || currentKey !== key2) return;
|
|
738
|
+
if (entry.promise === captured) {
|
|
739
|
+
onCacheUpdate();
|
|
740
|
+
if (entry.error) onError?.(entry.error);
|
|
741
|
+
else if (entry.data !== void 0) onSuccess?.(entry.data);
|
|
742
|
+
}
|
|
590
743
|
} catch {
|
|
744
|
+
if (disposed || currentKey !== key2) return;
|
|
745
|
+
if (entry.promise === captured) {
|
|
746
|
+
onCacheUpdate();
|
|
747
|
+
if (entry.error) onError?.(entry.error);
|
|
748
|
+
}
|
|
749
|
+
} finally {
|
|
750
|
+
if (!disposed && currentKey === key2) onSettled?.();
|
|
591
751
|
}
|
|
592
|
-
onCacheUpdate();
|
|
593
752
|
return;
|
|
594
753
|
}
|
|
595
754
|
abortController?.abort();
|
|
596
755
|
abortController = new AbortController();
|
|
597
756
|
const signal2 = abortController.signal;
|
|
598
757
|
setIsFetching(true);
|
|
599
|
-
|
|
758
|
+
let promise;
|
|
759
|
+
try {
|
|
760
|
+
promise = withRetry(() => fetcher({ signal: signal2, key: key2 }), retryOptions, void 0, signal2);
|
|
761
|
+
} catch (err) {
|
|
762
|
+
setIsFetching(false);
|
|
763
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
764
|
+
entry.error = errorObj;
|
|
765
|
+
onError?.(errorObj);
|
|
766
|
+
onSettled?.();
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
600
769
|
entry.promise = promise;
|
|
601
770
|
try {
|
|
602
771
|
const result = await promise;
|
|
@@ -658,6 +827,7 @@ function query(key, fetcher, options = {}) {
|
|
|
658
827
|
oldEntry.subscribers--;
|
|
659
828
|
if (oldEntry.subscribers <= 0 && cacheTime >= 0) {
|
|
660
829
|
const oldKey = currentKey;
|
|
830
|
+
if (oldEntry.gcTimer !== null) clearTimeout(oldEntry.gcTimer);
|
|
661
831
|
oldEntry.gcTimer = setTimeout(() => queryCache.delete(oldKey), cacheTime);
|
|
662
832
|
}
|
|
663
833
|
}
|
|
@@ -665,7 +835,7 @@ function query(key, fetcher, options = {}) {
|
|
|
665
835
|
const keyChanged = currentKey !== key2;
|
|
666
836
|
currentKey = key2;
|
|
667
837
|
const entry = getOrCreateEntry(key2, initialData);
|
|
668
|
-
if (keyChanged
|
|
838
|
+
if (keyChanged) entry.subscribers++;
|
|
669
839
|
if (entry.gcTimer !== null) {
|
|
670
840
|
clearTimeout(entry.gcTimer);
|
|
671
841
|
entry.gcTimer = null;
|
|
@@ -680,6 +850,11 @@ function query(key, fetcher, options = {}) {
|
|
|
680
850
|
setError(entry.error);
|
|
681
851
|
});
|
|
682
852
|
}
|
|
853
|
+
if (!keyChanged && currentKey === key2 && entry.data !== void 0) {
|
|
854
|
+
const isDataStale2 = entry.dataUpdatedAt === 0 || Date.now() - entry.dataUpdatedAt >= staleTime;
|
|
855
|
+
if (enabled && isDataStale2 && !entry.promise) doFetch();
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
683
858
|
const isDataStale = entry.dataUpdatedAt === 0 || Date.now() - entry.dataUpdatedAt >= staleTime;
|
|
684
859
|
if (enabled && (entry.data === void 0 || isDataStale)) {
|
|
685
860
|
doFetch();
|
|
@@ -707,6 +882,7 @@ function query(key, fetcher, options = {}) {
|
|
|
707
882
|
}
|
|
708
883
|
}
|
|
709
884
|
function dispose() {
|
|
885
|
+
if (disposed) return;
|
|
710
886
|
disposed = true;
|
|
711
887
|
abortController?.abort();
|
|
712
888
|
effectCleanup();
|
|
@@ -719,12 +895,17 @@ function query(key, fetcher, options = {}) {
|
|
|
719
895
|
entry.subscribers--;
|
|
720
896
|
if (entry.subscribers <= 0 && cacheTime >= 0) {
|
|
721
897
|
const key2 = currentKey;
|
|
898
|
+
if (entry.gcTimer !== null) clearTimeout(entry.gcTimer);
|
|
722
899
|
entry.gcTimer = setTimeout(() => queryCache.delete(key2), cacheTime);
|
|
723
900
|
}
|
|
724
901
|
}
|
|
725
902
|
}
|
|
726
|
-
if (focusHandler
|
|
727
|
-
|
|
903
|
+
if (focusHandler && typeof globalThis.removeEventListener === "function") {
|
|
904
|
+
globalThis.removeEventListener("focus", focusHandler);
|
|
905
|
+
}
|
|
906
|
+
if (onlineHandler && typeof globalThis.removeEventListener === "function") {
|
|
907
|
+
globalThis.removeEventListener("online", onlineHandler);
|
|
908
|
+
}
|
|
728
909
|
}
|
|
729
910
|
return {
|
|
730
911
|
data,
|
|
@@ -768,7 +949,19 @@ function clearQueryCache() {
|
|
|
768
949
|
}
|
|
769
950
|
queryCache.clear();
|
|
770
951
|
for (const listener of activeListeners) listener();
|
|
771
|
-
for (const refetcher of activeRefetchers)
|
|
952
|
+
for (const refetcher of activeRefetchers) {
|
|
953
|
+
refetcher().catch((err) => {
|
|
954
|
+
if (typeof console !== "undefined") {
|
|
955
|
+
console.warn("[SibuJS query] refetch after clearQueryCache failed:", err);
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
function __resetQueryCache() {
|
|
961
|
+
for (const entry of queryCache.values()) {
|
|
962
|
+
if (entry.gcTimer) clearTimeout(entry.gcTimer);
|
|
963
|
+
}
|
|
964
|
+
queryCache.clear();
|
|
772
965
|
}
|
|
773
966
|
|
|
774
967
|
// src/data/mutation.ts
|
|
@@ -831,7 +1024,10 @@ function mutation(mutationFn, options = {}) {
|
|
|
831
1024
|
isSuccess,
|
|
832
1025
|
isIdle,
|
|
833
1026
|
mutate: (variables) => {
|
|
834
|
-
execute(variables).catch(() => {
|
|
1027
|
+
execute(variables).catch((err) => {
|
|
1028
|
+
if (typeof console !== "undefined") {
|
|
1029
|
+
console.warn("[SibuJS mutation] mutate() failed; check `.error()` signal or onError option.", err);
|
|
1030
|
+
}
|
|
835
1031
|
});
|
|
836
1032
|
},
|
|
837
1033
|
mutateAsync: execute,
|
|
@@ -867,11 +1063,13 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
867
1063
|
const hasPreviousPage = derived(() => prevPageParam() !== void 0);
|
|
868
1064
|
let abortController = null;
|
|
869
1065
|
let disposed = false;
|
|
1066
|
+
let runId = 0;
|
|
870
1067
|
async function fetchPage(pageParam, direction) {
|
|
871
1068
|
if (disposed) return;
|
|
872
1069
|
abortController?.abort();
|
|
873
1070
|
abortController = new AbortController();
|
|
874
1071
|
const signal2 = abortController.signal;
|
|
1072
|
+
const myRun = ++runId;
|
|
875
1073
|
batch(() => {
|
|
876
1074
|
setIsFetching(true);
|
|
877
1075
|
if (direction === "next") setIsFetchingNext(true);
|
|
@@ -880,7 +1078,7 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
880
1078
|
});
|
|
881
1079
|
try {
|
|
882
1080
|
const page = await withRetry(() => fetcher({ signal: signal2, pageParam }), retryOptions, void 0, signal2);
|
|
883
|
-
if (disposed) return;
|
|
1081
|
+
if (disposed || myRun !== runId) return;
|
|
884
1082
|
const currentPages = pages();
|
|
885
1083
|
let newPages;
|
|
886
1084
|
if (direction === "prev") {
|
|
@@ -900,7 +1098,7 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
900
1098
|
});
|
|
901
1099
|
onSuccess?.(newPages);
|
|
902
1100
|
} catch (err) {
|
|
903
|
-
if (disposed) return;
|
|
1101
|
+
if (disposed || myRun !== runId) return;
|
|
904
1102
|
if (err instanceof DOMException && err.name === "AbortError") return;
|
|
905
1103
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
906
1104
|
batch(() => {
|
|
@@ -915,9 +1113,12 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
915
1113
|
const effectCleanup = effect(() => {
|
|
916
1114
|
resolveKey();
|
|
917
1115
|
if (enabled) {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1116
|
+
abortController?.abort();
|
|
1117
|
+
batch(() => {
|
|
1118
|
+
setPages([]);
|
|
1119
|
+
setNextPageParam(initialPageParam);
|
|
1120
|
+
setPrevPageParam(void 0);
|
|
1121
|
+
});
|
|
921
1122
|
fetchPage(initialPageParam, "initial");
|
|
922
1123
|
}
|
|
923
1124
|
});
|
|
@@ -1154,18 +1355,57 @@ function idbPut(db, store, item) {
|
|
|
1154
1355
|
tx.onerror = () => reject(tx.error);
|
|
1155
1356
|
});
|
|
1156
1357
|
}
|
|
1157
|
-
function
|
|
1358
|
+
function idbPutWithChange(db, item, change) {
|
|
1359
|
+
return new Promise((resolve, reject) => {
|
|
1360
|
+
const tx = db.transaction(["items", "_changes"], "readwrite");
|
|
1361
|
+
tx.objectStore("items").put(item);
|
|
1362
|
+
tx.objectStore("_changes").put(change);
|
|
1363
|
+
tx.oncomplete = () => resolve();
|
|
1364
|
+
tx.onerror = () => reject(tx.error);
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
function idbDeleteWithChange(db, key, change) {
|
|
1368
|
+
return new Promise((resolve, reject) => {
|
|
1369
|
+
const tx = db.transaction(["items", "_changes"], "readwrite");
|
|
1370
|
+
tx.objectStore("items").delete(key);
|
|
1371
|
+
tx.objectStore("_changes").put(change);
|
|
1372
|
+
tx.oncomplete = () => resolve();
|
|
1373
|
+
tx.onerror = () => reject(tx.error);
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
function idbGetAllWithKeys(db, store) {
|
|
1377
|
+
return new Promise((resolve, reject) => {
|
|
1378
|
+
const tx = db.transaction(store, "readonly");
|
|
1379
|
+
const out = [];
|
|
1380
|
+
const req = tx.objectStore(store).openCursor();
|
|
1381
|
+
req.onsuccess = () => {
|
|
1382
|
+
const cursor = req.result;
|
|
1383
|
+
if (cursor) {
|
|
1384
|
+
out.push({ key: cursor.primaryKey, value: cursor.value });
|
|
1385
|
+
cursor.continue();
|
|
1386
|
+
} else {
|
|
1387
|
+
resolve(out);
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
req.onerror = () => reject(req.error);
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
function idbDeleteKeys(db, store, keys) {
|
|
1394
|
+
if (keys.length === 0) return Promise.resolve();
|
|
1158
1395
|
return new Promise((resolve, reject) => {
|
|
1159
1396
|
const tx = db.transaction(store, "readwrite");
|
|
1160
|
-
tx.objectStore(store)
|
|
1397
|
+
const objStore = tx.objectStore(store);
|
|
1398
|
+
for (const k of keys) objStore.delete(k);
|
|
1161
1399
|
tx.oncomplete = () => resolve();
|
|
1162
1400
|
tx.onerror = () => reject(tx.error);
|
|
1163
1401
|
});
|
|
1164
1402
|
}
|
|
1165
|
-
function
|
|
1403
|
+
function idbPutMany(db, store, items) {
|
|
1404
|
+
if (items.length === 0) return Promise.resolve();
|
|
1166
1405
|
return new Promise((resolve, reject) => {
|
|
1167
1406
|
const tx = db.transaction(store, "readwrite");
|
|
1168
|
-
tx.objectStore(store)
|
|
1407
|
+
const objStore = tx.objectStore(store);
|
|
1408
|
+
for (const item of items) objStore.put(item);
|
|
1169
1409
|
tx.oncomplete = () => resolve();
|
|
1170
1410
|
tx.onerror = () => reject(tx.error);
|
|
1171
1411
|
});
|
|
@@ -1188,15 +1428,13 @@ async function offlineStore(options) {
|
|
|
1188
1428
|
setPendingCount(changes.length);
|
|
1189
1429
|
}
|
|
1190
1430
|
async function put(item) {
|
|
1191
|
-
await
|
|
1192
|
-
await idbPut(db, "_changes", { type: "put", item, timestamp: Date.now() });
|
|
1431
|
+
await idbPutWithChange(db, item, { type: "put", item, timestamp: Date.now() });
|
|
1193
1432
|
await refreshData();
|
|
1194
1433
|
}
|
|
1195
1434
|
async function remove(key) {
|
|
1196
1435
|
const existing = await idbGet(db, "items", key);
|
|
1197
1436
|
if (existing) {
|
|
1198
|
-
await
|
|
1199
|
-
await idbPut(db, "_changes", { type: "delete", item: existing, timestamp: Date.now() });
|
|
1437
|
+
await idbDeleteWithChange(db, key, { type: "delete", item: existing, timestamp: Date.now() });
|
|
1200
1438
|
await refreshData();
|
|
1201
1439
|
}
|
|
1202
1440
|
}
|
|
@@ -1207,25 +1445,45 @@ async function offlineStore(options) {
|
|
|
1207
1445
|
return data().filter(filter);
|
|
1208
1446
|
}
|
|
1209
1447
|
async function sync() {
|
|
1210
|
-
if (!adapter || isSyncing()) return;
|
|
1448
|
+
if (!adapter || isSyncing() || closed) return;
|
|
1211
1449
|
setIsSyncing(true);
|
|
1212
1450
|
try {
|
|
1213
|
-
const
|
|
1214
|
-
if (
|
|
1215
|
-
|
|
1451
|
+
const snapshot = await idbGetAllWithKeys(db, "_changes");
|
|
1452
|
+
if (closed) return;
|
|
1453
|
+
if (snapshot.length > 0) {
|
|
1454
|
+
const result = await adapter.push(snapshot.map((e) => e.value));
|
|
1455
|
+
if (closed) return;
|
|
1216
1456
|
if (result.ok) {
|
|
1217
|
-
await
|
|
1457
|
+
await idbDeleteKeys(
|
|
1458
|
+
db,
|
|
1459
|
+
"_changes",
|
|
1460
|
+
snapshot.map((e) => e.key)
|
|
1461
|
+
);
|
|
1462
|
+
if (closed) return;
|
|
1218
1463
|
}
|
|
1219
1464
|
}
|
|
1220
1465
|
const remoteItems = await adapter.pull(lastSynced());
|
|
1221
|
-
|
|
1222
|
-
|
|
1466
|
+
if (closed) return;
|
|
1467
|
+
const pendingChanges = await idbGetAll(db, "_changes");
|
|
1468
|
+
if (closed) return;
|
|
1469
|
+
const pendingKeys = /* @__PURE__ */ new Set();
|
|
1470
|
+
for (const c of pendingChanges) {
|
|
1471
|
+
const k = c.item[keyPath];
|
|
1472
|
+
if (k != null) pendingKeys.add(k);
|
|
1223
1473
|
}
|
|
1474
|
+
const safeRemote = remoteItems.filter((item) => {
|
|
1475
|
+
const k = item[keyPath];
|
|
1476
|
+
return k == null || !pendingKeys.has(k);
|
|
1477
|
+
});
|
|
1478
|
+
await idbPutMany(db, "items", safeRemote);
|
|
1479
|
+
if (closed) return;
|
|
1224
1480
|
const now = Date.now();
|
|
1225
1481
|
await idbPut(db, "_meta", now);
|
|
1482
|
+
if (closed) return;
|
|
1226
1483
|
setLastSynced(now);
|
|
1227
1484
|
await refreshData();
|
|
1228
|
-
} catch {
|
|
1485
|
+
} catch (err) {
|
|
1486
|
+
if (typeof console !== "undefined") console.warn("[offlineStore] sync failed", err);
|
|
1229
1487
|
} finally {
|
|
1230
1488
|
setIsSyncing(false);
|
|
1231
1489
|
}
|
|
@@ -1233,13 +1491,21 @@ async function offlineStore(options) {
|
|
|
1233
1491
|
function attach(newAdapter) {
|
|
1234
1492
|
adapter = newAdapter;
|
|
1235
1493
|
}
|
|
1494
|
+
let onlineHandler = null;
|
|
1495
|
+
let closed = false;
|
|
1236
1496
|
function close() {
|
|
1497
|
+
closed = true;
|
|
1498
|
+
if (onlineHandler && typeof window !== "undefined") {
|
|
1499
|
+
window.removeEventListener("online", onlineHandler);
|
|
1500
|
+
onlineHandler = null;
|
|
1501
|
+
}
|
|
1237
1502
|
db.close();
|
|
1238
1503
|
}
|
|
1239
1504
|
if (autoSync && typeof window !== "undefined") {
|
|
1240
|
-
|
|
1505
|
+
onlineHandler = () => {
|
|
1241
1506
|
sync();
|
|
1242
|
-
}
|
|
1507
|
+
};
|
|
1508
|
+
window.addEventListener("online", onlineHandler);
|
|
1243
1509
|
}
|
|
1244
1510
|
return {
|
|
1245
1511
|
data,
|
|
@@ -1262,9 +1528,11 @@ function syncAdapter(config) {
|
|
|
1262
1528
|
// src/core/rendering/context.ts
|
|
1263
1529
|
function context(defaultValue) {
|
|
1264
1530
|
const [getValue, setValue] = signal(defaultValue);
|
|
1265
|
-
|
|
1531
|
+
const ctx = {
|
|
1266
1532
|
provide(value) {
|
|
1533
|
+
const previous2 = getValue();
|
|
1267
1534
|
setValue(value);
|
|
1535
|
+
return () => setValue(previous2);
|
|
1268
1536
|
},
|
|
1269
1537
|
use() {
|
|
1270
1538
|
return getValue;
|
|
@@ -1274,8 +1542,18 @@ function context(defaultValue) {
|
|
|
1274
1542
|
},
|
|
1275
1543
|
set(value) {
|
|
1276
1544
|
setValue(value);
|
|
1545
|
+
},
|
|
1546
|
+
withContext(value, fn) {
|
|
1547
|
+
const previous2 = getValue();
|
|
1548
|
+
setValue(value);
|
|
1549
|
+
try {
|
|
1550
|
+
return fn();
|
|
1551
|
+
} finally {
|
|
1552
|
+
setValue(previous2);
|
|
1553
|
+
}
|
|
1277
1554
|
}
|
|
1278
1555
|
};
|
|
1556
|
+
return ctx;
|
|
1279
1557
|
}
|
|
1280
1558
|
|
|
1281
1559
|
// src/data/routeLoader.ts
|
|
@@ -1296,9 +1574,16 @@ function loaderData() {
|
|
|
1296
1574
|
error: resource2.error
|
|
1297
1575
|
};
|
|
1298
1576
|
}
|
|
1299
|
-
async function preloadRoute(route, context2) {
|
|
1577
|
+
async function preloadRoute(route, context2, callerSignal) {
|
|
1300
1578
|
if (!route.loader) return void 0;
|
|
1301
1579
|
const controller = new AbortController();
|
|
1580
|
+
if (callerSignal) {
|
|
1581
|
+
if (callerSignal.aborted) {
|
|
1582
|
+
controller.abort();
|
|
1583
|
+
} else {
|
|
1584
|
+
callerSignal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1302
1587
|
return route.loader(context2, { signal: controller.signal });
|
|
1303
1588
|
}
|
|
1304
1589
|
|
|
@@ -1313,7 +1598,7 @@ function validateWsUrl(raw) {
|
|
|
1313
1598
|
function socket(url, options) {
|
|
1314
1599
|
const autoReconnect = options?.autoReconnect ?? false;
|
|
1315
1600
|
const reconnectDelay = options?.reconnectDelay ?? 1e3;
|
|
1316
|
-
const maxReconnects = options?.maxReconnects ??
|
|
1601
|
+
const maxReconnects = options?.maxReconnects ?? 10;
|
|
1317
1602
|
const heartbeat = options?.heartbeat;
|
|
1318
1603
|
const protocols = options?.protocols;
|
|
1319
1604
|
const [data, setData] = signal(null);
|
|
@@ -1347,13 +1632,19 @@ function socket(url, options) {
|
|
|
1347
1632
|
ws.onclose = () => {
|
|
1348
1633
|
setStatus("closed");
|
|
1349
1634
|
stopHeartbeat();
|
|
1350
|
-
|
|
1635
|
+
const wasManual = manuallyClosed;
|
|
1636
|
+
manuallyClosed = false;
|
|
1637
|
+
if (autoReconnect && !disposed && !wasManual && reconnectCount < maxReconnects) {
|
|
1638
|
+
const cap = 3e4;
|
|
1639
|
+
const delay = Math.min(cap, reconnectDelay * 2 ** reconnectCount);
|
|
1640
|
+
const jittered = delay * (0.5 + Math.random() * 0.5);
|
|
1351
1641
|
reconnectCount++;
|
|
1352
1642
|
reconnectTimer = setTimeout(() => {
|
|
1643
|
+
reconnectTimer = null;
|
|
1644
|
+
if (disposed || manuallyClosed) return;
|
|
1353
1645
|
connect();
|
|
1354
|
-
},
|
|
1646
|
+
}, jittered);
|
|
1355
1647
|
}
|
|
1356
|
-
manuallyClosed = false;
|
|
1357
1648
|
};
|
|
1358
1649
|
ws.onerror = () => {
|
|
1359
1650
|
};
|
|
@@ -1399,13 +1690,24 @@ function socket(url, options) {
|
|
|
1399
1690
|
}
|
|
1400
1691
|
|
|
1401
1692
|
// src/utils/sanitize.ts
|
|
1693
|
+
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
1402
1694
|
function sanitizeUrl(url) {
|
|
1403
1695
|
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
1404
1696
|
if (!trimmed) return "";
|
|
1405
1697
|
const lower = trimmed.toLowerCase();
|
|
1406
|
-
|
|
1407
|
-
|
|
1698
|
+
let schemeEnd = -1;
|
|
1699
|
+
for (let i = 0; i < lower.length; i++) {
|
|
1700
|
+
const ch = lower.charCodeAt(i);
|
|
1701
|
+
if (ch === 58) {
|
|
1702
|
+
schemeEnd = i;
|
|
1703
|
+
break;
|
|
1704
|
+
}
|
|
1705
|
+
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
1408
1706
|
}
|
|
1707
|
+
if (schemeEnd === -1) return trimmed;
|
|
1708
|
+
const scheme = lower.slice(0, schemeEnd + 1);
|
|
1709
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
|
|
1710
|
+
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
1409
1711
|
return trimmed;
|
|
1410
1712
|
}
|
|
1411
1713
|
|
|
@@ -1417,12 +1719,16 @@ function validateSseUrl(raw) {
|
|
|
1417
1719
|
}
|
|
1418
1720
|
function stream(url, options) {
|
|
1419
1721
|
const autoReconnect = options?.autoReconnect ?? false;
|
|
1722
|
+
const maxReconnects = options?.maxReconnects ?? 10;
|
|
1723
|
+
const baseMs = options?.reconnectBaseMs ?? 1e3;
|
|
1724
|
+
const maxMs = options?.reconnectMaxMs ?? 3e4;
|
|
1420
1725
|
const [data, setData] = signal(null);
|
|
1421
1726
|
const [event, setEvent] = signal(null);
|
|
1422
1727
|
const [status, setStatus] = signal("connecting");
|
|
1423
1728
|
let source = null;
|
|
1424
1729
|
let disposed = false;
|
|
1425
1730
|
let reconnectTimer = null;
|
|
1731
|
+
let attempts = 0;
|
|
1426
1732
|
function connect() {
|
|
1427
1733
|
if (disposed) return;
|
|
1428
1734
|
const safeUrl = validateSseUrl(url);
|
|
@@ -1436,6 +1742,7 @@ function stream(url, options) {
|
|
|
1436
1742
|
});
|
|
1437
1743
|
source.onopen = () => {
|
|
1438
1744
|
setStatus("open");
|
|
1745
|
+
attempts = 0;
|
|
1439
1746
|
};
|
|
1440
1747
|
source.onmessage = (evt) => {
|
|
1441
1748
|
setData(evt.data);
|
|
@@ -1445,11 +1752,14 @@ function stream(url, options) {
|
|
|
1445
1752
|
if (source && source.readyState === EventSource.CLOSED) {
|
|
1446
1753
|
setStatus("closed");
|
|
1447
1754
|
source = null;
|
|
1448
|
-
if (autoReconnect && !disposed) {
|
|
1755
|
+
if (autoReconnect && !disposed && attempts < maxReconnects) {
|
|
1756
|
+
const delay = Math.min(maxMs, baseMs * 2 ** attempts);
|
|
1757
|
+
const jittered = delay * (0.5 + Math.random() * 0.5);
|
|
1758
|
+
attempts++;
|
|
1449
1759
|
reconnectTimer = setTimeout(() => {
|
|
1450
1760
|
reconnectTimer = null;
|
|
1451
1761
|
connect();
|
|
1452
|
-
},
|
|
1762
|
+
}, jittered);
|
|
1453
1763
|
}
|
|
1454
1764
|
}
|
|
1455
1765
|
};
|
|
@@ -1474,6 +1784,7 @@ function stream(url, options) {
|
|
|
1474
1784
|
}
|
|
1475
1785
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1476
1786
|
0 && (module.exports = {
|
|
1787
|
+
__resetQueryCache,
|
|
1477
1788
|
calculateDelay,
|
|
1478
1789
|
clearQueryCache,
|
|
1479
1790
|
debounce,
|