@bunbase-ae/react-sdk 1.0.0 → 1.0.1-next.2.7e6534b
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/package.json +2 -1
- package/src/cache.ts +41 -5
- package/src/useAuth.ts +1 -0
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bunbase-ae/react-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1-next.2.7e6534b",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React hooks for BunBase — caching, mutations, auth, realtime",
|
|
6
|
+
"homepage": "https://docs-bunbase.palmcode.ae/sdk/react",
|
|
6
7
|
"files": [
|
|
7
8
|
"src"
|
|
8
9
|
],
|
package/src/cache.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface CacheEntry {
|
|
|
24
24
|
/** Stored so focus-triggered refetch can re-run without external reference. */
|
|
25
25
|
fetcher: (() => Promise<unknown>) | null;
|
|
26
26
|
staleTime: number;
|
|
27
|
+
retryableError: boolean;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
// ─── Storage adapter ─────────────────────────────────────────────────────────
|
|
@@ -159,6 +160,7 @@ export class QueryCache {
|
|
|
159
160
|
promise: null,
|
|
160
161
|
fetcher: null,
|
|
161
162
|
staleTime: stored.staleTime,
|
|
163
|
+
retryableError: false,
|
|
162
164
|
});
|
|
163
165
|
} catch {
|
|
164
166
|
// Corrupt entry — skip silently.
|
|
@@ -212,7 +214,9 @@ export class QueryCache {
|
|
|
212
214
|
|
|
213
215
|
isStale(key: string): boolean {
|
|
214
216
|
const e = this.entries.get(key);
|
|
215
|
-
if (!e
|
|
217
|
+
if (!e) return true;
|
|
218
|
+
if (e.status === "error") return false;
|
|
219
|
+
if (e.status !== "success") return true;
|
|
216
220
|
return Date.now() >= e.staleAt;
|
|
217
221
|
}
|
|
218
222
|
|
|
@@ -244,6 +248,7 @@ export class QueryCache {
|
|
|
244
248
|
promise: null,
|
|
245
249
|
fetcher,
|
|
246
250
|
staleTime,
|
|
251
|
+
retryableError: false,
|
|
247
252
|
};
|
|
248
253
|
|
|
249
254
|
const promise: Promise<void> = fetcher().then(
|
|
@@ -259,6 +264,7 @@ export class QueryCache {
|
|
|
259
264
|
promise: null,
|
|
260
265
|
fetcher,
|
|
261
266
|
staleTime,
|
|
267
|
+
retryableError: false,
|
|
262
268
|
};
|
|
263
269
|
this.entries.set(key, next);
|
|
264
270
|
this.persist(key, next);
|
|
@@ -268,6 +274,7 @@ export class QueryCache {
|
|
|
268
274
|
(err: unknown) => {
|
|
269
275
|
const current = this.entries.get(key);
|
|
270
276
|
if (current?.promise !== promise) return;
|
|
277
|
+
const retryableError = isRetryableError(err);
|
|
271
278
|
this.entries.set(key, {
|
|
272
279
|
data: current?.data,
|
|
273
280
|
error: err instanceof Error ? err : new Error(String(err)),
|
|
@@ -276,6 +283,7 @@ export class QueryCache {
|
|
|
276
283
|
promise: null,
|
|
277
284
|
fetcher,
|
|
278
285
|
staleTime,
|
|
286
|
+
retryableError,
|
|
279
287
|
});
|
|
280
288
|
this.notify(key);
|
|
281
289
|
},
|
|
@@ -292,7 +300,14 @@ export class QueryCache {
|
|
|
292
300
|
refetch(key: string): void {
|
|
293
301
|
const entry = this.entries.get(key);
|
|
294
302
|
if (!entry?.fetcher) return;
|
|
295
|
-
this.entries.set(key, {
|
|
303
|
+
this.entries.set(key, {
|
|
304
|
+
...entry,
|
|
305
|
+
error: null,
|
|
306
|
+
status: entry.data !== undefined ? "success" : "loading",
|
|
307
|
+
staleAt: 0,
|
|
308
|
+
promise: null,
|
|
309
|
+
retryableError: false,
|
|
310
|
+
});
|
|
296
311
|
this.fetch(key, entry.fetcher, entry.staleTime);
|
|
297
312
|
}
|
|
298
313
|
|
|
@@ -309,7 +324,19 @@ export class QueryCache {
|
|
|
309
324
|
const toNotify: string[] = [];
|
|
310
325
|
for (const [key, entry] of this.entries) {
|
|
311
326
|
if (key.startsWith(prefix)) {
|
|
312
|
-
this.entries.set(key, {
|
|
327
|
+
this.entries.set(key, {
|
|
328
|
+
...entry,
|
|
329
|
+
error: null,
|
|
330
|
+
status:
|
|
331
|
+
entry.status === "error"
|
|
332
|
+
? entry.data !== undefined
|
|
333
|
+
? "success"
|
|
334
|
+
: "loading"
|
|
335
|
+
: entry.status,
|
|
336
|
+
staleAt: 0,
|
|
337
|
+
promise: null,
|
|
338
|
+
retryableError: false,
|
|
339
|
+
});
|
|
313
340
|
toNotify.push(key);
|
|
314
341
|
}
|
|
315
342
|
}
|
|
@@ -331,6 +358,7 @@ export class QueryCache {
|
|
|
331
358
|
promise: null,
|
|
332
359
|
fetcher: null,
|
|
333
360
|
staleTime,
|
|
361
|
+
retryableError: false,
|
|
334
362
|
};
|
|
335
363
|
this.entries.set(key, entry);
|
|
336
364
|
this.persist(key, entry);
|
|
@@ -354,6 +382,7 @@ export class QueryCache {
|
|
|
354
382
|
promise: null,
|
|
355
383
|
fetcher: existing?.fetcher ?? null,
|
|
356
384
|
staleTime,
|
|
385
|
+
retryableError: false,
|
|
357
386
|
};
|
|
358
387
|
this.entries.set(key, entry);
|
|
359
388
|
this.persist(key, entry);
|
|
@@ -394,10 +423,17 @@ export class QueryCache {
|
|
|
394
423
|
refetchStale(): void {
|
|
395
424
|
for (const [key, entry] of this.entries) {
|
|
396
425
|
if (!entry.fetcher) continue;
|
|
397
|
-
const
|
|
398
|
-
|
|
426
|
+
const shouldRetryError = entry.status === "error" && entry.retryableError;
|
|
427
|
+
const isStale = entry.status === "success" && Date.now() >= entry.staleAt;
|
|
428
|
+
if ((shouldRetryError || isStale) && !entry.promise) {
|
|
399
429
|
this.fetch(key, entry.fetcher, entry.staleTime);
|
|
400
430
|
}
|
|
401
431
|
}
|
|
402
432
|
}
|
|
403
433
|
}
|
|
434
|
+
|
|
435
|
+
function isRetryableError(error: unknown): boolean {
|
|
436
|
+
if (!error || typeof error !== "object" || !("status" in error)) return true;
|
|
437
|
+
const status = (error as { status?: unknown }).status;
|
|
438
|
+
return typeof status !== "number" || status < 400 || status >= 500;
|
|
439
|
+
}
|
package/src/useAuth.ts
CHANGED