feat(frontend): implement API client and auth module
Adds the base fetch wrapper (client.ts) with JWT auth headers, automatic token refresh on 401 with request deduplication, and typed ApiError. Adds auth.ts with login/logout/refresh/listSessions/ terminateSession. Adds authStore (stores/auth.ts) persisted to localStorage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import type { User } from '$lib/api/types';
|
||||
|
||||
export interface AuthState {
|
||||
accessToken: string | null;
|
||||
refreshToken: string | null;
|
||||
user: User | null;
|
||||
}
|
||||
|
||||
const initial: AuthState = { accessToken: null, refreshToken: null, user: null };
|
||||
|
||||
function loadStored(): AuthState {
|
||||
if (typeof localStorage === 'undefined') return initial;
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem('auth') ?? 'null') ?? initial;
|
||||
} catch {
|
||||
return initial;
|
||||
}
|
||||
}
|
||||
|
||||
export const authStore = writable<AuthState>(loadStored());
|
||||
|
||||
authStore.subscribe((state) => {
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
localStorage.setItem('auth', JSON.stringify(state));
|
||||
}
|
||||
});
|
||||
|
||||
export const isAuthenticated = derived(authStore, ($auth) => !!$auth.accessToken);
|
||||
Reference in New Issue
Block a user