Skip to content

Commit f354c54

Browse files
committed
feat: enhance API and hooks documentation for authentication and session management
1 parent 60182a9 commit f354c54

6 files changed

Lines changed: 993 additions & 0 deletions

File tree

src/hooks/useAuth.ts

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,84 @@
1+
/**
2+
* React Query hooks for authentication state management.
3+
*
4+
* **Architecture:**
5+
* Wraps auth API functions with React Query for:
6+
* - Caching (reduce redundant API calls)
7+
* - Loading states (isLoading, isPending)
8+
* - Error handling (error object)
9+
* - Optimistic updates (immediate UI feedback)
10+
* - Query invalidation (refresh data after mutations)
11+
*
12+
* **Authentication Flow:**
13+
* 1. useRegister/useLogin: Mutate to create session
14+
* 2. onSuccess: Invalidate ['me'] query to trigger refetch
15+
* 3. useMe: Query fetches current user data
16+
* 4. useLogout: Mutate to clear session, clear ['me'] cache
17+
*
18+
* **Cache Keys:**
19+
* - ['me']: Current user data (5-minute stale time)
20+
*
21+
* **Usage Pattern:**
22+
* ```typescript
23+
* const { mutate: login, isPending } = useLogin();
24+
* const { data: user, isLoading } = useMe();
25+
* const { mutate: logout } = useLogout();
26+
*
27+
* // Login
28+
* login({ email, password }, {
29+
* onSuccess: () => navigate('/dashboard'),
30+
* onError: (error) => showToast(error.message),
31+
* });
32+
*
33+
* // Check auth
34+
* if (user) {
35+
* // User logged in
36+
* }
37+
*
38+
* // Logout
39+
* logout();
40+
* ```
41+
*/
142
'use client';
243

344
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
445
import { login, register, logout, fetchMe } from '@/lib/api/auth';
546
import type { LoginPayload, RegisterPayload } from '@/lib/api/types';
647

48+
/**
49+
* Login mutation hook.
50+
*
51+
* **Mutation:**
52+
* Calls POST /api/auth/login with credentials.
53+
* Sets HttpOnly session cookie on success.
54+
*
55+
* **Side Effects:**
56+
* - onSuccess: Invalidates ['me'] query to refetch user data
57+
* - Cookie automatically sent on future requests
58+
*
59+
* **Usage:**
60+
* ```typescript
61+
* const { mutate: login, isPending, error } = useLogin();
62+
*
63+
* login({ email: 'user@example.com', password: 'secret' }, {
64+
* onSuccess: () => {
65+
* showToast('Login successful');
66+
* navigate('/dashboard');
67+
* },
68+
* onError: (error) => {
69+
* showToast(error.message);
70+
* },
71+
* });
72+
* ```
73+
*
74+
* **Return Values:**
75+
* - mutate: Function to trigger login
76+
* - isPending: True while request in flight
77+
* - error: Error object if request fails
78+
* - data: Response data if successful
79+
*
80+
* @returns React Query mutation result
81+
*/
782
export function useLogin() {
883
const queryClient = useQueryClient();
984

@@ -16,6 +91,50 @@ export function useLogin() {
1691
});
1792
}
1893

94+
/**
95+
* Registration mutation hook.
96+
*
97+
* **Mutation:**
98+
* Calls POST /api/auth/register with user data.
99+
* Creates account and sets HttpOnly session cookie.
100+
*
101+
* **Side Effects:**
102+
* - onSuccess: Invalidates ['me'] query to refetch user data
103+
* - User immediately authenticated after registration
104+
*
105+
* **Validation:**
106+
* - email: Must be valid and unique
107+
* - password: Minimum 8 characters
108+
* - firstName, lastName: Required
109+
*
110+
* **Usage:**
111+
* ```typescript
112+
* const { mutate: register, isPending, error } = useRegister();
113+
*
114+
* register({
115+
* email: 'user@example.com',
116+
* password: 'SecurePass123',
117+
* firstName: 'John',
118+
* lastName: 'Doe',
119+
* }, {
120+
* onSuccess: () => {
121+
* showToast('Account created!');
122+
* navigate('/dashboard');
123+
* },
124+
* onError: (error) => {
125+
* showToast(error.message); // e.g., "Email already registered"
126+
* },
127+
* });
128+
* ```
129+
*
130+
* **Return Values:**
131+
* - mutate: Function to trigger registration
132+
* - isPending: True while request in flight
133+
* - error: Error object if request fails
134+
* - data: Response data if successful
135+
*
136+
* @returns React Query mutation result
137+
*/
19138
export function useRegister() {
20139
const queryClient = useQueryClient();
21140

@@ -28,6 +147,40 @@ export function useRegister() {
28147
});
29148
}
30149

150+
/**
151+
* Logout mutation hook.
152+
*
153+
* **Mutation:**
154+
* Calls POST /api/auth/logout to clear session.
155+
* Clears HttpOnly cookie on server.
156+
*
157+
* **Side Effects:**
158+
* - onSuccess: Sets ['me'] query data to null (immediate UI update)
159+
* - onSuccess: Invalidates ['me'] query (trigger refetch if component still mounted)
160+
*
161+
* **Security Note:**
162+
* JWT token remains valid until expiration (stateless).
163+
* Attacker with stolen token can still use it.
164+
* Logout only clears cookie and client cache.
165+
*
166+
* **Usage:**
167+
* ```typescript
168+
* const { mutate: logout, isPending } = useLogout();
169+
*
170+
* logout(undefined, {
171+
* onSuccess: () => {
172+
* showToast('Logged out');
173+
* navigate('/login');
174+
* },
175+
* });
176+
* ```
177+
*
178+
* **Return Values:**
179+
* - mutate: Function to trigger logout
180+
* - isPending: True while request in flight
181+
*
182+
* @returns React Query mutation result
183+
*/
31184
export function useLogout() {
32185
const queryClient = useQueryClient();
33186

@@ -41,6 +194,49 @@ export function useLogout() {
41194
});
42195
}
43196

197+
/**
198+
* Current user query hook.
199+
*
200+
* **Query:**
201+
* Fetches GET /api/auth/me to get authenticated user.
202+
* Requires valid session cookie.
203+
*
204+
* **Caching:**
205+
* - staleTime: 5 minutes (avoid refetch on every navigation)
206+
* - retry: false (don't retry on 401, user just not logged in)
207+
*
208+
* **Usage:**
209+
* ```typescript
210+
* const { data, isLoading, error } = useMe();
211+
*
212+
* if (isLoading) return <Spinner />;
213+
* if (error) return <LoginPrompt />;
214+
* if (data?.user) {
215+
* return <Dashboard user={data.user} />;
216+
* }
217+
* ```
218+
*
219+
* **Conditional Fetching:**
220+
* ```typescript
221+
* // Only fetch if needed
222+
* const { data } = useMe(false); // Don't fetch
223+
* const { data } = useMe(shouldFetch); // Conditional
224+
* ```
225+
*
226+
* **Return Values:**
227+
* - data: { user: User } or undefined
228+
* - isLoading: True on initial fetch
229+
* - error: Error object if request fails (e.g., 401)
230+
*
231+
* **Authentication Check:**
232+
* ```typescript
233+
* const { data: currentUser } = useMe();
234+
* const isAuthenticated = Boolean(currentUser?.user);
235+
* ```
236+
*
237+
* @param enabled - Whether to fetch (default: true)
238+
* @returns React Query query result
239+
*/
44240
export function useMe(enabled = true) {
45241
return useQuery({
46242
queryKey: ['me'],

0 commit comments

Comments
 (0)