@passkeyme/auth 1.0.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/LICENSE +21 -0
  3. package/README.md +598 -0
  4. package/dist/index.esm.js +5660 -0
  5. package/dist/index.esm.js.map +1 -0
  6. package/dist/index.js +5680 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/index.umd.js +5686 -0
  9. package/dist/index.umd.js.map +1 -0
  10. package/dist/src/api-client.d.ts +56 -0
  11. package/dist/src/api-client.d.ts.map +1 -0
  12. package/dist/src/errors.d.ts +61 -0
  13. package/dist/src/errors.d.ts.map +1 -0
  14. package/dist/src/http-interceptors.d.ts +28 -0
  15. package/dist/src/http-interceptors.d.ts.map +1 -0
  16. package/dist/src/index.d.ts +49 -0
  17. package/dist/src/index.d.ts.map +1 -0
  18. package/dist/src/passkeyme-auth.d.ts +157 -0
  19. package/dist/src/passkeyme-auth.d.ts.map +1 -0
  20. package/dist/src/platform/PasskeySDK.d.ts +112 -0
  21. package/dist/src/platform/PasskeySDK.d.ts.map +1 -0
  22. package/dist/src/platform/ReactNativePasskeySDK.d.ts +42 -0
  23. package/dist/src/platform/ReactNativePasskeySDK.d.ts.map +1 -0
  24. package/dist/src/platform/WebPasskeySDK.d.ts +25 -0
  25. package/dist/src/platform/WebPasskeySDK.d.ts.map +1 -0
  26. package/dist/src/platform/index.d.ts +8 -0
  27. package/dist/src/platform/index.d.ts.map +1 -0
  28. package/dist/src/storage/BrowserStorageProvider.d.ts +14 -0
  29. package/dist/src/storage/BrowserStorageProvider.d.ts.map +1 -0
  30. package/dist/src/storage/StorageProvider.d.ts +32 -0
  31. package/dist/src/storage/StorageProvider.d.ts.map +1 -0
  32. package/dist/src/storage/index.d.ts +6 -0
  33. package/dist/src/storage/index.d.ts.map +1 -0
  34. package/dist/src/token-storage.d.ts +46 -0
  35. package/dist/src/token-storage.d.ts.map +1 -0
  36. package/dist/src/types.d.ts +217 -0
  37. package/dist/src/types.d.ts.map +1 -0
  38. package/dist/src/utils/logger.d.ts +23 -0
  39. package/dist/src/utils/logger.d.ts.map +1 -0
  40. package/dist/test/platform/PasskeySDK.test.d.ts +5 -0
  41. package/dist/test/platform/PasskeySDK.test.d.ts.map +1 -0
  42. package/dist/test/setup.d.ts +13 -0
  43. package/dist/test/setup.d.ts.map +1 -0
  44. package/dist/test/storage/BrowserStorageProvider.test.d.ts +5 -0
  45. package/dist/test/storage/BrowserStorageProvider.test.d.ts.map +1 -0
  46. package/package.json +72 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,93 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ # Changelog
9
+
10
+ All notable changes to this project will be documented in this file.
11
+
12
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
13
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
14
+
15
+ ## [1.0.0] - 2025-07-12
16
+
17
+ ### 🎉 First Stable Release
18
+
19
+ This marks the first stable release of the PasskeyMe Authentication SDK with enterprise-grade quality and comprehensive feature set.
20
+
21
+ ### Added
22
+
23
+ - **Professional Logging System**: Environment-aware structured logging with configurable levels
24
+ - **Enterprise-Grade Build System**: Clean TypeScript compilation with multiple output formats (CommonJS, ESM, UMD)
25
+ - **Comprehensive Test Suite**: 30/30 tests passing with full coverage of core functionality
26
+ - **Code Quality Standards**: Prettier formatting, ESLint linting, and consistent code style
27
+ - **Production-Ready Infrastructure**: Optimized package configuration and publishing setup
28
+ - **TypeScript Documentation**: Comprehensive type definitions and IntelliSense support
29
+ - **Advanced Configuration**: Custom token storage patterns and HTTP interceptor examples
30
+ - **Error Handling**: Robust error handling patterns with custom error types
31
+ - **API Integration**: Comprehensive distribution setup and client integration patterns
32
+
33
+ ### Enhanced
34
+
35
+ - **Bundle Optimization**: Minimal dependencies and optimized output sizes
36
+ - **Developer Experience**: Improved debugging capabilities and development workflow
37
+ - **Documentation**: Complete API reference and usage examples
38
+ - **Security**: Enhanced token management and secure storage patterns
39
+
40
+ ### Fixed
41
+
42
+ - **Memory Leaks**: Resolved potential memory issues in token management
43
+ - **Type Safety**: Improved TypeScript strict mode compliance
44
+ - **Error Handling**: Comprehensive error boundary implementation
45
+
46
+ ## [Unreleased]
47
+ - .npmignore for cleaner package publishing
48
+
49
+ ### Enhanced
50
+
51
+ - README with detailed TypeScript usage patterns
52
+ - API documentation with complete type definitions
53
+ - Framework integration examples
54
+
55
+ ## [0.2.0-beta.2] - 2024-12-07
56
+
57
+ ### Fixed
58
+
59
+ - WebSDK method name compatibility issues
60
+ - Credential serialization for API calls
61
+ - Authentication flow improvements
62
+
63
+ ### Changed
64
+
65
+ - Improved error handling
66
+ - Enhanced debugging capabilities
67
+
68
+ ## [0.2.0-beta.1] - 2024-11-15
69
+
70
+ ### Added
71
+
72
+ - Initial beta release
73
+ - Core authentication functionality
74
+ - OAuth integration (Google, GitHub)
75
+ - Passkey (WebAuthn) support
76
+ - Username/password authentication
77
+ - Hosted authentication pages
78
+ - JWT token management
79
+ - Auto-refresh token handling
80
+ - TypeScript support
81
+
82
+ ### Features
83
+
84
+ - Multiple authentication methods
85
+ - Hosted authentication pages
86
+ - Automatic token management
87
+ - Privacy-first design
88
+ - Self-hosted option
89
+ - Lightweight implementation
90
+
91
+ [Unreleased]: https://github.com/passkeyme/sdk/compare/v0.2.0-beta.2...HEAD
92
+ [0.2.0-beta.2]: https://github.com/passkeyme/sdk/compare/v0.2.0-beta.1...v0.2.0-beta.2
93
+ [0.2.0-beta.1]: https://github.com/passkeyme/sdk/releases/tag/v0.2.0-beta.1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 PasskeyMe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,598 @@
1
+ # @passkeyme/auth
2
+
3
+ A simple, powerful authentication SDK that makes authentication easier than Firebase Auth.
4
+
5
+ ## 🚀 Features
6
+
7
+ - **🔐 Multiple Auth Methods**: OAuth (Google, GitHub), Passkeys (WebAuthn), Username/Password
8
+ - **� Hosted Authentication**: Secure, pre-built auth pages - no UI to build
9
+ - **🔄 Automatic Token Management**: Auto-refresh, HTTP interceptors
10
+ - **🏠 Privacy-First**: Self-hosted option, no vendor lock-in
11
+ - **📱 Modern**: Built-in passkey support, TypeScript-first
12
+ - **⚡ Lightweight**: Pure JavaScript, no heavy dependencies
13
+
14
+ ## 📦 Installation
15
+
16
+ ```bash
17
+ npm install @passkeyme/auth
18
+ ```
19
+
20
+ ## 🔧 Quick Start
21
+
22
+ ### 1. Initialize the SDK
23
+
24
+ ```typescript
25
+ import { PasskeymeAuth } from "@passkeyme/auth";
26
+
27
+ const auth = new PasskeymeAuth({
28
+ appId: "your-passkeyme-app-id",
29
+ redirectUri: "http://localhost:3000/auth/callback",
30
+ });
31
+
32
+ // Initialize on app start
33
+ await auth.init();
34
+ ```
35
+
36
+ ### 2. Choose Your Authentication Approach
37
+
38
+ #### **Approach 1: Hosted Auth Pages** ✨ (Recommended)
39
+
40
+ ```typescript
41
+ // Redirects to your branded hosted login page
42
+ // User sees all available login methods (OAuth, Passkey, Username/Password)
43
+ auth.redirectToLogin();
44
+
45
+ // With options
46
+ auth.redirectToLogin({
47
+ authMethod: "passkey", // Pre-select passkey method
48
+ state: "custom-state", // Custom state for callback
49
+ });
50
+ ```
51
+
52
+ #### **Approach 2: Direct OAuth** ⚡
53
+
54
+ ```typescript
55
+ // Skip hosted page, go directly to OAuth provider
56
+ auth.redirectToOAuth("google");
57
+ auth.redirectToOAuth("github");
58
+ auth.redirectToOAuth("facebook");
59
+
60
+ // With custom redirect URI
61
+ auth.redirectToOAuth("google", "http://localhost:3000/custom/callback");
62
+ ```
63
+
64
+ #### **The Key Difference:**
65
+
66
+ - `redirectToLogin()` → Shows your branded page with all auth options
67
+ - `redirectToOAuth('google')` → Goes directly to Google OAuth (skips hosted page)
68
+
69
+ #### Direct OAuth Provider
70
+
71
+ ```typescript
72
+ // Skip login page, go directly to OAuth provider
73
+ auth.redirectToOAuth("google");
74
+ auth.redirectToOAuth("github");
75
+ auth.redirectToOAuth("facebook");
76
+ ```
77
+
78
+ ### 3. Handle Authentication Callback
79
+
80
+ On your callback page (`/auth/callback`):
81
+
82
+ ```typescript
83
+ // This handles the authentication return and gets the user
84
+ const user = await auth.handleAuthCallback();
85
+
86
+ if (user) {
87
+ // Redirect to your app
88
+ window.location.href = "/dashboard";
89
+ } else {
90
+ // Handle auth failure
91
+ window.location.href = "/login?error=auth_failed";
92
+ }
93
+ ```
94
+
95
+ ### 4. Check Authentication Status
96
+
97
+ ```typescript
98
+ // Check if user is logged in
99
+ const user = auth.getCurrentUser();
100
+
101
+ if (user) {
102
+ console.log("Logged in as:", user.email);
103
+ } else {
104
+ console.log("Not logged in");
105
+ }
106
+
107
+ // Or check auth state
108
+ console.log("Auth state:", auth.state);
109
+
110
+ // Check on page load
111
+ await auth.init(); // This will restore session if available
112
+ ```
113
+
114
+ ### 5. Logout
115
+
116
+ ```typescript
117
+ await auth.logout();
118
+ ```
119
+
120
+ ## 🔗 HTTP Client Integration
121
+
122
+ Automatically add auth headers to your API calls:
123
+
124
+ ### With Axios
125
+
126
+ ```typescript
127
+ import axios from "axios";
128
+ import { setupHttpInterceptor } from "@passkeyme/auth";
129
+
130
+ const apiClient = axios.create({
131
+ baseURL: "https://your-api.com",
132
+ });
133
+
134
+ // Setup automatic token management
135
+ const cleanup = setupHttpInterceptor(auth, apiClient);
136
+
137
+ // Now all requests automatically include auth headers
138
+ const response = await apiClient.get("/protected-data");
139
+ ```
140
+
141
+ ### With Fetch
142
+
143
+ ```typescript
144
+ import { createAuthenticatedFetch } from "@passkeyme/auth";
145
+
146
+ const authenticatedFetch = createAuthenticatedFetch(auth);
147
+
148
+ // Use like regular fetch, but with automatic auth headers
149
+ const response = await authenticatedFetch("/api/protected-data");
150
+ ```
151
+
152
+ ### Manual Header Management
153
+
154
+ ```typescript
155
+ import { addAuthHeader } from "@passkeyme/auth";
156
+
157
+ const headers = await addAuthHeader(auth, {
158
+ "Content-Type": "application/json",
159
+ });
160
+
161
+ fetch("/api/data", { headers });
162
+ ```
163
+
164
+ ## 🎭 Event Handling
165
+
166
+ Listen to authentication events:
167
+
168
+ ```typescript
169
+ const unsubscribe = auth.addEventListener((event) => {
170
+ switch (event.type) {
171
+ case "login":
172
+ console.log("User logged in:", event.user);
173
+ break;
174
+ case "logout":
175
+ console.log("User logged out");
176
+ break;
177
+ case "token_refresh":
178
+ console.log("Token refreshed");
179
+ break;
180
+ case "error":
181
+ console.error("Auth error:", event.error);
182
+ break;
183
+ }
184
+ });
185
+
186
+ // Clean up when done
187
+ unsubscribe();
188
+ ```
189
+
190
+ ## ⚙️ Configuration Options
191
+
192
+ ### Basic Configuration
193
+
194
+ ```typescript
195
+ const auth = new PasskeymeAuth({
196
+ appId: "your-app-id", // Required: From PasskeyMe dashboard
197
+ redirectUri: "http://localhost:3000/callback", // Optional: Default callback URL
198
+ debug: true, // Optional: Enable debug logging
199
+ });
200
+ ```
201
+
202
+ ### Custom Domain Configuration
203
+
204
+ ```typescript
205
+ const auth = new PasskeymeAuth({
206
+ appId: "your-app-id",
207
+ apiUrl: "https://auth.yourdomain.com", // Your custom domain
208
+ redirectUri: "https://yourapp.com/callback",
209
+ });
210
+ ```
211
+
212
+ ### Self-Hosted Configuration
213
+
214
+ ```typescript
215
+ const auth = new PasskeymeAuth({
216
+ appId: "your-app-id",
217
+ apiUrl: "http://localhost:8000", // Your self-hosted server
218
+ redirectUri: "http://localhost:3000/callback",
219
+ debug: true, // Helpful for development
220
+ });
221
+ ```
222
+
223
+ ### Storage Configuration
224
+
225
+ ```typescript
226
+ import { PasskeymeAuth, BrowserStorageProvider } from "@passkeyme/auth";
227
+
228
+ // Default behavior (localStorage)
229
+ const auth = new PasskeymeAuth({
230
+ appId: "your-app-id",
231
+ });
232
+
233
+ // Use sessionStorage instead
234
+ const auth = new PasskeymeAuth({
235
+ appId: "your-app-id",
236
+ storage: new BrowserStorageProvider(true), // true = use sessionStorage
237
+ });
238
+
239
+ // Custom storage implementation
240
+ class CustomStorageProvider {
241
+ async getItem(key) {
242
+ /* your implementation */
243
+ }
244
+ async setItem(key, value) {
245
+ /* your implementation */
246
+ }
247
+ async removeItem(key) {
248
+ /* your implementation */
249
+ }
250
+ }
251
+
252
+ const auth = new PasskeymeAuth({
253
+ appId: "your-app-id",
254
+ storage: new CustomStorageProvider(),
255
+ });
256
+ ```
257
+
258
+ ### State Subscription
259
+
260
+ ```typescript
261
+ // Subscribe to authentication state changes
262
+ const unsubscribe = auth.subscribe((state) => {
263
+ console.log("Auth state changed:", state);
264
+ // { user, loading, error, isAuthenticated }
265
+ });
266
+
267
+ // Get current state
268
+ const currentState = auth.getState();
269
+
270
+ // Clean up when done
271
+ unsubscribe();
272
+ ```
273
+
274
+ ## 🆚 vs Firebase Auth
275
+
276
+ | Feature | PasskeyMe Auth | Firebase Auth |
277
+ | -------------------- | -------------------------- | --------------------------- |
278
+ | **Setup Complexity** | ✅ Single provider | ❌ Multiple services needed |
279
+ | **Hosted Auth UI** | ✅ Pre-built, customizable | ❌ Build your own |
280
+ | **Passkey Support** | ✅ Built-in WebAuthn | ❌ Manual implementation |
281
+ | **Self-Hosting** | ✅ Full control | ❌ Google-only |
282
+ | **Vendor Lock-in** | ✅ Standard JWT | ❌ Firebase-specific |
283
+ | **Privacy** | ✅ Your data | ❌ Google's servers |
284
+ | **Bundle Size** | ✅ Lightweight | ❌ Heavy SDK |
285
+
286
+ ## 📋 API Reference
287
+
288
+ ### PasskeymeAuth Class
289
+
290
+ ```typescript
291
+ class PasskeymeAuth {
292
+ // Properties
293
+ readonly state: AuthState;
294
+
295
+ // Methods
296
+ init(): Promise<void>;
297
+ redirectToLogin(options?: RedirectOptions): void;
298
+ redirectToOAuth(
299
+ provider: "google" | "github" | "facebook",
300
+ options?: RedirectOptions
301
+ ): void;
302
+ handleAuthCallback(): Promise<User | null>;
303
+ logout(): Promise<void>;
304
+ getCurrentUser(): User | null;
305
+ getAccessToken(): Promise<string | null>;
306
+ refreshToken(): Promise<string>;
307
+ addEventListener(listener: AuthEventListener): () => void;
308
+ removeEventListener(listener: AuthEventListener): void;
309
+ }
310
+ ```
311
+
312
+ ### Types
313
+
314
+ ```typescript
315
+ interface User {
316
+ id: string;
317
+ email?: string;
318
+ name?: string;
319
+ picture?: string;
320
+ provider?: string;
321
+ createdAt?: string;
322
+ lastLoginAt?: string;
323
+ }
324
+
325
+ interface AuthState {
326
+ user: User | null;
327
+ loading: boolean;
328
+ error: string | null;
329
+ isAuthenticated: boolean;
330
+ }
331
+
332
+ interface RedirectOptions {
333
+ redirectTo?: string; // Where to go after successful auth
334
+ state?: string; // Custom state parameter
335
+ }
336
+ ```
337
+
338
+ ## 🔧 Advanced Usage
339
+
340
+ ### Handling the Complete Flow
341
+
342
+ ```typescript
343
+ // 1. App initialization
344
+ const auth = new PasskeymeAuth({
345
+ appId: "your-app-id",
346
+ redirectUri: "http://localhost:3000/auth/callback",
347
+ });
348
+
349
+ await auth.init();
350
+
351
+ // 2. Login button click
352
+ document.getElementById("login-btn").addEventListener("click", () => {
353
+ auth.redirectToLogin({ redirectTo: "/dashboard" });
354
+ });
355
+
356
+ // 3. On callback page (/auth/callback)
357
+ const user = await auth.handleAuthCallback();
358
+ if (user) {
359
+ // Redirect to the intended page
360
+ const urlParams = new URLSearchParams(window.location.search);
361
+ const redirectTo = urlParams.get("redirectTo") || "/";
362
+ window.location.href = redirectTo;
363
+ }
364
+ ```
365
+
366
+ ## 🔗 TypeScript Integration
367
+
368
+ This package is written in TypeScript and provides comprehensive type definitions.
369
+
370
+ ### Type Imports
371
+
372
+ ```typescript
373
+ import type {
374
+ PasskeymeConfig,
375
+ User,
376
+ AuthTokens,
377
+ OAuthProvider,
378
+ PasskeyCredential,
379
+ AuthState,
380
+ TokenStorage,
381
+ HttpInterceptor,
382
+ } from "@passkeyme/auth";
383
+
384
+ // Configuration interface
385
+ interface PasskeymeConfig {
386
+ appId: string;
387
+ baseUrl?: string; // Default: 'https://auth.passkeyme.com'
388
+ redirectUri: string;
389
+ debug?: boolean; // Enable debug logging
390
+ tokenStorage?: TokenStorage; // Custom token storage
391
+ httpInterceptors?: HttpInterceptor[]; // Custom HTTP interceptors
392
+ }
393
+
394
+ // User object structure
395
+ interface User {
396
+ id: string;
397
+ email: string;
398
+ name?: string;
399
+ avatar?: string;
400
+ emailVerified: boolean;
401
+ createdAt: string;
402
+ lastLoginAt: string;
403
+ metadata?: Record<string, any>;
404
+ }
405
+
406
+ // Authentication tokens
407
+ interface AuthTokens {
408
+ accessToken: string;
409
+ refreshToken: string;
410
+ expiresAt: number;
411
+ tokenType: string;
412
+ }
413
+ ```
414
+
415
+ ### Advanced Configuration
416
+
417
+ ```typescript
418
+ import { PasskeymeAuth, LocalStorageTokenStorage } from "@passkeyme/auth";
419
+
420
+ // Custom token storage implementation
421
+ class SecureTokenStorage implements TokenStorage {
422
+ async setTokens(tokens: AuthTokens): Promise<void> {
423
+ // Store in encrypted storage or secure keychain
424
+ await secureStorage.set("auth_tokens", encrypt(tokens));
425
+ }
426
+
427
+ async getTokens(): Promise<AuthTokens | null> {
428
+ const encrypted = await secureStorage.get("auth_tokens");
429
+ return encrypted ? decrypt(encrypted) : null;
430
+ }
431
+
432
+ async clearTokens(): Promise<void> {
433
+ await secureStorage.remove("auth_tokens");
434
+ }
435
+ }
436
+
437
+ // HTTP interceptor for API calls
438
+ const apiInterceptor: HttpInterceptor = {
439
+ request: async (config) => {
440
+ // Add custom headers or modify requests
441
+ config.headers = {
442
+ ...config.headers,
443
+ "X-Client-Version": "1.0.0",
444
+ "X-Client-Platform": "web",
445
+ };
446
+ return config;
447
+ },
448
+
449
+ response: async (response) => {
450
+ // Handle responses globally
451
+ if (response.status === 401) {
452
+ // Handle unauthorized responses
453
+ await auth.logout();
454
+ window.location.href = "/login";
455
+ }
456
+ return response;
457
+ },
458
+ };
459
+
460
+ const auth = new PasskeymeAuth({
461
+ appId: "your-app-id",
462
+ redirectUri: "https://yourapp.com/auth/callback",
463
+ debug: process.env.NODE_ENV === "development",
464
+ tokenStorage: new SecureTokenStorage(),
465
+ httpInterceptors: [apiInterceptor],
466
+ });
467
+ ```
468
+
469
+ ### API Client Integration
470
+
471
+ ```typescript
472
+ import { PasskeymeAuth } from "@passkeyme/auth";
473
+
474
+ class ApiClient {
475
+ private auth: PasskeymeAuth;
476
+
477
+ constructor(auth: PasskeymeAuth) {
478
+ this.auth = auth;
479
+ }
480
+
481
+ async makeAuthenticatedRequest<T>(
482
+ url: string,
483
+ options: RequestInit = {}
484
+ ): Promise<T> {
485
+ const authHeader = await this.auth.getAuthHeader();
486
+
487
+ const response = await fetch(url, {
488
+ ...options,
489
+ headers: {
490
+ ...options.headers,
491
+ Authorization: authHeader,
492
+ "Content-Type": "application/json",
493
+ },
494
+ });
495
+
496
+ if (!response.ok) {
497
+ if (response.status === 401) {
498
+ // Try to refresh token
499
+ await this.auth.refreshToken();
500
+ // Retry request with new token
501
+ return this.makeAuthenticatedRequest(url, options);
502
+ }
503
+ throw new Error(`API Error: ${response.status}`);
504
+ }
505
+
506
+ return response.json();
507
+ }
508
+
509
+ // Type-safe API methods
510
+ async getUserProfile(): Promise<User> {
511
+ return this.makeAuthenticatedRequest<User>("/api/user/profile");
512
+ }
513
+
514
+ async updateUserProfile(updates: Partial<User>): Promise<User> {
515
+ return this.makeAuthenticatedRequest<User>("/api/user/profile", {
516
+ method: "PATCH",
517
+ body: JSON.stringify(updates),
518
+ });
519
+ }
520
+ }
521
+ ```
522
+
523
+ ### Framework Integration Examples
524
+
525
+ #### Vanilla JavaScript (SPA)
526
+
527
+ ```typescript
528
+ // main.js
529
+ const auth = new PasskeymeAuth({
530
+ appId: "your-app-id",
531
+ redirectUri: window.location.origin + "/auth/callback",
532
+ });
533
+
534
+ await auth.init();
535
+
536
+ // Router logic
537
+ if (window.location.pathname === "/auth/callback") {
538
+ const user = await auth.handleAuthCallback();
539
+ if (user) {
540
+ window.location.href = "/dashboard";
541
+ }
542
+ } else if (!auth.getCurrentUser() && window.location.pathname !== "/login") {
543
+ window.location.href = "/login";
544
+ }
545
+ ```
546
+
547
+ #### Next.js Pages Router
548
+
549
+ ```typescript
550
+ // pages/auth/callback.js
551
+ import { useEffect } from "react";
552
+ import { useRouter } from "next/router";
553
+ import { auth } from "../lib/auth";
554
+
555
+ export default function AuthCallback() {
556
+ const router = useRouter();
557
+
558
+ useEffect(() => {
559
+ auth.handleAuthCallback().then((user) => {
560
+ if (user) {
561
+ router.push("/dashboard");
562
+ } else {
563
+ router.push("/login?error=auth_failed");
564
+ }
565
+ });
566
+ }, []);
567
+
568
+ return <div>Completing authentication...</div>;
569
+ }
570
+ ```
571
+
572
+ ## 🛠️ Development
573
+
574
+ This package is part of the PasskeyMe project. For development:
575
+
576
+ ```bash
577
+ # Install dependencies
578
+ npm install
579
+
580
+ # Build the package
581
+ npm run build
582
+
583
+ # Run tests
584
+ npm test
585
+
586
+ # Development mode (watch)
587
+ npm run dev
588
+ ```
589
+
590
+ ## 📄 License
591
+
592
+ MIT - see LICENSE file for details.
593
+
594
+ ## 🤝 Support
595
+
596
+ - **Documentation**: https://passkeyme.com/docs
597
+ - **Issues**: https://github.com/passkeyme/passkeyme/issues
598
+ - **Discord**: https://discord.gg/passkeyme