@lenan-soft/auth 1.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/index.ts","../../src/react/auth-provider.tsx","../../src/shared/types.ts","../../src/react/auth-client.ts","../../src/react/storage.ts"],"sourcesContent":["// Provider and hooks\nexport {\n AuthProvider,\n useAuth,\n useIsAuthenticated,\n useUser,\n} from \"./auth-provider\";\nexport type { AuthContextValue, AuthProviderProps } from \"./auth-provider\";\n\n// Auth client\nexport { AuthClient, createAuthClient } from \"./auth-client\";\n\n// Storage adapters\nexport { LocalStorageAdapter, MemoryStorageAdapter } from \"./storage\";\n\n// Re-export shared types for convenience\nexport type {\n AuthClientConfig,\n AuthEndpoints,\n AuthState,\n AuthTokens,\n BaseUser,\n LoginCredentials,\n RegisterData,\n TokenStorage,\n} from \"../shared\";\n\nexport { DEFAULT_AUTH_ENDPOINTS, TOKEN_STORAGE_KEYS } from \"../shared\";\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\nimport type {\n AuthEndpoints,\n AuthState,\n BaseUser,\n TokenStorage,\n} from \"../shared\";\nimport { AuthClient } from \"./auth-client\";\nimport { LocalStorageAdapter } from \"./storage\";\n\n/**\n * Auth context value interface\n */\nexport interface AuthContextValue<\n TUser extends BaseUser = BaseUser,\n> extends AuthState<TUser> {\n /** Login with email and password */\n login: (email: string, password: string) => Promise<void>;\n /** Register a new user */\n register: (\n email: string,\n password: string,\n confirmPassword?: string,\n ) => Promise<void>;\n /** Logout the current user */\n logout: () => Promise<void>;\n /** Manually refresh tokens */\n refreshToken: () => Promise<void>;\n /** Clear any auth errors */\n clearError: () => void;\n /** The auth client instance */\n client: AuthClient;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n/**\n * Auth provider configuration\n */\nexport interface AuthProviderProps {\n /** Base URL for auth API endpoints */\n baseUrl: string;\n /** Token storage implementation (defaults to localStorage) */\n tokenStorage?: TokenStorage;\n /** Custom auth endpoints */\n endpoints?: Partial<AuthEndpoints>;\n /** Custom headers for requests */\n headers?: Record<string, string>;\n /** Children to render */\n children: ReactNode;\n /** Callback when auth state changes */\n onAuthStateChange?: (state: AuthState) => void;\n /** Whether to automatically refresh token on mount */\n autoRefresh?: boolean;\n}\n\n/**\n * Auth provider component\n * Wraps your app and provides auth state and methods via context\n *\n * @example\n * ```tsx\n * <AuthProvider baseUrl=\"https://api.example.com\">\n * <App />\n * </AuthProvider>\n * ```\n */\nexport function AuthProvider<TUser extends BaseUser = BaseUser>({\n baseUrl,\n tokenStorage,\n endpoints,\n headers,\n children,\n onAuthStateChange,\n autoRefresh = true,\n}: AuthProviderProps) {\n const [state, setState] = useState<AuthState<TUser>>({\n user: null,\n tokens: null,\n isLoading: true,\n isAuthenticated: false,\n error: null,\n });\n\n // Create the auth client\n const client = useMemo(() => {\n const storage = tokenStorage ?? new LocalStorageAdapter();\n return new AuthClient(\n { baseUrl, tokenStorage: storage, headers },\n endpoints,\n );\n }, [baseUrl, tokenStorage, endpoints, headers]);\n\n // Update state helper\n const updateState = useCallback(\n (updates: Partial<AuthState<TUser>>) => {\n setState((prev) => {\n const newState = { ...prev, ...updates };\n onAuthStateChange?.(newState);\n return newState;\n });\n },\n [onAuthStateChange],\n );\n\n // Initialize auth state on mount\n useEffect(() => {\n const initAuth = async () => {\n try {\n const hasTokens = await client.hasTokens();\n\n if (!hasTokens) {\n updateState({ isLoading: false });\n return;\n }\n\n // Try to get current user\n const user = await client.me<TUser>();\n\n if (user) {\n const tokens = await client.getTokens();\n updateState({\n user,\n tokens,\n isAuthenticated: true,\n isLoading: false,\n });\n } else if (autoRefresh) {\n // Try to refresh tokens\n const newTokens = await client.refresh();\n if (newTokens) {\n const refreshedUser = await client.me<TUser>();\n updateState({\n user: refreshedUser,\n tokens: newTokens,\n isAuthenticated: !!refreshedUser,\n isLoading: false,\n });\n } else {\n updateState({ isLoading: false });\n }\n } else {\n updateState({ isLoading: false });\n }\n } catch (error) {\n updateState({\n isLoading: false,\n error:\n error instanceof Error\n ? error.message\n : \"Failed to initialize auth\",\n });\n }\n };\n\n initAuth();\n }, [client, autoRefresh, updateState]);\n\n // Login handler\n const login = useCallback(\n async (email: string, password: string) => {\n updateState({ isLoading: true, error: null });\n\n try {\n const tokens = await client.login(email, password);\n const user = await client.me<TUser>();\n\n updateState({\n user,\n tokens,\n isAuthenticated: true,\n isLoading: false,\n });\n } catch (error) {\n updateState({\n isLoading: false,\n error: error instanceof Error ? error.message : \"Login failed\",\n });\n throw error;\n }\n },\n [client, updateState],\n );\n\n // Register handler\n const register = useCallback(\n async (email: string, password: string, confirmPassword?: string) => {\n updateState({ isLoading: true, error: null });\n\n try {\n const tokens = await client.register(email, password, confirmPassword);\n const user = await client.me<TUser>();\n\n updateState({\n user,\n tokens,\n isAuthenticated: true,\n isLoading: false,\n });\n } catch (error) {\n updateState({\n isLoading: false,\n error: error instanceof Error ? error.message : \"Registration failed\",\n });\n throw error;\n }\n },\n [client, updateState],\n );\n\n // Logout handler\n const logout = useCallback(async () => {\n updateState({ isLoading: true, error: null });\n\n try {\n await client.logout();\n\n updateState({\n user: null,\n tokens: null,\n isAuthenticated: false,\n isLoading: false,\n });\n } catch (error) {\n // Still clear local state even if logout API fails\n updateState({\n user: null,\n tokens: null,\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Logout failed\",\n });\n }\n }, [client, updateState]);\n\n // Refresh token handler\n const refreshToken = useCallback(async () => {\n try {\n const tokens = await client.refresh();\n\n if (tokens) {\n const user = await client.me<TUser>();\n updateState({\n user,\n tokens,\n isAuthenticated: !!user,\n });\n } else {\n updateState({\n user: null,\n tokens: null,\n isAuthenticated: false,\n });\n }\n } catch (error) {\n updateState({\n user: null,\n tokens: null,\n isAuthenticated: false,\n error: error instanceof Error ? error.message : \"Token refresh failed\",\n });\n }\n }, [client, updateState]);\n\n // Clear error handler\n const clearError = useCallback(() => {\n updateState({ error: null });\n }, [updateState]);\n\n // Memoize context value\n const contextValue = useMemo<AuthContextValue<TUser>>(\n () => ({\n ...state,\n login,\n register,\n logout,\n refreshToken,\n clearError,\n client,\n }),\n [state, login, register, logout, refreshToken, clearError, client],\n );\n\n return (\n <AuthContext.Provider value={contextValue as AuthContextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\n/**\n * Hook to access auth context\n * Must be used within an AuthProvider\n *\n * @example\n * ```tsx\n * function LoginButton() {\n * const { login, isLoading, error } = useAuth();\n *\n * const handleLogin = async () => {\n * await login('user@example.com', 'password');\n * };\n *\n * return (\n * <button onClick={handleLogin} disabled={isLoading}>\n * {isLoading ? 'Logging in...' : 'Login'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useAuth<\n TUser extends BaseUser = BaseUser,\n>(): AuthContextValue<TUser> {\n const context = useContext(AuthContext);\n\n if (!context) {\n throw new Error(\"useAuth must be used within an AuthProvider\");\n }\n\n return context as AuthContextValue<TUser>;\n}\n\n/**\n * Hook to get the current authenticated user\n * Returns null if not authenticated\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const user = useUser();\n *\n * if (!user) {\n * return <div>Not logged in</div>;\n * }\n *\n * return <div>Welcome, {user.email}!</div>;\n * }\n * ```\n */\nexport function useUser<TUser extends BaseUser = BaseUser>(): TUser | null {\n const { user } = useAuth<TUser>();\n return user;\n}\n\n/**\n * Hook to check if user is authenticated\n *\n * @example\n * ```tsx\n * function ProtectedRoute({ children }) {\n * const isAuthenticated = useIsAuthenticated();\n *\n * if (!isAuthenticated) {\n * return <Navigate to=\"/login\" />;\n * }\n *\n * return children;\n * }\n * ```\n */\nexport function useIsAuthenticated(): boolean {\n const { isAuthenticated, isLoading } = useAuth();\n return isAuthenticated && !isLoading;\n}\n","/**\n * JWT payload structure\n */\nexport interface JwtPayload {\n /** User ID (subject) */\n sub: string;\n /** User email */\n email: string;\n /** Issued at timestamp */\n iat?: number;\n /** Expiration timestamp */\n exp?: number;\n}\n\n/**\n * Token response containing access and refresh tokens\n */\nexport interface AuthTokens {\n /** Short-lived access token */\n accessToken: string;\n /** Long-lived refresh token */\n refreshToken: string;\n}\n\n/**\n * Base user interface - minimal fields required by the auth system\n * Consumers should extend this with their own user properties\n */\nexport interface BaseUser {\n /** Unique user identifier */\n id: string;\n /** User email address */\n email: string;\n}\n\n/**\n * User with password hash - used internally for authentication\n */\nexport interface UserWithPassword extends BaseUser {\n /** Bcrypt hashed password */\n passwordHash: string;\n}\n\n/**\n * User with refresh token - used for token refresh operations\n */\nexport interface UserWithRefreshToken extends BaseUser {\n /** Hashed refresh token (nullable when logged out) */\n hashedRefreshToken: string | null;\n}\n\n/**\n * Full auth user interface combining all auth-related fields\n */\nexport interface AuthUser extends BaseUser {\n passwordHash: string;\n hashedRefreshToken: string | null;\n}\n\n/**\n * Login credentials\n */\nexport interface LoginCredentials {\n email: string;\n password: string;\n}\n\n/**\n * Registration data\n */\nexport interface RegisterData {\n email: string;\n password: string;\n}\n\n/**\n * Auth state for frontend applications\n */\nexport interface AuthState<TUser extends BaseUser = BaseUser> {\n /** Current authenticated user or null */\n user: TUser | null;\n /** Current tokens or null */\n tokens: AuthTokens | null;\n /** Whether auth state is being loaded/validated */\n isLoading: boolean;\n /** Whether user is authenticated */\n isAuthenticated: boolean;\n /** Auth error if any */\n error: string | null;\n}\n\n/**\n * Token storage interface for frontend applications\n * Implement this to use different storage backends (localStorage, SecureStore, etc.)\n */\nexport interface TokenStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * Auth client configuration for frontend HTTP client\n */\nexport interface AuthClientConfig {\n /** Base URL for auth API endpoints */\n baseUrl: string;\n /** Token storage implementation */\n tokenStorage: TokenStorage;\n /** Custom headers to include in requests */\n headers?: Record<string, string>;\n /** Access token storage key (default: 'lenan_access_token') */\n accessTokenKey?: string;\n /** Refresh token storage key (default: 'lenan_refresh_token') */\n refreshTokenKey?: string;\n}\n\n/**\n * Auth API endpoints configuration\n */\nexport interface AuthEndpoints {\n login: string;\n register: string;\n refresh: string;\n logout: string;\n me: string;\n}\n\n/**\n * Default auth endpoints\n */\nexport const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints = {\n login: \"/auth/login\",\n register: \"/auth/register\",\n refresh: \"/auth/refresh\",\n logout: \"/auth/logout\",\n me: \"/auth/me\",\n};\n\n/**\n * Default token storage keys\n */\nexport const TOKEN_STORAGE_KEYS = {\n ACCESS_TOKEN: \"lenan_access_token\",\n REFRESH_TOKEN: \"lenan_refresh_token\",\n} as const;\n","import type {\n AuthClientConfig,\n AuthEndpoints,\n AuthTokens,\n BaseUser,\n} from \"../shared\";\nimport { DEFAULT_AUTH_ENDPOINTS, TOKEN_STORAGE_KEYS } from \"../shared\";\n\n/**\n * Auth HTTP client for making authenticated requests\n * Handles token management, automatic refresh, and request/response handling\n */\nexport class AuthClient {\n private config: AuthClientConfig;\n private endpoints: AuthEndpoints;\n private accessTokenKey: string;\n private refreshTokenKey: string;\n private isRefreshing = false;\n private refreshPromise: Promise<AuthTokens | null> | null = null;\n\n constructor(config: AuthClientConfig, endpoints?: Partial<AuthEndpoints>) {\n this.config = config;\n this.endpoints = { ...DEFAULT_AUTH_ENDPOINTS, ...endpoints };\n this.accessTokenKey =\n config.accessTokenKey ?? TOKEN_STORAGE_KEYS.ACCESS_TOKEN;\n this.refreshTokenKey =\n config.refreshTokenKey ?? TOKEN_STORAGE_KEYS.REFRESH_TOKEN;\n }\n\n /**\n * Make an authenticated request\n * Automatically attaches access token and handles 401 refresh\n */\n async request<T = any>(path: string, options: RequestInit = {}): Promise<T> {\n const accessToken = await this.getAccessToken();\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...this.config.headers,\n ...((options.headers as Record<string, string>) || {}),\n };\n\n if (accessToken) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n }\n\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n ...options,\n headers,\n });\n\n // Handle 401 - try to refresh token\n if (response.status === 401 && accessToken) {\n const refreshed = await this.tryRefreshToken();\n if (refreshed) {\n // Retry the request with new token\n headers[\"Authorization\"] = `Bearer ${refreshed.accessToken}`;\n const retryResponse = await fetch(`${this.config.baseUrl}${path}`, {\n ...options,\n headers,\n });\n return this.handleResponse(retryResponse);\n }\n }\n\n return this.handleResponse(response);\n }\n\n /**\n * Login with email and password\n */\n async login(email: string, password: string): Promise<AuthTokens> {\n const response = await fetch(\n `${this.config.baseUrl}${this.endpoints.login}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.config.headers,\n },\n body: JSON.stringify({ email, password }),\n },\n );\n\n const tokens = await this.handleResponse<AuthTokens>(response);\n await this.storeTokens(tokens);\n return tokens;\n }\n\n /**\n * Register a new user\n */\n async register(\n email: string,\n password: string,\n confirmPassword?: string,\n ): Promise<AuthTokens> {\n const response = await fetch(\n `${this.config.baseUrl}${this.endpoints.register}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.config.headers,\n },\n body: JSON.stringify({\n email,\n password,\n confirmPassword: confirmPassword ?? password,\n }),\n },\n );\n\n const tokens = await this.handleResponse<AuthTokens>(response);\n await this.storeTokens(tokens);\n return tokens;\n }\n\n /**\n * Refresh the access token\n */\n async refresh(): Promise<AuthTokens | null> {\n const refreshToken = await this.getRefreshToken();\n if (!refreshToken) {\n return null;\n }\n\n try {\n const response = await fetch(\n `${this.config.baseUrl}${this.endpoints.refresh}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.config.headers,\n },\n body: JSON.stringify({ refreshToken }),\n },\n );\n\n if (!response.ok) {\n await this.clearTokens();\n return null;\n }\n\n const tokens = (await response.json()) as AuthTokens;\n await this.storeTokens(tokens);\n return tokens;\n } catch {\n await this.clearTokens();\n return null;\n }\n }\n\n /**\n * Logout the user\n */\n async logout(): Promise<void> {\n const accessToken = await this.getAccessToken();\n\n if (accessToken) {\n try {\n await fetch(`${this.config.baseUrl}${this.endpoints.logout}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n ...this.config.headers,\n },\n });\n } catch {\n // Ignore logout errors - still clear local tokens\n }\n }\n\n await this.clearTokens();\n }\n\n /**\n * Get the current user\n */\n async me<TUser extends BaseUser = BaseUser>(): Promise<TUser | null> {\n const accessToken = await this.getAccessToken();\n if (!accessToken) {\n return null;\n }\n\n try {\n const response = await this.request<TUser>(this.endpoints.me);\n return response;\n } catch {\n return null;\n }\n }\n\n /**\n * Check if user has tokens stored\n */\n async hasTokens(): Promise<boolean> {\n const accessToken = await this.getAccessToken();\n return !!accessToken;\n }\n\n /**\n * Get stored tokens\n */\n async getTokens(): Promise<AuthTokens | null> {\n const [accessToken, refreshToken] = await Promise.all([\n this.getAccessToken(),\n this.getRefreshToken(),\n ]);\n\n if (!accessToken || !refreshToken) {\n return null;\n }\n\n return { accessToken, refreshToken };\n }\n\n private async tryRefreshToken(): Promise<AuthTokens | null> {\n // Prevent multiple simultaneous refresh attempts\n if (this.isRefreshing) {\n return this.refreshPromise;\n }\n\n this.isRefreshing = true;\n this.refreshPromise = this.refresh();\n\n try {\n const result = await this.refreshPromise;\n return result;\n } finally {\n this.isRefreshing = false;\n this.refreshPromise = null;\n }\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n let errorMessage = `Request failed with status ${response.status}`;\n\n try {\n const errorBody = await response.json();\n if (typeof errorBody === \"object\" && errorBody !== null) {\n const body = errorBody as Record<string, unknown>;\n if (typeof body.message === \"string\") {\n errorMessage = body.message;\n } else if (typeof body.error === \"string\") {\n errorMessage = body.error;\n }\n }\n } catch {\n // Ignore JSON parse errors\n }\n\n throw new Error(errorMessage);\n }\n\n // Handle empty responses\n const text = await response.text();\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n private async getAccessToken(): Promise<string | null> {\n return Promise.resolve(\n this.config.tokenStorage.getItem(this.accessTokenKey),\n );\n }\n\n private async getRefreshToken(): Promise<string | null> {\n return Promise.resolve(\n this.config.tokenStorage.getItem(this.refreshTokenKey),\n );\n }\n\n private async storeTokens(tokens: AuthTokens): Promise<void> {\n await Promise.all([\n this.config.tokenStorage.setItem(this.accessTokenKey, tokens.accessToken),\n this.config.tokenStorage.setItem(\n this.refreshTokenKey,\n tokens.refreshToken,\n ),\n ]);\n }\n\n private async clearTokens(): Promise<void> {\n await Promise.all([\n this.config.tokenStorage.removeItem(this.accessTokenKey),\n this.config.tokenStorage.removeItem(this.refreshTokenKey),\n ]);\n }\n}\n\n/**\n * Create an auth client instance\n */\nexport function createAuthClient(\n config: AuthClientConfig,\n endpoints?: Partial<AuthEndpoints>,\n): AuthClient {\n return new AuthClient(config, endpoints);\n}\n","import type { TokenStorage } from \"../shared\";\n\n/**\n * localStorage-based token storage for web browsers\n * Falls back to in-memory storage if localStorage is not available\n */\nexport class LocalStorageAdapter implements TokenStorage {\n private memoryStorage: Map<string, string> = new Map();\n private isLocalStorageAvailable: boolean;\n\n constructor() {\n this.isLocalStorageAvailable = this.checkLocalStorage();\n }\n\n private checkLocalStorage(): boolean {\n try {\n const testKey = \"__lenan_auth_test__\";\n localStorage.setItem(testKey, testKey);\n localStorage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n }\n\n getItem(key: string): string | null {\n if (this.isLocalStorageAvailable) {\n return localStorage.getItem(key);\n }\n return this.memoryStorage.get(key) ?? null;\n }\n\n setItem(key: string, value: string): void {\n if (this.isLocalStorageAvailable) {\n localStorage.setItem(key, value);\n } else {\n this.memoryStorage.set(key, value);\n }\n }\n\n removeItem(key: string): void {\n if (this.isLocalStorageAvailable) {\n localStorage.removeItem(key);\n } else {\n this.memoryStorage.delete(key);\n }\n }\n}\n\n/**\n * In-memory token storage for server-side rendering or testing\n */\nexport class MemoryStorageAdapter implements TokenStorage {\n private storage: Map<string, string> = new Map();\n\n getItem(key: string): string | null {\n return this.storage.get(key) ?? null;\n }\n\n setItem(key: string, value: string): void {\n this.storage.set(key, value);\n }\n\n removeItem(key: string): void {\n this.storage.delete(key);\n }\n\n clear(): void {\n this.storage.clear();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,285 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Token response containing access and refresh tokens
6
+ */
7
+ interface AuthTokens {
8
+ /** Short-lived access token */
9
+ accessToken: string;
10
+ /** Long-lived refresh token */
11
+ refreshToken: string;
12
+ }
13
+ /**
14
+ * Base user interface - minimal fields required by the auth system
15
+ * Consumers should extend this with their own user properties
16
+ */
17
+ interface BaseUser {
18
+ /** Unique user identifier */
19
+ id: string;
20
+ /** User email address */
21
+ email: string;
22
+ }
23
+ /**
24
+ * Login credentials
25
+ */
26
+ interface LoginCredentials {
27
+ email: string;
28
+ password: string;
29
+ }
30
+ /**
31
+ * Registration data
32
+ */
33
+ interface RegisterData {
34
+ email: string;
35
+ password: string;
36
+ }
37
+ /**
38
+ * Auth state for frontend applications
39
+ */
40
+ interface AuthState<TUser extends BaseUser = BaseUser> {
41
+ /** Current authenticated user or null */
42
+ user: TUser | null;
43
+ /** Current tokens or null */
44
+ tokens: AuthTokens | null;
45
+ /** Whether auth state is being loaded/validated */
46
+ isLoading: boolean;
47
+ /** Whether user is authenticated */
48
+ isAuthenticated: boolean;
49
+ /** Auth error if any */
50
+ error: string | null;
51
+ }
52
+ /**
53
+ * Token storage interface for frontend applications
54
+ * Implement this to use different storage backends (localStorage, SecureStore, etc.)
55
+ */
56
+ interface TokenStorage {
57
+ getItem(key: string): Promise<string | null> | string | null;
58
+ setItem(key: string, value: string): Promise<void> | void;
59
+ removeItem(key: string): Promise<void> | void;
60
+ }
61
+ /**
62
+ * Auth client configuration for frontend HTTP client
63
+ */
64
+ interface AuthClientConfig {
65
+ /** Base URL for auth API endpoints */
66
+ baseUrl: string;
67
+ /** Token storage implementation */
68
+ tokenStorage: TokenStorage;
69
+ /** Custom headers to include in requests */
70
+ headers?: Record<string, string>;
71
+ /** Access token storage key (default: 'lenan_access_token') */
72
+ accessTokenKey?: string;
73
+ /** Refresh token storage key (default: 'lenan_refresh_token') */
74
+ refreshTokenKey?: string;
75
+ }
76
+ /**
77
+ * Auth API endpoints configuration
78
+ */
79
+ interface AuthEndpoints {
80
+ login: string;
81
+ register: string;
82
+ refresh: string;
83
+ logout: string;
84
+ me: string;
85
+ }
86
+ /**
87
+ * Default auth endpoints
88
+ */
89
+ declare const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints;
90
+ /**
91
+ * Default token storage keys
92
+ */
93
+ declare const TOKEN_STORAGE_KEYS: {
94
+ readonly ACCESS_TOKEN: "lenan_access_token";
95
+ readonly REFRESH_TOKEN: "lenan_refresh_token";
96
+ };
97
+
98
+ /**
99
+ * Auth HTTP client for making authenticated requests
100
+ * Handles token management, automatic refresh, and request/response handling
101
+ */
102
+ declare class AuthClient {
103
+ private config;
104
+ private endpoints;
105
+ private accessTokenKey;
106
+ private refreshTokenKey;
107
+ private isRefreshing;
108
+ private refreshPromise;
109
+ constructor(config: AuthClientConfig, endpoints?: Partial<AuthEndpoints>);
110
+ /**
111
+ * Make an authenticated request
112
+ * Automatically attaches access token and handles 401 refresh
113
+ */
114
+ request<T = any>(path: string, options?: RequestInit): Promise<T>;
115
+ /**
116
+ * Login with email and password
117
+ */
118
+ login(email: string, password: string): Promise<AuthTokens>;
119
+ /**
120
+ * Register a new user
121
+ */
122
+ register(email: string, password: string, confirmPassword?: string): Promise<AuthTokens>;
123
+ /**
124
+ * Refresh the access token
125
+ */
126
+ refresh(): Promise<AuthTokens | null>;
127
+ /**
128
+ * Logout the user
129
+ */
130
+ logout(): Promise<void>;
131
+ /**
132
+ * Get the current user
133
+ */
134
+ me<TUser extends BaseUser = BaseUser>(): Promise<TUser | null>;
135
+ /**
136
+ * Check if user has tokens stored
137
+ */
138
+ hasTokens(): Promise<boolean>;
139
+ /**
140
+ * Get stored tokens
141
+ */
142
+ getTokens(): Promise<AuthTokens | null>;
143
+ private tryRefreshToken;
144
+ private handleResponse;
145
+ private getAccessToken;
146
+ private getRefreshToken;
147
+ private storeTokens;
148
+ private clearTokens;
149
+ }
150
+ /**
151
+ * Create an auth client instance
152
+ */
153
+ declare function createAuthClient(config: AuthClientConfig, endpoints?: Partial<AuthEndpoints>): AuthClient;
154
+
155
+ /**
156
+ * Auth context value interface
157
+ */
158
+ interface AuthContextValue<TUser extends BaseUser = BaseUser> extends AuthState<TUser> {
159
+ /** Login with email and password */
160
+ login: (email: string, password: string) => Promise<void>;
161
+ /** Register a new user */
162
+ register: (email: string, password: string, confirmPassword?: string) => Promise<void>;
163
+ /** Logout the current user */
164
+ logout: () => Promise<void>;
165
+ /** Manually refresh tokens */
166
+ refreshToken: () => Promise<void>;
167
+ /** Clear any auth errors */
168
+ clearError: () => void;
169
+ /** The auth client instance */
170
+ client: AuthClient;
171
+ }
172
+ /**
173
+ * Auth provider configuration
174
+ */
175
+ interface AuthProviderProps {
176
+ /** Base URL for auth API endpoints */
177
+ baseUrl: string;
178
+ /** Token storage implementation (defaults to localStorage) */
179
+ tokenStorage?: TokenStorage;
180
+ /** Custom auth endpoints */
181
+ endpoints?: Partial<AuthEndpoints>;
182
+ /** Custom headers for requests */
183
+ headers?: Record<string, string>;
184
+ /** Children to render */
185
+ children: ReactNode;
186
+ /** Callback when auth state changes */
187
+ onAuthStateChange?: (state: AuthState) => void;
188
+ /** Whether to automatically refresh token on mount */
189
+ autoRefresh?: boolean;
190
+ }
191
+ /**
192
+ * Auth provider component
193
+ * Wraps your app and provides auth state and methods via context
194
+ *
195
+ * @example
196
+ * ```tsx
197
+ * <AuthProvider baseUrl="https://api.example.com">
198
+ * <App />
199
+ * </AuthProvider>
200
+ * ```
201
+ */
202
+ declare function AuthProvider<TUser extends BaseUser = BaseUser>({ baseUrl, tokenStorage, endpoints, headers, children, onAuthStateChange, autoRefresh, }: AuthProviderProps): react_jsx_runtime.JSX.Element;
203
+ /**
204
+ * Hook to access auth context
205
+ * Must be used within an AuthProvider
206
+ *
207
+ * @example
208
+ * ```tsx
209
+ * function LoginButton() {
210
+ * const { login, isLoading, error } = useAuth();
211
+ *
212
+ * const handleLogin = async () => {
213
+ * await login('user@example.com', 'password');
214
+ * };
215
+ *
216
+ * return (
217
+ * <button onClick={handleLogin} disabled={isLoading}>
218
+ * {isLoading ? 'Logging in...' : 'Login'}
219
+ * </button>
220
+ * );
221
+ * }
222
+ * ```
223
+ */
224
+ declare function useAuth<TUser extends BaseUser = BaseUser>(): AuthContextValue<TUser>;
225
+ /**
226
+ * Hook to get the current authenticated user
227
+ * Returns null if not authenticated
228
+ *
229
+ * @example
230
+ * ```tsx
231
+ * function UserProfile() {
232
+ * const user = useUser();
233
+ *
234
+ * if (!user) {
235
+ * return <div>Not logged in</div>;
236
+ * }
237
+ *
238
+ * return <div>Welcome, {user.email}!</div>;
239
+ * }
240
+ * ```
241
+ */
242
+ declare function useUser<TUser extends BaseUser = BaseUser>(): TUser | null;
243
+ /**
244
+ * Hook to check if user is authenticated
245
+ *
246
+ * @example
247
+ * ```tsx
248
+ * function ProtectedRoute({ children }) {
249
+ * const isAuthenticated = useIsAuthenticated();
250
+ *
251
+ * if (!isAuthenticated) {
252
+ * return <Navigate to="/login" />;
253
+ * }
254
+ *
255
+ * return children;
256
+ * }
257
+ * ```
258
+ */
259
+ declare function useIsAuthenticated(): boolean;
260
+
261
+ /**
262
+ * localStorage-based token storage for web browsers
263
+ * Falls back to in-memory storage if localStorage is not available
264
+ */
265
+ declare class LocalStorageAdapter implements TokenStorage {
266
+ private memoryStorage;
267
+ private isLocalStorageAvailable;
268
+ constructor();
269
+ private checkLocalStorage;
270
+ getItem(key: string): string | null;
271
+ setItem(key: string, value: string): void;
272
+ removeItem(key: string): void;
273
+ }
274
+ /**
275
+ * In-memory token storage for server-side rendering or testing
276
+ */
277
+ declare class MemoryStorageAdapter implements TokenStorage {
278
+ private storage;
279
+ getItem(key: string): string | null;
280
+ setItem(key: string, value: string): void;
281
+ removeItem(key: string): void;
282
+ clear(): void;
283
+ }
284
+
285
+ export { AuthClient, type AuthClientConfig, type AuthContextValue, type AuthEndpoints, AuthProvider, type AuthProviderProps, type AuthState, type AuthTokens, type BaseUser, DEFAULT_AUTH_ENDPOINTS, LocalStorageAdapter, type LoginCredentials, MemoryStorageAdapter, type RegisterData, TOKEN_STORAGE_KEYS, type TokenStorage, createAuthClient, useAuth, useIsAuthenticated, useUser };
@@ -0,0 +1,285 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Token response containing access and refresh tokens
6
+ */
7
+ interface AuthTokens {
8
+ /** Short-lived access token */
9
+ accessToken: string;
10
+ /** Long-lived refresh token */
11
+ refreshToken: string;
12
+ }
13
+ /**
14
+ * Base user interface - minimal fields required by the auth system
15
+ * Consumers should extend this with their own user properties
16
+ */
17
+ interface BaseUser {
18
+ /** Unique user identifier */
19
+ id: string;
20
+ /** User email address */
21
+ email: string;
22
+ }
23
+ /**
24
+ * Login credentials
25
+ */
26
+ interface LoginCredentials {
27
+ email: string;
28
+ password: string;
29
+ }
30
+ /**
31
+ * Registration data
32
+ */
33
+ interface RegisterData {
34
+ email: string;
35
+ password: string;
36
+ }
37
+ /**
38
+ * Auth state for frontend applications
39
+ */
40
+ interface AuthState<TUser extends BaseUser = BaseUser> {
41
+ /** Current authenticated user or null */
42
+ user: TUser | null;
43
+ /** Current tokens or null */
44
+ tokens: AuthTokens | null;
45
+ /** Whether auth state is being loaded/validated */
46
+ isLoading: boolean;
47
+ /** Whether user is authenticated */
48
+ isAuthenticated: boolean;
49
+ /** Auth error if any */
50
+ error: string | null;
51
+ }
52
+ /**
53
+ * Token storage interface for frontend applications
54
+ * Implement this to use different storage backends (localStorage, SecureStore, etc.)
55
+ */
56
+ interface TokenStorage {
57
+ getItem(key: string): Promise<string | null> | string | null;
58
+ setItem(key: string, value: string): Promise<void> | void;
59
+ removeItem(key: string): Promise<void> | void;
60
+ }
61
+ /**
62
+ * Auth client configuration for frontend HTTP client
63
+ */
64
+ interface AuthClientConfig {
65
+ /** Base URL for auth API endpoints */
66
+ baseUrl: string;
67
+ /** Token storage implementation */
68
+ tokenStorage: TokenStorage;
69
+ /** Custom headers to include in requests */
70
+ headers?: Record<string, string>;
71
+ /** Access token storage key (default: 'lenan_access_token') */
72
+ accessTokenKey?: string;
73
+ /** Refresh token storage key (default: 'lenan_refresh_token') */
74
+ refreshTokenKey?: string;
75
+ }
76
+ /**
77
+ * Auth API endpoints configuration
78
+ */
79
+ interface AuthEndpoints {
80
+ login: string;
81
+ register: string;
82
+ refresh: string;
83
+ logout: string;
84
+ me: string;
85
+ }
86
+ /**
87
+ * Default auth endpoints
88
+ */
89
+ declare const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints;
90
+ /**
91
+ * Default token storage keys
92
+ */
93
+ declare const TOKEN_STORAGE_KEYS: {
94
+ readonly ACCESS_TOKEN: "lenan_access_token";
95
+ readonly REFRESH_TOKEN: "lenan_refresh_token";
96
+ };
97
+
98
+ /**
99
+ * Auth HTTP client for making authenticated requests
100
+ * Handles token management, automatic refresh, and request/response handling
101
+ */
102
+ declare class AuthClient {
103
+ private config;
104
+ private endpoints;
105
+ private accessTokenKey;
106
+ private refreshTokenKey;
107
+ private isRefreshing;
108
+ private refreshPromise;
109
+ constructor(config: AuthClientConfig, endpoints?: Partial<AuthEndpoints>);
110
+ /**
111
+ * Make an authenticated request
112
+ * Automatically attaches access token and handles 401 refresh
113
+ */
114
+ request<T = any>(path: string, options?: RequestInit): Promise<T>;
115
+ /**
116
+ * Login with email and password
117
+ */
118
+ login(email: string, password: string): Promise<AuthTokens>;
119
+ /**
120
+ * Register a new user
121
+ */
122
+ register(email: string, password: string, confirmPassword?: string): Promise<AuthTokens>;
123
+ /**
124
+ * Refresh the access token
125
+ */
126
+ refresh(): Promise<AuthTokens | null>;
127
+ /**
128
+ * Logout the user
129
+ */
130
+ logout(): Promise<void>;
131
+ /**
132
+ * Get the current user
133
+ */
134
+ me<TUser extends BaseUser = BaseUser>(): Promise<TUser | null>;
135
+ /**
136
+ * Check if user has tokens stored
137
+ */
138
+ hasTokens(): Promise<boolean>;
139
+ /**
140
+ * Get stored tokens
141
+ */
142
+ getTokens(): Promise<AuthTokens | null>;
143
+ private tryRefreshToken;
144
+ private handleResponse;
145
+ private getAccessToken;
146
+ private getRefreshToken;
147
+ private storeTokens;
148
+ private clearTokens;
149
+ }
150
+ /**
151
+ * Create an auth client instance
152
+ */
153
+ declare function createAuthClient(config: AuthClientConfig, endpoints?: Partial<AuthEndpoints>): AuthClient;
154
+
155
+ /**
156
+ * Auth context value interface
157
+ */
158
+ interface AuthContextValue<TUser extends BaseUser = BaseUser> extends AuthState<TUser> {
159
+ /** Login with email and password */
160
+ login: (email: string, password: string) => Promise<void>;
161
+ /** Register a new user */
162
+ register: (email: string, password: string, confirmPassword?: string) => Promise<void>;
163
+ /** Logout the current user */
164
+ logout: () => Promise<void>;
165
+ /** Manually refresh tokens */
166
+ refreshToken: () => Promise<void>;
167
+ /** Clear any auth errors */
168
+ clearError: () => void;
169
+ /** The auth client instance */
170
+ client: AuthClient;
171
+ }
172
+ /**
173
+ * Auth provider configuration
174
+ */
175
+ interface AuthProviderProps {
176
+ /** Base URL for auth API endpoints */
177
+ baseUrl: string;
178
+ /** Token storage implementation (defaults to localStorage) */
179
+ tokenStorage?: TokenStorage;
180
+ /** Custom auth endpoints */
181
+ endpoints?: Partial<AuthEndpoints>;
182
+ /** Custom headers for requests */
183
+ headers?: Record<string, string>;
184
+ /** Children to render */
185
+ children: ReactNode;
186
+ /** Callback when auth state changes */
187
+ onAuthStateChange?: (state: AuthState) => void;
188
+ /** Whether to automatically refresh token on mount */
189
+ autoRefresh?: boolean;
190
+ }
191
+ /**
192
+ * Auth provider component
193
+ * Wraps your app and provides auth state and methods via context
194
+ *
195
+ * @example
196
+ * ```tsx
197
+ * <AuthProvider baseUrl="https://api.example.com">
198
+ * <App />
199
+ * </AuthProvider>
200
+ * ```
201
+ */
202
+ declare function AuthProvider<TUser extends BaseUser = BaseUser>({ baseUrl, tokenStorage, endpoints, headers, children, onAuthStateChange, autoRefresh, }: AuthProviderProps): react_jsx_runtime.JSX.Element;
203
+ /**
204
+ * Hook to access auth context
205
+ * Must be used within an AuthProvider
206
+ *
207
+ * @example
208
+ * ```tsx
209
+ * function LoginButton() {
210
+ * const { login, isLoading, error } = useAuth();
211
+ *
212
+ * const handleLogin = async () => {
213
+ * await login('user@example.com', 'password');
214
+ * };
215
+ *
216
+ * return (
217
+ * <button onClick={handleLogin} disabled={isLoading}>
218
+ * {isLoading ? 'Logging in...' : 'Login'}
219
+ * </button>
220
+ * );
221
+ * }
222
+ * ```
223
+ */
224
+ declare function useAuth<TUser extends BaseUser = BaseUser>(): AuthContextValue<TUser>;
225
+ /**
226
+ * Hook to get the current authenticated user
227
+ * Returns null if not authenticated
228
+ *
229
+ * @example
230
+ * ```tsx
231
+ * function UserProfile() {
232
+ * const user = useUser();
233
+ *
234
+ * if (!user) {
235
+ * return <div>Not logged in</div>;
236
+ * }
237
+ *
238
+ * return <div>Welcome, {user.email}!</div>;
239
+ * }
240
+ * ```
241
+ */
242
+ declare function useUser<TUser extends BaseUser = BaseUser>(): TUser | null;
243
+ /**
244
+ * Hook to check if user is authenticated
245
+ *
246
+ * @example
247
+ * ```tsx
248
+ * function ProtectedRoute({ children }) {
249
+ * const isAuthenticated = useIsAuthenticated();
250
+ *
251
+ * if (!isAuthenticated) {
252
+ * return <Navigate to="/login" />;
253
+ * }
254
+ *
255
+ * return children;
256
+ * }
257
+ * ```
258
+ */
259
+ declare function useIsAuthenticated(): boolean;
260
+
261
+ /**
262
+ * localStorage-based token storage for web browsers
263
+ * Falls back to in-memory storage if localStorage is not available
264
+ */
265
+ declare class LocalStorageAdapter implements TokenStorage {
266
+ private memoryStorage;
267
+ private isLocalStorageAvailable;
268
+ constructor();
269
+ private checkLocalStorage;
270
+ getItem(key: string): string | null;
271
+ setItem(key: string, value: string): void;
272
+ removeItem(key: string): void;
273
+ }
274
+ /**
275
+ * In-memory token storage for server-side rendering or testing
276
+ */
277
+ declare class MemoryStorageAdapter implements TokenStorage {
278
+ private storage;
279
+ getItem(key: string): string | null;
280
+ setItem(key: string, value: string): void;
281
+ removeItem(key: string): void;
282
+ clear(): void;
283
+ }
284
+
285
+ export { AuthClient, type AuthClientConfig, type AuthContextValue, type AuthEndpoints, AuthProvider, type AuthProviderProps, type AuthState, type AuthTokens, type BaseUser, DEFAULT_AUTH_ENDPOINTS, LocalStorageAdapter, type LoginCredentials, MemoryStorageAdapter, type RegisterData, TOKEN_STORAGE_KEYS, type TokenStorage, createAuthClient, useAuth, useIsAuthenticated, useUser };