@classic-homes/auth 0.1.0

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 ADDED
@@ -0,0 +1,255 @@
1
+ # @classic-homes/auth
2
+
3
+ Framework-agnostic authentication core with Svelte bindings for the Classic Theme design system.
4
+
5
+ ## Features
6
+
7
+ - JWT-based authentication with automatic token refresh
8
+ - SSO (Single Sign-On) support with configurable providers
9
+ - Multi-factor authentication (MFA/TOTP) support
10
+ - Pluggable storage adapter (localStorage, sessionStorage, or custom)
11
+ - Svelte reactive stores for authentication state
12
+ - Route guards for protected pages
13
+ - TypeScript-first with full type safety
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @classic-homes/auth
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### 1. Initialize Authentication
24
+
25
+ In your app's entry point (e.g., `hooks.client.ts` for SvelteKit):
26
+
27
+ ```typescript
28
+ import { initAuth } from '@classic-homes/auth';
29
+
30
+ initAuth({
31
+ baseUrl: 'https://api.example.com',
32
+ storage: {
33
+ getItem: (key) => localStorage.getItem(key),
34
+ setItem: (key, value) => localStorage.setItem(key, value),
35
+ removeItem: (key) => localStorage.removeItem(key),
36
+ },
37
+ onAuthError: (error) => {
38
+ console.error('Auth error:', error);
39
+ },
40
+ });
41
+ ```
42
+
43
+ ### 2. Use the Auth Store (Svelte)
44
+
45
+ ```svelte
46
+ <script lang="ts">
47
+ import { authStore, authActions } from '@classic-homes/auth/svelte';
48
+
49
+ async function handleLogin() {
50
+ await authActions.login({
51
+ email: 'user@example.com',
52
+ password: 'password123',
53
+ });
54
+ }
55
+
56
+ async function handleLogout() {
57
+ await authActions.logout();
58
+ }
59
+ </script>
60
+
61
+ {#if $authStore.isAuthenticated}
62
+ <p>Welcome, {$authStore.user?.email}</p>
63
+ <button onclick={handleLogout}>Logout</button>
64
+ {:else}
65
+ <button onclick={handleLogin}>Login</button>
66
+ {/if}
67
+ ```
68
+
69
+ ### 3. Protect Routes
70
+
71
+ ```typescript
72
+ // src/routes/dashboard/+page.ts
73
+ import { authGuard } from '@classic-homes/auth/svelte';
74
+
75
+ export const load = authGuard({
76
+ redirectTo: '/login',
77
+ });
78
+ ```
79
+
80
+ ## API Reference
81
+
82
+ ### Core Exports
83
+
84
+ ```typescript
85
+ import {
86
+ // Initialization
87
+ initAuth,
88
+ getAuthConfig,
89
+
90
+ // Service
91
+ authService,
92
+ AuthService,
93
+
94
+ // API
95
+ authApi,
96
+
97
+ // Types
98
+ type User,
99
+ type AuthTokens,
100
+ type LoginCredentials,
101
+ type RegisterData,
102
+ type AuthConfig,
103
+ } from '@classic-homes/auth';
104
+ ```
105
+
106
+ ### Svelte Exports
107
+
108
+ ```typescript
109
+ import {
110
+ // Store
111
+ authStore,
112
+ isAuthenticated,
113
+ currentUser,
114
+
115
+ // Actions
116
+ authActions,
117
+
118
+ // Guards
119
+ authGuard,
120
+ roleGuard,
121
+ } from '@classic-homes/auth/svelte';
122
+ ```
123
+
124
+ ## Configuration Options
125
+
126
+ ```typescript
127
+ interface AuthConfig {
128
+ /** Base URL for the auth API */
129
+ baseUrl: string;
130
+
131
+ /** Storage adapter for tokens */
132
+ storage?: {
133
+ getItem: (key: string) => string | null;
134
+ setItem: (key: string, value: string) => void;
135
+ removeItem: (key: string) => void;
136
+ };
137
+
138
+ /** SSO configuration */
139
+ sso?: {
140
+ enabled: boolean;
141
+ provider: string;
142
+ authorizeUrl?: string;
143
+ tokenUrl?: string;
144
+ };
145
+
146
+ /** Callback when auth errors occur */
147
+ onAuthError?: (error: Error) => void;
148
+
149
+ /** Custom headers for API requests */
150
+ headers?: Record<string, string>;
151
+ }
152
+ ```
153
+
154
+ ## Auth Actions
155
+
156
+ The `authActions` object provides methods for authentication operations:
157
+
158
+ ```typescript
159
+ // Login with email/password
160
+ await authActions.login({ email, password, rememberMe });
161
+
162
+ // Register new user
163
+ await authActions.register({ email, password, fullName });
164
+
165
+ // Logout
166
+ await authActions.logout();
167
+
168
+ // Refresh session
169
+ await authActions.refreshSession();
170
+
171
+ // Change password
172
+ await authActions.changePassword({ currentPassword, newPassword });
173
+
174
+ // MFA operations
175
+ await authActions.verifyMfa({ code, trustDevice });
176
+ await authActions.setupMfa({ secret, code });
177
+ await authActions.disableMfa({ password });
178
+
179
+ // SSO
180
+ await authActions.initiateSSO();
181
+ await authActions.handleSSOCallback(code);
182
+ ```
183
+
184
+ ## Auth Store State
185
+
186
+ ```typescript
187
+ interface AuthState {
188
+ user: User | null;
189
+ tokens: AuthTokens | null;
190
+ isAuthenticated: boolean;
191
+ isLoading: boolean;
192
+ error: string | null;
193
+ mfaRequired: boolean;
194
+ mfaToken: string | null;
195
+ }
196
+ ```
197
+
198
+ ## Route Guards
199
+
200
+ ### Basic Auth Guard
201
+
202
+ ```typescript
203
+ import { authGuard } from '@classic-homes/auth/svelte';
204
+
205
+ export const load = authGuard({
206
+ redirectTo: '/login',
207
+ returnUrl: true, // Append ?returnUrl= to redirect
208
+ });
209
+ ```
210
+
211
+ ### Role-Based Guard
212
+
213
+ ```typescript
214
+ import { roleGuard } from '@classic-homes/auth/svelte';
215
+
216
+ export const load = roleGuard({
217
+ roles: ['admin', 'manager'],
218
+ redirectTo: '/unauthorized',
219
+ });
220
+ ```
221
+
222
+ ## Using with @classic-homes/theme-svelte
223
+
224
+ The auth package integrates with the form validation from `@classic-homes/theme-svelte`:
225
+
226
+ ```svelte
227
+ <script lang="ts">
228
+ import { useForm, loginSchema } from '@classic-homes/theme-svelte';
229
+ import { authActions } from '@classic-homes/auth/svelte';
230
+
231
+ const form = useForm({
232
+ schema: loginSchema,
233
+ initialValues: {
234
+ email: '',
235
+ password: '',
236
+ rememberMe: false,
237
+ },
238
+ onSubmit: async (data) => {
239
+ await authActions.login(data);
240
+ },
241
+ });
242
+ </script>
243
+
244
+ <form onsubmit={form.handleSubmit}>
245
+ <input bind:value={form.data.email} />
246
+ {#if form.errors.email}
247
+ <span class="error">{form.errors.email}</span>
248
+ {/if}
249
+ <!-- ... -->
250
+ </form>
251
+ ```
252
+
253
+ ## License
254
+
255
+ MIT