@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 CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@bunbase-ae/react-sdk",
3
- "version": "1.0.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 || e.status !== "success") return true;
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, { ...entry, staleAt: 0, promise: null });
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, { ...entry, staleAt: 0, promise: null });
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 isStale = entry.status === "error" || Date.now() >= entry.staleAt;
398
- if (isStale && !entry.promise) {
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
@@ -170,5 +170,6 @@ export function useAuth<T>(selector?: (s: UseAuthResult) => T): UseAuthResult |
170
170
  return useSyncExternalStore(
171
171
  useCallback((fn) => client.auth.subscribeSnapshot(fn), [client]),
172
172
  getSnapshot,
173
+ getSnapshot,
173
174
  ) as UseAuthResult | T;
174
175
  }