@archie/react-sdk 0.2.0 → 0.3.1
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/README.md +25 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.js +103 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -583,6 +583,31 @@ const {
|
|
|
583
583
|
| `markAllAsRead` | `() => Promise<void>` | Mark all loaded notifications read; reconciles `unreadCount` with the server (normally 0) |
|
|
584
584
|
| `refetch` | `() => Promise<void>` | Reload the notification history |
|
|
585
585
|
|
|
586
|
+
#### Infinite scroll
|
|
587
|
+
|
|
588
|
+
`useNotifications` pages backward through history without dropping or duplicating live items:
|
|
589
|
+
|
|
590
|
+
```tsx
|
|
591
|
+
const { notifications, fetchMore, hasMore, isFetchingMore, error } = useNotifications(user.id, {
|
|
592
|
+
limit: 20, // page size for fetchMore()
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
// e.g. an IntersectionObserver on a sentinel at the bottom of the list.
|
|
596
|
+
// Gate on `!error` so a failed page doesn't drive a tight auto-retry loop
|
|
597
|
+
// (the hook also suppresses fetchMore internally after an error until refetch).
|
|
598
|
+
useEffect(() => {
|
|
599
|
+
if (hasMore && !isFetchingMore && !error) void fetchMore();
|
|
600
|
+
}, [hasMore, isFetchingMore, error, fetchMore]);
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
- `fetchMore()` — loads the next older page and appends it (deduped, newest-first). No-op when
|
|
604
|
+
`!hasMore`, a fetch is already in flight, the hook is disabled, or a previous `fetchMore`
|
|
605
|
+
errored (call `refetch()` — or change `receiverId`/`unreadOnly` — to retry).
|
|
606
|
+
- `hasMore` — more older records exist for the active filter.
|
|
607
|
+
- `isFetchingMore` — a `fetchMore()` call is in flight (drive a bottom "loading older" indicator).
|
|
608
|
+
|
|
609
|
+
Changing `receiverId` or `unreadOnly` resets pagination and re-seeds from the first page.
|
|
610
|
+
|
|
586
611
|
**Example — notification bell with unread badge:**
|
|
587
612
|
|
|
588
613
|
```tsx
|
package/dist/index.d.ts
CHANGED
|
@@ -253,6 +253,11 @@ declare function useRestMutation<T = unknown>(path: string, method?: 'POST' | 'P
|
|
|
253
253
|
interface UseNotificationsOptions {
|
|
254
254
|
enabled?: boolean;
|
|
255
255
|
unreadOnly?: boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Page size. Applies to `fetchMore()` (older pages); when omitted, `fetchMore` uses 20.
|
|
258
|
+
* It also caps the initial load (`first: limit`) — so omitting it lets the backend choose the
|
|
259
|
+
* initial page size, meaning the first page and subsequent `fetchMore` pages may differ in size.
|
|
260
|
+
*/
|
|
256
261
|
limit?: number;
|
|
257
262
|
onNotification?: (notification: Notification) => void;
|
|
258
263
|
}
|
|
@@ -266,14 +271,25 @@ interface UseNotificationsReturn {
|
|
|
266
271
|
markAsRead: (id: string) => Promise<void>;
|
|
267
272
|
markAllAsRead: () => Promise<void>;
|
|
268
273
|
refetch: () => Promise<void>;
|
|
274
|
+
/**
|
|
275
|
+
* Load the next older page of history. No-op if `!hasMore`, a fetch is already in flight,
|
|
276
|
+
* disabled, or a previous `fetchMore` errored (call `refetch()` or change the filter to retry).
|
|
277
|
+
*/
|
|
278
|
+
fetchMore: () => Promise<void>;
|
|
279
|
+
/** True while more older history exists for the active filter (the last page did not exhaust it). */
|
|
280
|
+
hasMore: boolean;
|
|
281
|
+
/** True while a fetchMore() call is in flight (drives a "loading older" indicator). */
|
|
282
|
+
isFetchingMore: boolean;
|
|
269
283
|
}
|
|
270
284
|
/**
|
|
271
285
|
* Subscribe to a user's in-app notifications: loads the existing list,
|
|
272
|
-
* then streams new ones live
|
|
286
|
+
* then streams new ones live, and pages backward through history via fetchMore().
|
|
287
|
+
* Returns idiomatic React state.
|
|
273
288
|
*
|
|
274
289
|
* @example
|
|
275
290
|
* ```tsx
|
|
276
|
-
* const { notifications, unreadCount,
|
|
291
|
+
* const { notifications, unreadCount, fetchMore, hasMore, isFetchingMore } =
|
|
292
|
+
* useNotifications(user.id, { limit: 20 });
|
|
277
293
|
* ```
|
|
278
294
|
*/
|
|
279
295
|
declare function useNotifications(receiverId: string, options?: UseNotificationsOptions): UseNotificationsReturn;
|
package/dist/index.js
CHANGED
|
@@ -465,6 +465,11 @@ function useRestMutation(path, method = "POST") {
|
|
|
465
465
|
}, []);
|
|
466
466
|
return { execute, data, error, isLoading, reset };
|
|
467
467
|
}
|
|
468
|
+
var DEFAULT_PAGE_SIZE = 20;
|
|
469
|
+
function idsAt(items, ts) {
|
|
470
|
+
if (ts == null) return [];
|
|
471
|
+
return items.filter((n) => n.createdAt === ts).map((n) => n.id);
|
|
472
|
+
}
|
|
468
473
|
function useNotifications(receiverId, options) {
|
|
469
474
|
const { client } = useArchieContext();
|
|
470
475
|
const [notifications, setNotifications] = useState([]);
|
|
@@ -475,20 +480,59 @@ function useNotifications(receiverId, options) {
|
|
|
475
480
|
const [connectionState, setConnectionState] = useState(
|
|
476
481
|
() => client.realtime.currentState
|
|
477
482
|
);
|
|
483
|
+
const [hasMore, setHasMore] = useState(false);
|
|
484
|
+
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
478
485
|
const enabled = options?.enabled !== false;
|
|
479
486
|
const unreadOnly = options?.unreadOnly ?? false;
|
|
480
487
|
const limit = options?.limit;
|
|
488
|
+
const pageSize = limit ?? DEFAULT_PAGE_SIZE;
|
|
481
489
|
const optionsRef = useRef(options);
|
|
482
490
|
optionsRef.current = options;
|
|
483
491
|
const notificationsRef = useRef([]);
|
|
484
492
|
notificationsRef.current = notifications;
|
|
485
493
|
const seenIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
494
|
+
const oldestCreatedAtRef = useRef(null);
|
|
495
|
+
const boundaryIdsRef = useRef([]);
|
|
496
|
+
const isFetchingMoreRef = useRef(false);
|
|
497
|
+
const paginationErroredRef = useRef(false);
|
|
498
|
+
const hasMoreRef = useRef(false);
|
|
499
|
+
hasMoreRef.current = hasMore;
|
|
500
|
+
const loadTokenRef = useRef(0);
|
|
501
|
+
const invalidateInFlightPagination = useCallback(() => {
|
|
502
|
+
loadTokenRef.current += 1;
|
|
503
|
+
isFetchingMoreRef.current = false;
|
|
504
|
+
paginationErroredRef.current = false;
|
|
505
|
+
setIsFetchingMore(false);
|
|
506
|
+
}, []);
|
|
507
|
+
const seedFromList = useCallback((items, totalCount) => {
|
|
508
|
+
const oldest = items.length > 0 ? items[items.length - 1].createdAt : null;
|
|
509
|
+
oldestCreatedAtRef.current = oldest;
|
|
510
|
+
boundaryIdsRef.current = idsAt(items, oldest);
|
|
511
|
+
setHasMore(items.length < totalCount);
|
|
512
|
+
}, []);
|
|
513
|
+
const mergeAndSeed = useCallback(
|
|
514
|
+
(items, totalCount) => {
|
|
515
|
+
const serverIds = new Set(items.map((n) => n.id));
|
|
516
|
+
const newestSnapshot = items.length > 0 ? items[0].createdAt : null;
|
|
517
|
+
const liveOnly = notificationsRef.current.filter(
|
|
518
|
+
(n) => !serverIds.has(n.id) && (newestSnapshot === null || n.createdAt > newestSnapshot)
|
|
519
|
+
);
|
|
520
|
+
setNotifications([...liveOnly, ...items]);
|
|
521
|
+
seenIdsRef.current = /* @__PURE__ */ new Set([...liveOnly.map((n) => n.id), ...items.map((n) => n.id)]);
|
|
522
|
+
seedFromList(items, totalCount);
|
|
523
|
+
},
|
|
524
|
+
[seedFromList]
|
|
525
|
+
);
|
|
486
526
|
useEffect(() => {
|
|
487
527
|
setNotifications([]);
|
|
488
528
|
setLatest(null);
|
|
489
529
|
setUnreadCount(0);
|
|
490
530
|
seenIdsRef.current = /* @__PURE__ */ new Set();
|
|
491
|
-
|
|
531
|
+
oldestCreatedAtRef.current = null;
|
|
532
|
+
boundaryIdsRef.current = [];
|
|
533
|
+
setHasMore(false);
|
|
534
|
+
invalidateInFlightPagination();
|
|
535
|
+
}, [receiverId, unreadOnly, invalidateInFlightPagination]);
|
|
492
536
|
const load = useCallback(async () => {
|
|
493
537
|
const [listResult, unread] = await Promise.all([
|
|
494
538
|
client.notifications.list(receiverId, { unreadOnly, first: limit }),
|
|
@@ -502,11 +546,11 @@ function useNotifications(receiverId, options) {
|
|
|
502
546
|
return;
|
|
503
547
|
}
|
|
504
548
|
let active = true;
|
|
549
|
+
invalidateInFlightPagination();
|
|
505
550
|
setIsLoading(true);
|
|
506
551
|
load().then(({ listResult, unread }) => {
|
|
507
552
|
if (!active) return;
|
|
508
|
-
|
|
509
|
-
seenIdsRef.current = new Set(listResult.items.map((n) => n.id));
|
|
553
|
+
mergeAndSeed(listResult.items, listResult.totalCount);
|
|
510
554
|
setUnreadCount(unread);
|
|
511
555
|
setError(null);
|
|
512
556
|
}).catch((err) => {
|
|
@@ -517,7 +561,7 @@ function useNotifications(receiverId, options) {
|
|
|
517
561
|
return () => {
|
|
518
562
|
active = false;
|
|
519
563
|
};
|
|
520
|
-
}, [enabled, load]);
|
|
564
|
+
}, [enabled, load, mergeAndSeed, invalidateInFlightPagination]);
|
|
521
565
|
useEffect(() => {
|
|
522
566
|
if (!enabled) return;
|
|
523
567
|
const unsubConnection = client.realtime.onConnectionStateChange(setConnectionState);
|
|
@@ -566,11 +610,11 @@ function useNotifications(receiverId, options) {
|
|
|
566
610
|
}
|
|
567
611
|
}, [client, receiverId]);
|
|
568
612
|
const refetch = useCallback(async () => {
|
|
613
|
+
invalidateInFlightPagination();
|
|
569
614
|
setIsLoading(true);
|
|
570
615
|
try {
|
|
571
616
|
const { listResult, unread } = await load();
|
|
572
|
-
|
|
573
|
-
seenIdsRef.current = new Set(listResult.items.map((n) => n.id));
|
|
617
|
+
mergeAndSeed(listResult.items, listResult.totalCount);
|
|
574
618
|
setUnreadCount(unread);
|
|
575
619
|
setError(null);
|
|
576
620
|
} catch (err) {
|
|
@@ -578,7 +622,55 @@ function useNotifications(receiverId, options) {
|
|
|
578
622
|
} finally {
|
|
579
623
|
setIsLoading(false);
|
|
580
624
|
}
|
|
581
|
-
}, [load]);
|
|
625
|
+
}, [load, mergeAndSeed, invalidateInFlightPagination]);
|
|
626
|
+
const fetchMore = useCallback(async () => {
|
|
627
|
+
if (!enabled || !hasMoreRef.current || isFetchingMoreRef.current || paginationErroredRef.current) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const cursor = oldestCreatedAtRef.current;
|
|
631
|
+
if (cursor == null) return;
|
|
632
|
+
const token = loadTokenRef.current;
|
|
633
|
+
isFetchingMoreRef.current = true;
|
|
634
|
+
setIsFetchingMore(true);
|
|
635
|
+
try {
|
|
636
|
+
const page = await client.notifications.list(receiverId, {
|
|
637
|
+
unreadOnly,
|
|
638
|
+
first: pageSize,
|
|
639
|
+
orderBy: { createdAt: "DESC" },
|
|
640
|
+
createdBefore: cursor,
|
|
641
|
+
// Tie-safe keyset: don't skip rows sharing the cursor timestamp that we haven't loaded yet.
|
|
642
|
+
excludeIds: boundaryIdsRef.current,
|
|
643
|
+
// Page-fill drives hasMore below, so skip the (potentially O(N)) COUNT on deep pages.
|
|
644
|
+
includeTotal: false
|
|
645
|
+
});
|
|
646
|
+
if (loadTokenRef.current !== token) return;
|
|
647
|
+
if (page.items.length === 0) {
|
|
648
|
+
setHasMore(false);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
const fresh = page.items.filter((n) => !seenIdsRef.current.has(n.id));
|
|
652
|
+
fresh.forEach((n) => seenIdsRef.current.add(n.id));
|
|
653
|
+
if (fresh.length > 0) {
|
|
654
|
+
setNotifications((prev) => [...prev, ...fresh]);
|
|
655
|
+
}
|
|
656
|
+
const newOldest = page.items[page.items.length - 1].createdAt;
|
|
657
|
+
const idsAtNewOldest = idsAt(page.items, newOldest);
|
|
658
|
+
boundaryIdsRef.current = newOldest === cursor ? Array.from(/* @__PURE__ */ new Set([...boundaryIdsRef.current, ...idsAtNewOldest])) : idsAtNewOldest;
|
|
659
|
+
oldestCreatedAtRef.current = newOldest;
|
|
660
|
+
setHasMore(page.items.length === pageSize);
|
|
661
|
+
setError(null);
|
|
662
|
+
} catch (err) {
|
|
663
|
+
if (loadTokenRef.current === token) {
|
|
664
|
+
paginationErroredRef.current = true;
|
|
665
|
+
setError(err);
|
|
666
|
+
}
|
|
667
|
+
} finally {
|
|
668
|
+
if (loadTokenRef.current === token) {
|
|
669
|
+
isFetchingMoreRef.current = false;
|
|
670
|
+
setIsFetchingMore(false);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}, [client, receiverId, unreadOnly, pageSize, enabled]);
|
|
582
674
|
return {
|
|
583
675
|
notifications,
|
|
584
676
|
latest,
|
|
@@ -588,7 +680,10 @@ function useNotifications(receiverId, options) {
|
|
|
588
680
|
connectionState,
|
|
589
681
|
markAsRead,
|
|
590
682
|
markAllAsRead,
|
|
591
|
-
refetch
|
|
683
|
+
refetch,
|
|
684
|
+
fetchMore,
|
|
685
|
+
hasMore,
|
|
686
|
+
isFetchingMore
|
|
592
687
|
};
|
|
593
688
|
}
|
|
594
689
|
function AuthGuard({
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/query-cache.ts","../src/provider.tsx","../src/hooks/useArchieClient.ts","../src/hooks/useAuth.ts","../src/hooks/useQuery.ts","../src/hooks/useMutation.ts","../src/hooks/useSubscription.ts","../src/hooks/useFileUpload.ts","../src/hooks/useRest.ts","../src/hooks/useNotifications.ts","../src/components/AuthGuard.tsx"],"names":["React","useMemo","useState","useCallback","useEffect","useRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-memory query cache with in-flight request deduplication and stale-while-revalidate.\n * @internal\n */\n\ninterface CacheEntry<T = unknown> {\n data: T;\n timestamp: number;\n}\n\nexport class QueryCache {\n private cache = new Map<string, CacheEntry>();\n private inflight = new Map<string, Promise<unknown>>();\n private staleTime = 0;\n\n static key(query: string, variables?: Record<string, unknown>): string {\n return `${query}::${variables ? JSON.stringify(variables) : ''}`;\n }\n\n get<T>(key: string): CacheEntry<T> | undefined {\n return this.cache.get(key) as CacheEntry<T> | undefined;\n }\n\n set<T>(key: string, data: T): void {\n this.cache.set(key, { data, timestamp: Date.now() });\n }\n\n isFresh(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n if (this.staleTime === 0) return false;\n return Date.now() - entry.timestamp < this.staleTime;\n }\n\n /**\n * Deduplicate in-flight requests: if an identical fetch is already pending,\n * return the same promise. Otherwise, run `fetcher` and share the promise.\n */\n async dedup<T>(key: string, fetcher: () => Promise<T>): Promise<T> {\n const existing = this.inflight.get(key);\n if (existing) return existing as Promise<T>;\n\n const promise = fetcher().finally(() => {\n this.inflight.delete(key);\n });\n\n this.inflight.set(key, promise);\n return promise;\n }\n\n getInflight<T>(key: string): Promise<T> | undefined {\n return this.inflight.get(key) as Promise<T> | undefined;\n }\n\n invalidate(querySubstring: string): void {\n for (const key of this.cache.keys()) {\n if (key.includes(querySubstring)) {\n this.cache.delete(key);\n }\n }\n }\n\n clear(): void {\n this.cache.clear();\n this.inflight.clear();\n }\n}\n","import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\nimport type { ArchieClient, Session, AuthEvent } from '@archie/js-sdk';\nimport { QueryCache } from './lib/query-cache';\n\n// ─── Context ──────────────────────────────────────────────────\n\ninterface ArchieContextValue {\n client: ArchieClient;\n session: Session | null;\n isLoading: boolean;\n cache: QueryCache;\n}\n\nexport const ArchieContext = createContext<ArchieContextValue | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────\n\nexport interface ArchieProviderProps {\n client: ArchieClient;\n children: React.ReactNode;\n /** @internal Inject a custom cache (useful for testing). */\n cache?: QueryCache;\n}\n\n/**\n * ArchieProvider — wraps your React app to provide the Archie client and session state.\n *\n * @example\n * ```tsx\n * import { createClient } from '@archie/js-sdk'\n * import { ArchieProvider } from '@archie/react-sdk'\n *\n * const archie = createClient({ projectId: '...' })\n *\n * function App() {\n * return (\n * <ArchieProvider client={archie}>\n * <MyApp />\n * </ArchieProvider>\n * )\n * }\n * ```\n */\nexport function ArchieProvider({ client, children, cache: injectedCache }: ArchieProviderProps) {\n const [session, setSession] = useState<Session | null>(client.auth.getSession());\n const [isLoading, setIsLoading] = useState(true);\n const defaultCache = useMemo(() => new QueryCache(), [client]);\n const cache = injectedCache ?? defaultCache;\n\n useEffect(() => {\n client.auth.waitForInit().then(() => {\n setSession(client.auth.getSession());\n setIsLoading(false);\n });\n\n const unsubscribe = client.auth.onAuthStateChange(\n (_event: AuthEvent, newSession: Session | null) => {\n setSession(newSession);\n },\n );\n\n return unsubscribe;\n }, [client]);\n\n const value = useMemo<ArchieContextValue>(\n () => ({ client, session, isLoading, cache }),\n [client, session, isLoading, cache],\n );\n\n return React.createElement(ArchieContext.Provider, { value }, children);\n}\n\n/**\n * Internal hook to access the Archie context.\n * @throws if used outside ArchieProvider\n * @internal\n */\nexport function useArchieContext(): ArchieContextValue {\n const context = useContext(ArchieContext);\n if (!context) {\n throw new Error(\n 'useArchieClient must be used within an <ArchieProvider>. ' +\n 'Wrap your app with <ArchieProvider client={archieClient}>.',\n );\n }\n return context;\n}\n","import { useArchieContext } from '../provider';\nimport type { ArchieClient } from '@archie/js-sdk';\n\n/**\n * Returns the ArchieClient instance from context.\n * Must be used within an ArchieProvider.\n *\n * @throws Error if used outside ArchieProvider\n */\nexport function useArchieClient(): ArchieClient {\n const { client } = useArchieContext();\n return client;\n}\n","import { useCallback, useMemo } from 'react';\nimport { useArchieContext } from '../provider';\nimport type {\n User,\n Session,\n AuthSignUpParams,\n AuthSignInParams,\n AuthConfirmParams,\n AuthRecoverParams,\n AuthResetPasswordParams,\n ArchieError,\n} from '@archie/js-sdk';\n\ninterface UseAuthReturn {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n isAuthenticated: boolean;\n signIn: (\n params: AuthSignInParams,\n ) => Promise<{ session: Session | null; error: ArchieError | null }>;\n signUp: (\n params: AuthSignUpParams,\n ) => Promise<{ data: { userId: string; message: string } | null; error: ArchieError | null }>;\n signOut: () => Promise<void>;\n confirmSignUp: (\n params: AuthConfirmParams,\n ) => Promise<{ session: Session | null; error: ArchieError | null }>;\n recoverPassword: (\n params: AuthRecoverParams,\n ) => Promise<{ data: { message: string } | null; error: ArchieError | null }>;\n resetPassword: (\n params: AuthResetPasswordParams,\n ) => Promise<{ data: { message: string } | null; error: ArchieError | null }>;\n refreshSession: () => Promise<{ session: Session | null; error: ArchieError | null }>;\n}\n\n/**\n * Hook for authentication state and operations.\n * All methods return `{ data/session, error }` (never throws).\n */\nexport function useAuth(): UseAuthReturn {\n const { client, session, isLoading } = useArchieContext();\n\n const signIn = useCallback(\n async (params: AuthSignInParams) => {\n try {\n const result = await client.auth.signIn(params);\n return { session: result.session, error: null };\n } catch (err) {\n return { session: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const signUp = useCallback(\n async (params: AuthSignUpParams) => {\n try {\n const result = await client.auth.signUp(params);\n return { data: result, error: null };\n } catch (err) {\n return { data: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const signOut = useCallback(async () => {\n await client.auth.signOut();\n }, [client]);\n\n const confirmSignUp = useCallback(\n async (params: AuthConfirmParams) => {\n try {\n const result = await client.auth.confirmSignUp(params);\n return { session: result.session, error: null };\n } catch (err) {\n return { session: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const recoverPassword = useCallback(\n async (params: AuthRecoverParams) => {\n try {\n const result = await client.auth.recoverPassword(params);\n return { data: result, error: null };\n } catch (err) {\n return { data: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const resetPassword = useCallback(\n async (params: AuthResetPasswordParams) => {\n try {\n const result = await client.auth.resetPassword(params);\n return { data: result, error: null };\n } catch (err) {\n return { data: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const refreshSession = useCallback(async () => {\n try {\n const result = await client.auth.refreshSession();\n return { session: result.session, error: null };\n } catch (err) {\n return { session: null, error: err as ArchieError };\n }\n }, [client]);\n\n return useMemo(\n () => ({\n user: session?.user ?? null,\n session,\n isLoading,\n isAuthenticated: session !== null,\n signIn,\n signUp,\n signOut,\n confirmSignUp,\n recoverPassword,\n resetPassword,\n refreshSession,\n }),\n [\n session,\n isLoading,\n signIn,\n signUp,\n signOut,\n confirmSignUp,\n recoverPassword,\n resetPassword,\n refreshSession,\n ],\n );\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { useArchieContext } from '../provider';\nimport { QueryCache } from '../lib/query-cache';\nimport type { ArchieError } from '@archie/js-sdk';\n\ninterface UseQueryOptions<T> {\n enabled?: boolean;\n refetchInterval?: number;\n refetchOnWindowFocus?: boolean;\n onSuccess?: (data: T) => void;\n onError?: (error: ArchieError) => void;\n}\n\ninterface UseQueryReturn<T> {\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n isRefetching: boolean;\n refetch: () => Promise<void>;\n}\n\n/**\n * Declarative GraphQL query hook with caching and stale-while-revalidate.\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useQuery<{ users: User[] }>(\n * 'query { users { id email name } }',\n * { limit: 10 }\n * )\n * ```\n */\nexport function useQuery<T = unknown>(\n gql: string,\n variables?: Record<string, unknown>,\n options?: UseQueryOptions<T>,\n): UseQueryReturn<T> {\n const { client, session, cache } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isRefetching, setIsRefetching] = useState(false);\n\n const enabled = options?.enabled !== false;\n\n const variablesKey = variables ? JSON.stringify(variables) : '';\n const cacheKey = QueryCache.key(gql, variables);\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const fetchData = useCallback(\n async (isRefetch = false) => {\n if (!enabled) return;\n\n if (isRefetch) {\n setIsRefetching(true);\n } else {\n setIsLoading(true);\n }\n\n try {\n const result = await cache.dedup(cacheKey, () => client.graphql.query<T>(gql, variables));\n if (result.error) {\n setError(result.error);\n setData(null);\n optionsRef.current?.onError?.(result.error);\n } else {\n setData(result.data);\n setError(null);\n cache.set(cacheKey, result.data);\n optionsRef.current?.onSuccess?.(result.data as T);\n }\n } catch (err) {\n setError(err as ArchieError);\n setData(null);\n } finally {\n setIsLoading(false);\n setIsRefetching(false);\n }\n },\n [client, gql, variablesKey, enabled, cacheKey, cache],\n );\n\n // Initial fetch & refetch on variable change\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n\n const cached = cache.get<T>(cacheKey);\n if (cached) {\n setData(cached.data);\n setIsLoading(false);\n fetchData(true);\n } else {\n fetchData(false);\n }\n }, [cacheKey, enabled]);\n\n // Refetch on auth state change (new token)\n const prevSessionRef = useRef(session?.accessToken);\n useEffect(() => {\n if (\n enabled &&\n prevSessionRef.current !== session?.accessToken &&\n prevSessionRef.current !== undefined\n ) {\n fetchData(true);\n }\n prevSessionRef.current = session?.accessToken;\n }, [session?.accessToken, enabled]);\n\n // Polling (refetchInterval)\n useEffect(() => {\n if (!enabled || !options?.refetchInterval) return;\n\n const interval = setInterval(() => {\n fetchData(true);\n }, options.refetchInterval);\n\n return () => clearInterval(interval);\n }, [enabled, options?.refetchInterval]);\n\n // Refetch on window focus\n useEffect(() => {\n if (!enabled || !options?.refetchOnWindowFocus) return;\n if (typeof window === 'undefined') return;\n\n const handleFocus = () => fetchData(true);\n window.addEventListener('focus', handleFocus);\n return () => window.removeEventListener('focus', handleFocus);\n }, [enabled, options?.refetchOnWindowFocus]);\n\n const refetch = useCallback(() => fetchData(true), [fetchData]);\n\n return { data, error, isLoading, isRefetching, refetch };\n}\n","import { useState, useCallback, useRef } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError } from '@archie/js-sdk';\n\ninterface UseMutationOptions<T> {\n onSuccess?: (data: T) => void;\n onError?: (error: ArchieError) => void;\n onSettled?: () => void;\n /** Query substrings to invalidate (forcing refetch) after a successful mutation. */\n invalidateQueries?: string[];\n}\n\ninterface UseMutationReturn<T> {\n mutate: (variables?: Record<string, unknown>) => void;\n mutateAsync: (variables?: Record<string, unknown>) => Promise<T | null>;\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n reset: () => void;\n}\n\n/**\n * Hook for GraphQL mutations.\n *\n * @example\n * ```tsx\n * const { mutate, isLoading } = useMutation<{ createUser: User }>(\n * 'mutation($data: CreateUserInput!) { createUser(data: $data) { id email } }',\n * { invalidateQueries: ['users'] }\n * )\n *\n * mutate({ data: { email: 'new@user.com', name: 'John' } })\n * ```\n */\nexport function useMutation<T = unknown>(\n gql: string,\n options?: UseMutationOptions<T>,\n): UseMutationReturn<T> {\n const { client, cache } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const execute = useCallback(\n async (variables?: Record<string, unknown>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await client.graphql.mutate<T>(gql, variables);\n\n if (result.error) {\n setError(result.error);\n setData(null);\n optionsRef.current?.onError?.(result.error);\n optionsRef.current?.onSettled?.();\n return null;\n }\n\n setData(result.data);\n setError(null);\n optionsRef.current?.onSuccess?.(result.data as T);\n\n if (optionsRef.current?.invalidateQueries) {\n for (const queryKey of optionsRef.current.invalidateQueries) {\n cache.invalidate(queryKey);\n }\n }\n\n optionsRef.current?.onSettled?.();\n return result.data;\n } catch (err) {\n const archieErr = err as ArchieError;\n setError(archieErr);\n setData(null);\n optionsRef.current?.onError?.(archieErr);\n optionsRef.current?.onSettled?.();\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [client, gql, cache],\n );\n\n const mutate = useCallback(\n (variables?: Record<string, unknown>) => {\n execute(variables);\n },\n [execute],\n );\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return { mutate, mutateAsync: execute, data, error, isLoading, reset };\n}\n","import { useState, useEffect, useRef } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, ConnectionState } from '@archie/js-sdk';\n\ninterface UseSubscriptionOptions<T> {\n enabled?: boolean;\n onData?: (data: T) => void;\n onError?: (error: ArchieError) => void;\n}\n\ninterface UseSubscriptionReturn<T> {\n data: T | null;\n error: ArchieError | null;\n connectionState: ConnectionState;\n}\n\n/**\n * Hook for real-time GraphQL subscriptions.\n * Subscribes on mount, unsubscribes on unmount.\n *\n * @example\n * ```tsx\n * const { data } = useSubscription<{ orderUpdated: Order }>(\n * 'subscription { orderUpdated { id status total } }'\n * )\n * ```\n */\nexport function useSubscription<T = unknown>(\n gql: string,\n variables?: Record<string, unknown>,\n options?: UseSubscriptionOptions<T>,\n): UseSubscriptionReturn<T> {\n const { client } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [connectionState, setConnectionState] = useState<ConnectionState>('DISCONNECTED');\n\n const enabled = options?.enabled !== false;\n const variablesKey = variables ? JSON.stringify(variables) : '';\n\n // Track latest callbacks to avoid stale closures\n const callbacksRef = useRef(options);\n callbacksRef.current = options;\n\n useEffect(() => {\n if (!enabled) return;\n\n const unsub = client.realtime.onConnectionStateChange(setConnectionState);\n\n const subscription = client.realtime.subscribe<T>(gql, variables, {\n onData: (newData: T) => {\n setData(newData);\n setError(null);\n callbacksRef.current?.onData?.(newData);\n },\n onError: (err) => {\n setError(err);\n callbacksRef.current?.onError?.(err);\n },\n onComplete: () => {\n // Subscription completed server-side\n },\n });\n\n return () => {\n subscription.unsubscribe();\n unsub();\n };\n }, [client, gql, variablesKey, enabled]);\n\n return { data, error, connectionState };\n}\n","import { useState, useCallback } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, FileUploadOptions, FileUploadResult } from '@archie/js-sdk';\n\ninterface UseFileUploadReturn {\n upload: (file: File | Blob, options?: FileUploadOptions) => Promise<void>;\n progress: number;\n isUploading: boolean;\n data: FileUploadResult | null;\n error: ArchieError | null;\n reset: () => void;\n}\n\n/**\n * Hook for file uploads.\n *\n * @example\n * ```tsx\n * const { upload, isUploading, data } = useFileUpload()\n *\n * <input type=\"file\" onChange={(e) => upload(e.target.files[0])} />\n * {isUploading && <Spinner />}\n * ```\n */\nexport function useFileUpload(): UseFileUploadReturn {\n const { client } = useArchieContext();\n const [progress, setProgress] = useState(0);\n const [isUploading, setIsUploading] = useState(false);\n const [data, setData] = useState<FileUploadResult | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n\n const upload = useCallback(\n async (file: File | Blob, options?: FileUploadOptions) => {\n setIsUploading(true);\n setProgress(0);\n setError(null);\n setData(null);\n\n try {\n const result = await client.files.upload(file, options);\n\n setData(result);\n setProgress(100);\n } catch (err) {\n setError(err as ArchieError);\n } finally {\n setIsUploading(false);\n }\n },\n [client],\n );\n\n const reset = useCallback(() => {\n setProgress(0);\n setIsUploading(false);\n setData(null);\n setError(null);\n }, []);\n\n return { upload, progress, isUploading, data, error, reset };\n}\n","import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, RestRequestOptions, IRestModule } from '@archie/js-sdk';\n\n// ─── useRest (base) ──────────────────────────────────────────\n\n/**\n * Returns the REST module from the Archie client.\n * Provides direct access to `get`, `post`, `put`, `patch`, `delete`.\n *\n * @example\n * ```tsx\n * const rest = useRest()\n * const data = await rest.get('/api/products')\n * await rest.post('/api/products', { name: 'Widget' })\n * ```\n */\nexport function useRest(): IRestModule {\n const { client } = useArchieContext();\n return useMemo(() => client.rest, [client]);\n}\n\n// ─── useRestQuery ─────────────────────────────────────────────\n\ninterface UseRestQueryReturn<T> {\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n refetch: () => Promise<void>;\n}\n\n/**\n * Declarative hook for GET requests to custom REST APIs.\n */\nexport function useRestQuery<T = unknown>(\n path: string,\n options?: RestRequestOptions & { enabled?: boolean },\n): UseRestQueryReturn<T> {\n const { client } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n\n const enabled = options?.enabled !== false;\n\n const fetchData = useCallback(async () => {\n if (!enabled) return;\n setIsLoading(true);\n\n try {\n const result = await client.rest.get<T>(path, options);\n setData(result);\n setError(null);\n } catch (err) {\n setError(err as ArchieError);\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, path, enabled]);\n\n useEffect(() => {\n if (enabled) {\n fetchData();\n } else {\n setIsLoading(false);\n }\n }, [fetchData, enabled]);\n\n return { data, error, isLoading, refetch: fetchData };\n}\n\n// ─── useRestMutation ──────────────────────────────────────────\n\ninterface UseRestMutationReturn<T> {\n execute: (body?: unknown, overrideOptions?: RestRequestOptions) => Promise<T | null>;\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n reset: () => void;\n}\n\n/**\n * Imperative hook for POST/PUT/PATCH/DELETE requests to custom REST APIs.\n */\nexport function useRestMutation<T = unknown>(\n path: string,\n method: 'POST' | 'PUT' | 'PATCH' | 'DELETE' = 'POST',\n): UseRestMutationReturn<T> {\n const { client } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const execute = useCallback(\n async (body?: unknown, overrideOptions?: RestRequestOptions): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n\n try {\n let result: T;\n switch (method) {\n case 'POST':\n result = await client.rest.post<T>(path, body, overrideOptions);\n break;\n case 'PUT':\n result = await client.rest.put<T>(path, body, overrideOptions);\n break;\n case 'PATCH':\n result = await client.rest.patch<T>(path, body, overrideOptions);\n break;\n case 'DELETE':\n result = await client.rest.delete<T>(path, overrideOptions);\n break;\n }\n\n setData(result);\n setError(null);\n return result;\n } catch (err) {\n const archieErr = err as ArchieError;\n setError(archieErr);\n setData(null);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [client, path, method],\n );\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return { execute, data, error, isLoading, reset };\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, ConnectionState, Notification } from '@archie/js-sdk';\n\nexport interface UseNotificationsOptions {\n enabled?: boolean;\n unreadOnly?: boolean;\n limit?: number;\n onNotification?: (notification: Notification) => void;\n}\n\nexport interface UseNotificationsReturn {\n notifications: Notification[];\n latest: Notification | null;\n unreadCount: number;\n isLoading: boolean;\n error: ArchieError | null;\n connectionState: ConnectionState;\n markAsRead: (id: string) => Promise<void>;\n markAllAsRead: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\n/**\n * Subscribe to a user's in-app notifications: loads the existing list,\n * then streams new ones live. Returns idiomatic React state.\n *\n * @example\n * ```tsx\n * const { notifications, unreadCount, markAsRead } = useNotifications(user.id);\n * ```\n */\nexport function useNotifications(\n receiverId: string,\n options?: UseNotificationsOptions,\n): UseNotificationsReturn {\n const { client } = useArchieContext();\n const [notifications, setNotifications] = useState<Notification[]>([]);\n const [latest, setLatest] = useState<Notification | null>(null);\n const [unreadCount, setUnreadCount] = useState(0);\n const [isLoading, setIsLoading] = useState(options?.enabled !== false);\n const [error, setError] = useState<ArchieError | null>(null);\n const [connectionState, setConnectionState] = useState<ConnectionState>(\n () => client.realtime.currentState,\n );\n\n const enabled = options?.enabled !== false;\n const unreadOnly = options?.unreadOnly ?? false;\n const limit = options?.limit;\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const notificationsRef = useRef<Notification[]>([]);\n notificationsRef.current = notifications;\n\n const seenIdsRef = useRef<Set<string>>(new Set());\n\n // Reset local state when the receiver changes (never show the prior user's data)\n useEffect(() => {\n setNotifications([]);\n setLatest(null);\n setUnreadCount(0);\n seenIdsRef.current = new Set();\n }, [receiverId]);\n\n const load = useCallback(async () => {\n const [listResult, unread] = await Promise.all([\n client.notifications.list(receiverId, { unreadOnly, first: limit }),\n client.notifications.getUnreadCount(receiverId),\n ]);\n return { listResult, unread };\n }, [client, receiverId, unreadOnly, limit]);\n\n // Data load — re-runs on list params; cancellable so stale results never win\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n let active = true;\n setIsLoading(true);\n load()\n .then(({ listResult, unread }) => {\n if (!active) return;\n setNotifications(listResult.items);\n seenIdsRef.current = new Set(listResult.items.map((n) => n.id));\n setUnreadCount(unread);\n setError(null);\n })\n .catch((err) => {\n if (active) setError(err as ArchieError);\n })\n .finally(() => {\n if (active) setIsLoading(false);\n });\n return () => {\n active = false;\n };\n }, [enabled, load]);\n\n // Live subscription — only re-runs on client/receiverId/enabled, NOT on list params\n useEffect(() => {\n if (!enabled) return;\n const unsubConnection = client.realtime.onConnectionStateChange(setConnectionState);\n setConnectionState(client.realtime.currentState);\n\n const channel = client.notifications.subscribe(receiverId, {\n onError: (err) => setError(err),\n });\n channel.on('*', (notification: Notification) => {\n if (seenIdsRef.current.has(notification.id)) return; // ignore duplicates entirely\n seenIdsRef.current.add(notification.id);\n setNotifications((prev) => [notification, ...prev]);\n setLatest(notification);\n if (!notification.isRead) setUnreadCount((c) => c + 1);\n optionsRef.current?.onNotification?.(notification);\n });\n\n return () => {\n channel.unsubscribe();\n unsubConnection();\n };\n }, [client, receiverId, enabled]);\n\n const markAsRead = useCallback(\n async (id: string) => {\n const wasUnread = notificationsRef.current.find((n) => n.id === id)?.isRead === false;\n try {\n await client.notifications.markAsRead(id);\n setNotifications((prev) =>\n prev.map((n) => (n.id === id && !n.isRead ? { ...n, isRead: true } : n)),\n );\n if (wasUnread) setUnreadCount((c) => Math.max(0, c - 1));\n } catch (err) {\n setError(err as ArchieError);\n throw err;\n }\n },\n [client],\n );\n\n const markAllAsRead = useCallback(async () => {\n try {\n await client.notifications.markAllAsRead(receiverId);\n setNotifications((prev) => prev.map((n) => (n.isRead ? n : { ...n, isRead: true })));\n // Reconcile against the authoritative server count rather than assuming 0\n const count = await client.notifications.getUnreadCount(receiverId);\n setUnreadCount(count);\n } catch (err) {\n setError(err as ArchieError);\n throw err;\n }\n }, [client, receiverId]);\n\n const refetch = useCallback(async () => {\n setIsLoading(true);\n try {\n const { listResult, unread } = await load();\n setNotifications(listResult.items);\n seenIdsRef.current = new Set(listResult.items.map((n) => n.id));\n setUnreadCount(unread);\n setError(null);\n } catch (err) {\n setError(err as ArchieError);\n } finally {\n setIsLoading(false);\n }\n }, [load]);\n\n return {\n notifications,\n latest,\n unreadCount,\n isLoading,\n error,\n connectionState,\n markAsRead,\n markAllAsRead,\n refetch,\n };\n}\n","import React from 'react';\nimport { useAuth } from '../hooks/useAuth';\n\nexport interface AuthGuardProps {\n /** Content to show when authenticated (and authorized if roles specified). */\n children: React.ReactNode;\n /** Content to show when NOT authenticated. */\n fallback?: React.ReactNode;\n /** Content to show while session is loading. */\n loadingComponent?: React.ReactNode;\n /** If specified, user must have at least one of these roles. */\n requiredRoles?: string[];\n}\n\n/**\n * AuthGuard component — conditionally renders children based on auth state.\n *\n * @example\n * ```tsx\n * <AuthGuard fallback={<LoginPage />} requiredRoles={['admin']}>\n * <AdminPanel />\n * </AuthGuard>\n * ```\n */\nexport function AuthGuard({\n children,\n fallback = null,\n loadingComponent = null,\n requiredRoles,\n}: AuthGuardProps) {\n const { user, isLoading, isAuthenticated } = useAuth();\n\n if (isLoading) {\n return React.createElement(React.Fragment, null, loadingComponent);\n }\n\n if (!isAuthenticated || !user) {\n return React.createElement(React.Fragment, null, fallback);\n }\n\n // Check roles if required\n if (requiredRoles && requiredRoles.length > 0) {\n const hasRequiredRole = requiredRoles.some((role) => user.roles.includes(role));\n if (!hasRequiredRole) {\n return React.createElement(React.Fragment, null, fallback);\n }\n }\n\n return React.createElement(React.Fragment, null, children);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/query-cache.ts","../src/provider.tsx","../src/hooks/useArchieClient.ts","../src/hooks/useAuth.ts","../src/hooks/useQuery.ts","../src/hooks/useMutation.ts","../src/hooks/useSubscription.ts","../src/hooks/useFileUpload.ts","../src/hooks/useRest.ts","../src/hooks/useNotifications.ts","../src/components/AuthGuard.tsx"],"names":["React","useMemo","useState","useCallback","useEffect","useRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-memory query cache with in-flight request deduplication and stale-while-revalidate.\n * @internal\n */\n\ninterface CacheEntry<T = unknown> {\n data: T;\n timestamp: number;\n}\n\nexport class QueryCache {\n private cache = new Map<string, CacheEntry>();\n private inflight = new Map<string, Promise<unknown>>();\n private staleTime = 0;\n\n static key(query: string, variables?: Record<string, unknown>): string {\n return `${query}::${variables ? JSON.stringify(variables) : ''}`;\n }\n\n get<T>(key: string): CacheEntry<T> | undefined {\n return this.cache.get(key) as CacheEntry<T> | undefined;\n }\n\n set<T>(key: string, data: T): void {\n this.cache.set(key, { data, timestamp: Date.now() });\n }\n\n isFresh(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n if (this.staleTime === 0) return false;\n return Date.now() - entry.timestamp < this.staleTime;\n }\n\n /**\n * Deduplicate in-flight requests: if an identical fetch is already pending,\n * return the same promise. Otherwise, run `fetcher` and share the promise.\n */\n async dedup<T>(key: string, fetcher: () => Promise<T>): Promise<T> {\n const existing = this.inflight.get(key);\n if (existing) return existing as Promise<T>;\n\n const promise = fetcher().finally(() => {\n this.inflight.delete(key);\n });\n\n this.inflight.set(key, promise);\n return promise;\n }\n\n getInflight<T>(key: string): Promise<T> | undefined {\n return this.inflight.get(key) as Promise<T> | undefined;\n }\n\n invalidate(querySubstring: string): void {\n for (const key of this.cache.keys()) {\n if (key.includes(querySubstring)) {\n this.cache.delete(key);\n }\n }\n }\n\n clear(): void {\n this.cache.clear();\n this.inflight.clear();\n }\n}\n","import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\nimport type { ArchieClient, Session, AuthEvent } from '@archie/js-sdk';\nimport { QueryCache } from './lib/query-cache';\n\n// ─── Context ──────────────────────────────────────────────────\n\ninterface ArchieContextValue {\n client: ArchieClient;\n session: Session | null;\n isLoading: boolean;\n cache: QueryCache;\n}\n\nexport const ArchieContext = createContext<ArchieContextValue | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────\n\nexport interface ArchieProviderProps {\n client: ArchieClient;\n children: React.ReactNode;\n /** @internal Inject a custom cache (useful for testing). */\n cache?: QueryCache;\n}\n\n/**\n * ArchieProvider — wraps your React app to provide the Archie client and session state.\n *\n * @example\n * ```tsx\n * import { createClient } from '@archie/js-sdk'\n * import { ArchieProvider } from '@archie/react-sdk'\n *\n * const archie = createClient({ projectId: '...' })\n *\n * function App() {\n * return (\n * <ArchieProvider client={archie}>\n * <MyApp />\n * </ArchieProvider>\n * )\n * }\n * ```\n */\nexport function ArchieProvider({ client, children, cache: injectedCache }: ArchieProviderProps) {\n const [session, setSession] = useState<Session | null>(client.auth.getSession());\n const [isLoading, setIsLoading] = useState(true);\n const defaultCache = useMemo(() => new QueryCache(), [client]);\n const cache = injectedCache ?? defaultCache;\n\n useEffect(() => {\n client.auth.waitForInit().then(() => {\n setSession(client.auth.getSession());\n setIsLoading(false);\n });\n\n const unsubscribe = client.auth.onAuthStateChange(\n (_event: AuthEvent, newSession: Session | null) => {\n setSession(newSession);\n },\n );\n\n return unsubscribe;\n }, [client]);\n\n const value = useMemo<ArchieContextValue>(\n () => ({ client, session, isLoading, cache }),\n [client, session, isLoading, cache],\n );\n\n return React.createElement(ArchieContext.Provider, { value }, children);\n}\n\n/**\n * Internal hook to access the Archie context.\n * @throws if used outside ArchieProvider\n * @internal\n */\nexport function useArchieContext(): ArchieContextValue {\n const context = useContext(ArchieContext);\n if (!context) {\n throw new Error(\n 'useArchieClient must be used within an <ArchieProvider>. ' +\n 'Wrap your app with <ArchieProvider client={archieClient}>.',\n );\n }\n return context;\n}\n","import { useArchieContext } from '../provider';\nimport type { ArchieClient } from '@archie/js-sdk';\n\n/**\n * Returns the ArchieClient instance from context.\n * Must be used within an ArchieProvider.\n *\n * @throws Error if used outside ArchieProvider\n */\nexport function useArchieClient(): ArchieClient {\n const { client } = useArchieContext();\n return client;\n}\n","import { useCallback, useMemo } from 'react';\nimport { useArchieContext } from '../provider';\nimport type {\n User,\n Session,\n AuthSignUpParams,\n AuthSignInParams,\n AuthConfirmParams,\n AuthRecoverParams,\n AuthResetPasswordParams,\n ArchieError,\n} from '@archie/js-sdk';\n\ninterface UseAuthReturn {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n isAuthenticated: boolean;\n signIn: (\n params: AuthSignInParams,\n ) => Promise<{ session: Session | null; error: ArchieError | null }>;\n signUp: (\n params: AuthSignUpParams,\n ) => Promise<{ data: { userId: string; message: string } | null; error: ArchieError | null }>;\n signOut: () => Promise<void>;\n confirmSignUp: (\n params: AuthConfirmParams,\n ) => Promise<{ session: Session | null; error: ArchieError | null }>;\n recoverPassword: (\n params: AuthRecoverParams,\n ) => Promise<{ data: { message: string } | null; error: ArchieError | null }>;\n resetPassword: (\n params: AuthResetPasswordParams,\n ) => Promise<{ data: { message: string } | null; error: ArchieError | null }>;\n refreshSession: () => Promise<{ session: Session | null; error: ArchieError | null }>;\n}\n\n/**\n * Hook for authentication state and operations.\n * All methods return `{ data/session, error }` (never throws).\n */\nexport function useAuth(): UseAuthReturn {\n const { client, session, isLoading } = useArchieContext();\n\n const signIn = useCallback(\n async (params: AuthSignInParams) => {\n try {\n const result = await client.auth.signIn(params);\n return { session: result.session, error: null };\n } catch (err) {\n return { session: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const signUp = useCallback(\n async (params: AuthSignUpParams) => {\n try {\n const result = await client.auth.signUp(params);\n return { data: result, error: null };\n } catch (err) {\n return { data: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const signOut = useCallback(async () => {\n await client.auth.signOut();\n }, [client]);\n\n const confirmSignUp = useCallback(\n async (params: AuthConfirmParams) => {\n try {\n const result = await client.auth.confirmSignUp(params);\n return { session: result.session, error: null };\n } catch (err) {\n return { session: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const recoverPassword = useCallback(\n async (params: AuthRecoverParams) => {\n try {\n const result = await client.auth.recoverPassword(params);\n return { data: result, error: null };\n } catch (err) {\n return { data: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const resetPassword = useCallback(\n async (params: AuthResetPasswordParams) => {\n try {\n const result = await client.auth.resetPassword(params);\n return { data: result, error: null };\n } catch (err) {\n return { data: null, error: err as ArchieError };\n }\n },\n [client],\n );\n\n const refreshSession = useCallback(async () => {\n try {\n const result = await client.auth.refreshSession();\n return { session: result.session, error: null };\n } catch (err) {\n return { session: null, error: err as ArchieError };\n }\n }, [client]);\n\n return useMemo(\n () => ({\n user: session?.user ?? null,\n session,\n isLoading,\n isAuthenticated: session !== null,\n signIn,\n signUp,\n signOut,\n confirmSignUp,\n recoverPassword,\n resetPassword,\n refreshSession,\n }),\n [\n session,\n isLoading,\n signIn,\n signUp,\n signOut,\n confirmSignUp,\n recoverPassword,\n resetPassword,\n refreshSession,\n ],\n );\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { useArchieContext } from '../provider';\nimport { QueryCache } from '../lib/query-cache';\nimport type { ArchieError } from '@archie/js-sdk';\n\ninterface UseQueryOptions<T> {\n enabled?: boolean;\n refetchInterval?: number;\n refetchOnWindowFocus?: boolean;\n onSuccess?: (data: T) => void;\n onError?: (error: ArchieError) => void;\n}\n\ninterface UseQueryReturn<T> {\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n isRefetching: boolean;\n refetch: () => Promise<void>;\n}\n\n/**\n * Declarative GraphQL query hook with caching and stale-while-revalidate.\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useQuery<{ users: User[] }>(\n * 'query { users { id email name } }',\n * { limit: 10 }\n * )\n * ```\n */\nexport function useQuery<T = unknown>(\n gql: string,\n variables?: Record<string, unknown>,\n options?: UseQueryOptions<T>,\n): UseQueryReturn<T> {\n const { client, session, cache } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isRefetching, setIsRefetching] = useState(false);\n\n const enabled = options?.enabled !== false;\n\n const variablesKey = variables ? JSON.stringify(variables) : '';\n const cacheKey = QueryCache.key(gql, variables);\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const fetchData = useCallback(\n async (isRefetch = false) => {\n if (!enabled) return;\n\n if (isRefetch) {\n setIsRefetching(true);\n } else {\n setIsLoading(true);\n }\n\n try {\n const result = await cache.dedup(cacheKey, () => client.graphql.query<T>(gql, variables));\n if (result.error) {\n setError(result.error);\n setData(null);\n optionsRef.current?.onError?.(result.error);\n } else {\n setData(result.data);\n setError(null);\n cache.set(cacheKey, result.data);\n optionsRef.current?.onSuccess?.(result.data as T);\n }\n } catch (err) {\n setError(err as ArchieError);\n setData(null);\n } finally {\n setIsLoading(false);\n setIsRefetching(false);\n }\n },\n [client, gql, variablesKey, enabled, cacheKey, cache],\n );\n\n // Initial fetch & refetch on variable change\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n\n const cached = cache.get<T>(cacheKey);\n if (cached) {\n setData(cached.data);\n setIsLoading(false);\n fetchData(true);\n } else {\n fetchData(false);\n }\n }, [cacheKey, enabled]);\n\n // Refetch on auth state change (new token)\n const prevSessionRef = useRef(session?.accessToken);\n useEffect(() => {\n if (\n enabled &&\n prevSessionRef.current !== session?.accessToken &&\n prevSessionRef.current !== undefined\n ) {\n fetchData(true);\n }\n prevSessionRef.current = session?.accessToken;\n }, [session?.accessToken, enabled]);\n\n // Polling (refetchInterval)\n useEffect(() => {\n if (!enabled || !options?.refetchInterval) return;\n\n const interval = setInterval(() => {\n fetchData(true);\n }, options.refetchInterval);\n\n return () => clearInterval(interval);\n }, [enabled, options?.refetchInterval]);\n\n // Refetch on window focus\n useEffect(() => {\n if (!enabled || !options?.refetchOnWindowFocus) return;\n if (typeof window === 'undefined') return;\n\n const handleFocus = () => fetchData(true);\n window.addEventListener('focus', handleFocus);\n return () => window.removeEventListener('focus', handleFocus);\n }, [enabled, options?.refetchOnWindowFocus]);\n\n const refetch = useCallback(() => fetchData(true), [fetchData]);\n\n return { data, error, isLoading, isRefetching, refetch };\n}\n","import { useState, useCallback, useRef } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError } from '@archie/js-sdk';\n\ninterface UseMutationOptions<T> {\n onSuccess?: (data: T) => void;\n onError?: (error: ArchieError) => void;\n onSettled?: () => void;\n /** Query substrings to invalidate (forcing refetch) after a successful mutation. */\n invalidateQueries?: string[];\n}\n\ninterface UseMutationReturn<T> {\n mutate: (variables?: Record<string, unknown>) => void;\n mutateAsync: (variables?: Record<string, unknown>) => Promise<T | null>;\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n reset: () => void;\n}\n\n/**\n * Hook for GraphQL mutations.\n *\n * @example\n * ```tsx\n * const { mutate, isLoading } = useMutation<{ createUser: User }>(\n * 'mutation($data: CreateUserInput!) { createUser(data: $data) { id email } }',\n * { invalidateQueries: ['users'] }\n * )\n *\n * mutate({ data: { email: 'new@user.com', name: 'John' } })\n * ```\n */\nexport function useMutation<T = unknown>(\n gql: string,\n options?: UseMutationOptions<T>,\n): UseMutationReturn<T> {\n const { client, cache } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const execute = useCallback(\n async (variables?: Record<string, unknown>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await client.graphql.mutate<T>(gql, variables);\n\n if (result.error) {\n setError(result.error);\n setData(null);\n optionsRef.current?.onError?.(result.error);\n optionsRef.current?.onSettled?.();\n return null;\n }\n\n setData(result.data);\n setError(null);\n optionsRef.current?.onSuccess?.(result.data as T);\n\n if (optionsRef.current?.invalidateQueries) {\n for (const queryKey of optionsRef.current.invalidateQueries) {\n cache.invalidate(queryKey);\n }\n }\n\n optionsRef.current?.onSettled?.();\n return result.data;\n } catch (err) {\n const archieErr = err as ArchieError;\n setError(archieErr);\n setData(null);\n optionsRef.current?.onError?.(archieErr);\n optionsRef.current?.onSettled?.();\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [client, gql, cache],\n );\n\n const mutate = useCallback(\n (variables?: Record<string, unknown>) => {\n execute(variables);\n },\n [execute],\n );\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return { mutate, mutateAsync: execute, data, error, isLoading, reset };\n}\n","import { useState, useEffect, useRef } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, ConnectionState } from '@archie/js-sdk';\n\ninterface UseSubscriptionOptions<T> {\n enabled?: boolean;\n onData?: (data: T) => void;\n onError?: (error: ArchieError) => void;\n}\n\ninterface UseSubscriptionReturn<T> {\n data: T | null;\n error: ArchieError | null;\n connectionState: ConnectionState;\n}\n\n/**\n * Hook for real-time GraphQL subscriptions.\n * Subscribes on mount, unsubscribes on unmount.\n *\n * @example\n * ```tsx\n * const { data } = useSubscription<{ orderUpdated: Order }>(\n * 'subscription { orderUpdated { id status total } }'\n * )\n * ```\n */\nexport function useSubscription<T = unknown>(\n gql: string,\n variables?: Record<string, unknown>,\n options?: UseSubscriptionOptions<T>,\n): UseSubscriptionReturn<T> {\n const { client } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [connectionState, setConnectionState] = useState<ConnectionState>('DISCONNECTED');\n\n const enabled = options?.enabled !== false;\n const variablesKey = variables ? JSON.stringify(variables) : '';\n\n // Track latest callbacks to avoid stale closures\n const callbacksRef = useRef(options);\n callbacksRef.current = options;\n\n useEffect(() => {\n if (!enabled) return;\n\n const unsub = client.realtime.onConnectionStateChange(setConnectionState);\n\n const subscription = client.realtime.subscribe<T>(gql, variables, {\n onData: (newData: T) => {\n setData(newData);\n setError(null);\n callbacksRef.current?.onData?.(newData);\n },\n onError: (err) => {\n setError(err);\n callbacksRef.current?.onError?.(err);\n },\n onComplete: () => {\n // Subscription completed server-side\n },\n });\n\n return () => {\n subscription.unsubscribe();\n unsub();\n };\n }, [client, gql, variablesKey, enabled]);\n\n return { data, error, connectionState };\n}\n","import { useState, useCallback } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, FileUploadOptions, FileUploadResult } from '@archie/js-sdk';\n\ninterface UseFileUploadReturn {\n upload: (file: File | Blob, options?: FileUploadOptions) => Promise<void>;\n progress: number;\n isUploading: boolean;\n data: FileUploadResult | null;\n error: ArchieError | null;\n reset: () => void;\n}\n\n/**\n * Hook for file uploads.\n *\n * @example\n * ```tsx\n * const { upload, isUploading, data } = useFileUpload()\n *\n * <input type=\"file\" onChange={(e) => upload(e.target.files[0])} />\n * {isUploading && <Spinner />}\n * ```\n */\nexport function useFileUpload(): UseFileUploadReturn {\n const { client } = useArchieContext();\n const [progress, setProgress] = useState(0);\n const [isUploading, setIsUploading] = useState(false);\n const [data, setData] = useState<FileUploadResult | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n\n const upload = useCallback(\n async (file: File | Blob, options?: FileUploadOptions) => {\n setIsUploading(true);\n setProgress(0);\n setError(null);\n setData(null);\n\n try {\n const result = await client.files.upload(file, options);\n\n setData(result);\n setProgress(100);\n } catch (err) {\n setError(err as ArchieError);\n } finally {\n setIsUploading(false);\n }\n },\n [client],\n );\n\n const reset = useCallback(() => {\n setProgress(0);\n setIsUploading(false);\n setData(null);\n setError(null);\n }, []);\n\n return { upload, progress, isUploading, data, error, reset };\n}\n","import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, RestRequestOptions, IRestModule } from '@archie/js-sdk';\n\n// ─── useRest (base) ──────────────────────────────────────────\n\n/**\n * Returns the REST module from the Archie client.\n * Provides direct access to `get`, `post`, `put`, `patch`, `delete`.\n *\n * @example\n * ```tsx\n * const rest = useRest()\n * const data = await rest.get('/api/products')\n * await rest.post('/api/products', { name: 'Widget' })\n * ```\n */\nexport function useRest(): IRestModule {\n const { client } = useArchieContext();\n return useMemo(() => client.rest, [client]);\n}\n\n// ─── useRestQuery ─────────────────────────────────────────────\n\ninterface UseRestQueryReturn<T> {\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n refetch: () => Promise<void>;\n}\n\n/**\n * Declarative hook for GET requests to custom REST APIs.\n */\nexport function useRestQuery<T = unknown>(\n path: string,\n options?: RestRequestOptions & { enabled?: boolean },\n): UseRestQueryReturn<T> {\n const { client } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n\n const enabled = options?.enabled !== false;\n\n const fetchData = useCallback(async () => {\n if (!enabled) return;\n setIsLoading(true);\n\n try {\n const result = await client.rest.get<T>(path, options);\n setData(result);\n setError(null);\n } catch (err) {\n setError(err as ArchieError);\n setData(null);\n } finally {\n setIsLoading(false);\n }\n }, [client, path, enabled]);\n\n useEffect(() => {\n if (enabled) {\n fetchData();\n } else {\n setIsLoading(false);\n }\n }, [fetchData, enabled]);\n\n return { data, error, isLoading, refetch: fetchData };\n}\n\n// ─── useRestMutation ──────────────────────────────────────────\n\ninterface UseRestMutationReturn<T> {\n execute: (body?: unknown, overrideOptions?: RestRequestOptions) => Promise<T | null>;\n data: T | null;\n error: ArchieError | null;\n isLoading: boolean;\n reset: () => void;\n}\n\n/**\n * Imperative hook for POST/PUT/PATCH/DELETE requests to custom REST APIs.\n */\nexport function useRestMutation<T = unknown>(\n path: string,\n method: 'POST' | 'PUT' | 'PATCH' | 'DELETE' = 'POST',\n): UseRestMutationReturn<T> {\n const { client } = useArchieContext();\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<ArchieError | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const execute = useCallback(\n async (body?: unknown, overrideOptions?: RestRequestOptions): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n\n try {\n let result: T;\n switch (method) {\n case 'POST':\n result = await client.rest.post<T>(path, body, overrideOptions);\n break;\n case 'PUT':\n result = await client.rest.put<T>(path, body, overrideOptions);\n break;\n case 'PATCH':\n result = await client.rest.patch<T>(path, body, overrideOptions);\n break;\n case 'DELETE':\n result = await client.rest.delete<T>(path, overrideOptions);\n break;\n }\n\n setData(result);\n setError(null);\n return result;\n } catch (err) {\n const archieErr = err as ArchieError;\n setError(archieErr);\n setData(null);\n return null;\n } finally {\n setIsLoading(false);\n }\n },\n [client, path, method],\n );\n\n const reset = useCallback(() => {\n setData(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n return { execute, data, error, isLoading, reset };\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { useArchieContext } from '../provider';\nimport type { ArchieError, ConnectionState, Notification } from '@archie/js-sdk';\n\nexport interface UseNotificationsOptions {\n enabled?: boolean;\n unreadOnly?: boolean;\n /**\n * Page size. Applies to `fetchMore()` (older pages); when omitted, `fetchMore` uses 20.\n * It also caps the initial load (`first: limit`) — so omitting it lets the backend choose the\n * initial page size, meaning the first page and subsequent `fetchMore` pages may differ in size.\n */\n limit?: number;\n onNotification?: (notification: Notification) => void;\n}\n\nexport interface UseNotificationsReturn {\n notifications: Notification[];\n latest: Notification | null;\n unreadCount: number;\n isLoading: boolean;\n error: ArchieError | null;\n connectionState: ConnectionState;\n markAsRead: (id: string) => Promise<void>;\n markAllAsRead: () => Promise<void>;\n refetch: () => Promise<void>;\n /**\n * Load the next older page of history. No-op if `!hasMore`, a fetch is already in flight,\n * disabled, or a previous `fetchMore` errored (call `refetch()` or change the filter to retry).\n */\n fetchMore: () => Promise<void>;\n /** True while more older history exists for the active filter (the last page did not exhaust it). */\n hasMore: boolean;\n /** True while a fetchMore() call is in flight (drives a \"loading older\" indicator). */\n isFetchingMore: boolean;\n}\n\n/** Default page size for fetchMore() when no `limit` is provided. Initial load is unaffected. */\nconst DEFAULT_PAGE_SIZE = 20;\n\n/** Ids of the items whose `createdAt` equals `ts` — the tie-group at a keyset boundary. */\nfunction idsAt(items: Notification[], ts: string | null): string[] {\n if (ts == null) return [];\n return items.filter((n) => n.createdAt === ts).map((n) => n.id);\n}\n\n/**\n * Subscribe to a user's in-app notifications: loads the existing list,\n * then streams new ones live, and pages backward through history via fetchMore().\n * Returns idiomatic React state.\n *\n * @example\n * ```tsx\n * const { notifications, unreadCount, fetchMore, hasMore, isFetchingMore } =\n * useNotifications(user.id, { limit: 20 });\n * ```\n */\nexport function useNotifications(\n receiverId: string,\n options?: UseNotificationsOptions,\n): UseNotificationsReturn {\n const { client } = useArchieContext();\n const [notifications, setNotifications] = useState<Notification[]>([]);\n const [latest, setLatest] = useState<Notification | null>(null);\n const [unreadCount, setUnreadCount] = useState(0);\n const [isLoading, setIsLoading] = useState(options?.enabled !== false);\n const [error, setError] = useState<ArchieError | null>(null);\n const [connectionState, setConnectionState] = useState<ConnectionState>(\n () => client.realtime.currentState,\n );\n const [hasMore, setHasMore] = useState(false);\n const [isFetchingMore, setIsFetchingMore] = useState(false);\n\n const enabled = options?.enabled !== false;\n const unreadOnly = options?.unreadOnly ?? false;\n const limit = options?.limit;\n const pageSize = limit ?? DEFAULT_PAGE_SIZE;\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const notificationsRef = useRef<Notification[]>([]);\n notificationsRef.current = notifications;\n\n const seenIdsRef = useRef<Set<string>>(new Set());\n\n // Pagination bookkeeping (in refs so callbacks read fresh values without re-creating).\n const oldestCreatedAtRef = useRef<string | null>(null); // keyset cursor: oldest loaded createdAt\n const boundaryIdsRef = useRef<string[]>([]); // ids already loaded at the cursor timestamp (tie-safe keyset)\n const isFetchingMoreRef = useRef(false); // synchronous guard against overlapping fetchMore calls\n const paginationErroredRef = useRef(false); // set on a fetchMore error; suppresses further fetchMore until a reseed\n const hasMoreRef = useRef(false); // mirror of hasMore for the fetchMore closure\n hasMoreRef.current = hasMore;\n const loadTokenRef = useRef(0); // bumped on every (re)seed; drops stale in-flight fetchMore results\n\n // Invalidate any in-flight fetchMore and clear its transient flags. Called on every (re)seed\n // (receiver/filter change, load effect, refetch) so a stale page never lands and the error gate resets.\n const invalidateInFlightPagination = useCallback(() => {\n loadTokenRef.current += 1;\n isFetchingMoreRef.current = false;\n paginationErroredRef.current = false;\n setIsFetchingMore(false);\n }, []);\n\n // Seed pagination bookkeeping from a fresh first-page list result.\n const seedFromList = useCallback((items: Notification[], totalCount: number) => {\n const oldest = items.length > 0 ? items[items.length - 1].createdAt : null;\n oldestCreatedAtRef.current = oldest;\n boundaryIdsRef.current = idsAt(items, oldest);\n // Initial page has no cursor, so totalCount is the grand total for the filter.\n setHasMore(items.length < totalCount);\n }, []);\n\n // Apply a fresh first-page result: merge any live events that arrived during the load window\n // (present in state but not in the server snapshot) at the head so they aren't dropped, refresh\n // the seen-set, and seed pagination bookkeeping.\n const mergeAndSeed = useCallback(\n (items: Notification[], totalCount: number) => {\n const serverIds = new Set(items.map((n) => n.id));\n // Keep only items strictly NEWER than the snapshot's newest row (and not already in it):\n // those are live events pushed during the load window. Restricting to \"newer than newest\"\n // (not merely \"absent from the snapshot\") is what makes this safe on refetch()/limit change —\n // otherwise the already-loaded OLDER paginated rows would be re-hoisted above the first page.\n // ISO `createdAt` strings sort chronologically, so string `>` is the correct comparison.\n const newestSnapshot = items.length > 0 ? items[0].createdAt : null;\n const liveOnly = notificationsRef.current.filter(\n (n) => !serverIds.has(n.id) && (newestSnapshot === null || n.createdAt > newestSnapshot),\n );\n setNotifications([...liveOnly, ...items]);\n seenIdsRef.current = new Set([...liveOnly.map((n) => n.id), ...items.map((n) => n.id)]);\n seedFromList(items, totalCount);\n },\n [seedFromList],\n );\n\n // Reset local state when the receiver or filter changes (never show the prior query's data)\n useEffect(() => {\n setNotifications([]);\n setLatest(null);\n setUnreadCount(0);\n seenIdsRef.current = new Set();\n oldestCreatedAtRef.current = null;\n boundaryIdsRef.current = [];\n setHasMore(false);\n invalidateInFlightPagination();\n }, [receiverId, unreadOnly, invalidateInFlightPagination]);\n\n const load = useCallback(async () => {\n const [listResult, unread] = await Promise.all([\n client.notifications.list(receiverId, { unreadOnly, first: limit }),\n client.notifications.getUnreadCount(receiverId),\n ]);\n return { listResult, unread };\n }, [client, receiverId, unreadOnly, limit]);\n\n // Data load — re-runs on list params; cancellable so stale results never win\n useEffect(() => {\n if (!enabled) {\n setIsLoading(false);\n return;\n }\n let active = true;\n // A (re)seed invalidates any in-flight fetchMore.\n invalidateInFlightPagination();\n setIsLoading(true);\n load()\n .then(({ listResult, unread }) => {\n if (!active) return;\n mergeAndSeed(listResult.items, listResult.totalCount);\n setUnreadCount(unread);\n setError(null);\n })\n .catch((err) => {\n if (active) setError(err as ArchieError);\n })\n .finally(() => {\n if (active) setIsLoading(false);\n });\n return () => {\n active = false;\n };\n }, [enabled, load, mergeAndSeed, invalidateInFlightPagination]);\n\n // Live subscription — only re-runs on client/receiverId/enabled, NOT on list params\n useEffect(() => {\n if (!enabled) return;\n const unsubConnection = client.realtime.onConnectionStateChange(setConnectionState);\n setConnectionState(client.realtime.currentState);\n\n const channel = client.notifications.subscribe(receiverId, {\n onError: (err) => setError(err),\n });\n channel.on('*', (notification: Notification) => {\n if (seenIdsRef.current.has(notification.id)) return; // ignore duplicates entirely\n seenIdsRef.current.add(notification.id);\n setNotifications((prev) => [notification, ...prev]);\n setLatest(notification);\n if (!notification.isRead) setUnreadCount((c) => c + 1);\n optionsRef.current?.onNotification?.(notification);\n });\n\n return () => {\n channel.unsubscribe();\n unsubConnection();\n };\n }, [client, receiverId, enabled]);\n\n const markAsRead = useCallback(\n async (id: string) => {\n const wasUnread = notificationsRef.current.find((n) => n.id === id)?.isRead === false;\n try {\n await client.notifications.markAsRead(id);\n setNotifications((prev) =>\n prev.map((n) => (n.id === id && !n.isRead ? { ...n, isRead: true } : n)),\n );\n if (wasUnread) setUnreadCount((c) => Math.max(0, c - 1));\n } catch (err) {\n setError(err as ArchieError);\n throw err;\n }\n },\n [client],\n );\n\n const markAllAsRead = useCallback(async () => {\n try {\n await client.notifications.markAllAsRead(receiverId);\n setNotifications((prev) => prev.map((n) => (n.isRead ? n : { ...n, isRead: true })));\n // Reconcile against the authoritative server count rather than assuming 0\n const count = await client.notifications.getUnreadCount(receiverId);\n setUnreadCount(count);\n } catch (err) {\n setError(err as ArchieError);\n throw err;\n }\n }, [client, receiverId]);\n\n const refetch = useCallback(async () => {\n invalidateInFlightPagination();\n setIsLoading(true);\n try {\n const { listResult, unread } = await load();\n mergeAndSeed(listResult.items, listResult.totalCount);\n setUnreadCount(unread);\n setError(null);\n } catch (err) {\n setError(err as ArchieError);\n } finally {\n setIsLoading(false);\n }\n }, [load, mergeAndSeed, invalidateInFlightPagination]);\n\n const fetchMore = useCallback(async () => {\n if (\n !enabled ||\n !hasMoreRef.current ||\n isFetchingMoreRef.current ||\n paginationErroredRef.current // a prior page errored — wait for refetch()/filter change\n ) {\n return;\n }\n const cursor = oldestCreatedAtRef.current;\n if (cursor == null) return;\n\n const token = loadTokenRef.current;\n isFetchingMoreRef.current = true;\n setIsFetchingMore(true);\n try {\n const page = await client.notifications.list(receiverId, {\n unreadOnly,\n first: pageSize,\n orderBy: { createdAt: 'DESC' },\n createdBefore: cursor,\n // Tie-safe keyset: don't skip rows sharing the cursor timestamp that we haven't loaded yet.\n excludeIds: boundaryIdsRef.current,\n // Page-fill drives hasMore below, so skip the (potentially O(N)) COUNT on deep pages.\n includeTotal: false,\n });\n if (loadTokenRef.current !== token) return; // reseeded mid-flight — drop this page\n if (page.items.length === 0) {\n // Server has no older rows — end of history. Also guards against a no-progress fetch loop.\n setHasMore(false);\n return;\n }\n const fresh = page.items.filter((n) => !seenIdsRef.current.has(n.id));\n fresh.forEach((n) => seenIdsRef.current.add(n.id));\n if (fresh.length > 0) {\n setNotifications((prev) => [...prev, ...fresh]);\n }\n // Advance the keyset cursor to the oldest row in this page, and track the ids at that exact\n // timestamp so the next page's excludeIds skips only what we've loaded — never a tie sibling.\n const newOldest = page.items[page.items.length - 1].createdAt;\n const idsAtNewOldest = idsAt(page.items, newOldest);\n boundaryIdsRef.current =\n newOldest === cursor\n ? Array.from(new Set([...boundaryIdsRef.current, ...idsAtNewOldest]))\n : idsAtNewOldest;\n oldestCreatedAtRef.current = newOldest;\n // Page-fill termination: a full page means more may remain; a short page is the tail.\n setHasMore(page.items.length === pageSize);\n setError(null);\n } catch (err) {\n if (loadTokenRef.current === token) {\n // Gate further fetchMore so a consumer's auto-load effect can't hammer the backend\n // in a tight retry loop; a reseed (refetch/receiver/filter change) clears the gate.\n paginationErroredRef.current = true;\n setError(err as ArchieError);\n }\n } finally {\n if (loadTokenRef.current === token) {\n isFetchingMoreRef.current = false;\n setIsFetchingMore(false);\n }\n }\n }, [client, receiverId, unreadOnly, pageSize, enabled]);\n\n return {\n notifications,\n latest,\n unreadCount,\n isLoading,\n error,\n connectionState,\n markAsRead,\n markAllAsRead,\n refetch,\n fetchMore,\n hasMore,\n isFetchingMore,\n };\n}\n","import React from 'react';\nimport { useAuth } from '../hooks/useAuth';\n\nexport interface AuthGuardProps {\n /** Content to show when authenticated (and authorized if roles specified). */\n children: React.ReactNode;\n /** Content to show when NOT authenticated. */\n fallback?: React.ReactNode;\n /** Content to show while session is loading. */\n loadingComponent?: React.ReactNode;\n /** If specified, user must have at least one of these roles. */\n requiredRoles?: string[];\n}\n\n/**\n * AuthGuard component — conditionally renders children based on auth state.\n *\n * @example\n * ```tsx\n * <AuthGuard fallback={<LoginPage />} requiredRoles={['admin']}>\n * <AdminPanel />\n * </AuthGuard>\n * ```\n */\nexport function AuthGuard({\n children,\n fallback = null,\n loadingComponent = null,\n requiredRoles,\n}: AuthGuardProps) {\n const { user, isLoading, isAuthenticated } = useAuth();\n\n if (isLoading) {\n return React.createElement(React.Fragment, null, loadingComponent);\n }\n\n if (!isAuthenticated || !user) {\n return React.createElement(React.Fragment, null, fallback);\n }\n\n // Check roles if required\n if (requiredRoles && requiredRoles.length > 0) {\n const hasRequiredRole = requiredRoles.some((role) => user.roles.includes(role));\n if (!hasRequiredRole) {\n return React.createElement(React.Fragment, null, fallback);\n }\n }\n\n return React.createElement(React.Fragment, null, children);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archie/react-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Archie BAAS - React hooks, provider & components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"react": ">=18.0.0",
|
|
23
|
-
"@archie/js-sdk": "0.
|
|
23
|
+
"@archie/js-sdk": "0.3.1"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"react": "^19.0.0",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@testing-library/react": "^16.0.0",
|
|
33
33
|
"@testing-library/jest-dom": "^6.0.0",
|
|
34
34
|
"jsdom": "^25.0.0",
|
|
35
|
-
"@archie/js-sdk": "0.
|
|
35
|
+
"@archie/js-sdk": "0.3.1"
|
|
36
36
|
},
|
|
37
37
|
"sideEffects": false,
|
|
38
38
|
"keywords": [
|