@passkeyme/react-auth 1.0.0 → 1.1.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.
package/dist/index.esm.js CHANGED
@@ -1,11 +1,351 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import React, { createContext, useContext, useState, useEffect, useCallback, useMemo, Profiler, useRef, lazy, Suspense, Component } from 'react';
3
- import { PasskeymeProvider as PasskeymeProvider$1, usePasskeyme } from '@passkeyme/react-core';
4
- export { usePasskeyme, usePasskeymeContext } from '@passkeyme/react-core';
5
- import { WebPasskeySDK, PasskeymeError, PasskeymeErrorCode } from '@passkeyme/auth';
2
+ import React, { createContext, useContext, useCallback, useState, useEffect, useMemo, Profiler, useRef, lazy, Suspense, Component } from 'react';
3
+ import { PasskeymeError, PasskeymeErrorCode, PasskeymeAuth, WebPasskeySDK } from '@passkeyme/auth';
6
4
  export { ErrorHandler, PasskeymeError, PasskeymeErrorCode } from '@passkeyme/auth';
7
5
  import { createPortal } from 'react-dom';
8
6
 
7
+ /**
8
+ * React Context Provider for PasskeyMe Authentication (Core)
9
+ * This is the shared provider for React and React Native
10
+ */
11
+ const PasskeymeContext = createContext(null);
12
+ const usePasskeymeContext = () => {
13
+ const context = useContext(PasskeymeContext);
14
+ if (!context) {
15
+ throw new Error("usePasskeymeContext must be used within a PasskeymeProvider");
16
+ }
17
+ return context;
18
+ };
19
+ const PasskeymeProvider$1 = ({ config, children, loadingComponent = null, errorComponent, onAuthChange, onError, }) => {
20
+ const [auth] = useState(() => new PasskeymeAuth(config));
21
+ const [authState, setAuthState] = useState({
22
+ user: null,
23
+ loading: true,
24
+ error: null,
25
+ isAuthenticated: false,
26
+ });
27
+ const [authLoading, setAuthLoading] = useState(false);
28
+ const [appConfig, setAppConfig] = useState(null);
29
+ useEffect(() => {
30
+ // Subscribe to state changes using the new subscription system
31
+ const unsubscribeState = auth.subscribe((newState) => {
32
+ setAuthState(newState);
33
+ // Call auth change callback
34
+ if (onAuthChange) {
35
+ onAuthChange(newState.user);
36
+ }
37
+ // Call error callback
38
+ if (newState.error && onError) {
39
+ onError(newState.error);
40
+ }
41
+ });
42
+ // Set up event listener for additional auth events
43
+ const unsubscribeEvents = auth.addEventListener((event) => {
44
+ // Handle specific events
45
+ switch (event.type) {
46
+ case "login":
47
+ if (onAuthChange && event.user) {
48
+ onAuthChange(event.user);
49
+ }
50
+ break;
51
+ case "logout":
52
+ if (onAuthChange) {
53
+ onAuthChange(null);
54
+ }
55
+ break;
56
+ case "error":
57
+ if (onError && event.error) {
58
+ onError(event.error);
59
+ }
60
+ break;
61
+ }
62
+ });
63
+ // Initialize auth
64
+ const initAuth = async () => {
65
+ try {
66
+ await auth.init();
67
+ // Load app configuration
68
+ try {
69
+ const config = await auth.getAppConfig();
70
+ setAppConfig(config);
71
+ }
72
+ catch (configError) {
73
+ console.warn("Failed to load app configuration:", configError);
74
+ }
75
+ }
76
+ catch (error) {
77
+ const errorMessage = error instanceof Error
78
+ ? error.message
79
+ : "Authentication initialization failed";
80
+ if (onError) {
81
+ onError(errorMessage);
82
+ }
83
+ }
84
+ };
85
+ initAuth();
86
+ // Cleanup
87
+ return () => {
88
+ unsubscribeState();
89
+ unsubscribeEvents();
90
+ };
91
+ }, [auth, onAuthChange, onError]);
92
+ const contextValue = {
93
+ auth,
94
+ user: authState.user,
95
+ loading: authState.loading,
96
+ error: authState.error,
97
+ isAuthenticated: authState.isAuthenticated,
98
+ authLoading,
99
+ setAuthLoading,
100
+ config,
101
+ appConfig,
102
+ };
103
+ // Show loading component if provided
104
+ if (authState.loading && loadingComponent) {
105
+ return React.createElement(React.Fragment, null, loadingComponent);
106
+ }
107
+ // Show error component if provided
108
+ if (authState.error && !authState.isAuthenticated && errorComponent) {
109
+ return React.createElement(React.Fragment, null, errorComponent(authState.error));
110
+ }
111
+ return (React.createElement(PasskeymeContext.Provider, { value: contextValue }, children));
112
+ };
113
+
114
+ /**
115
+ * Core React hooks for PasskeyMe Authentication
116
+ * Shared between React and React Native
117
+ */
118
+ // Simple debug function for core package
119
+ function debugLog$1(config, ...args) {
120
+ if (config.debug) {
121
+ console.log("[PasskeymeAuth]", ...args);
122
+ }
123
+ }
124
+ const usePasskeyme = () => {
125
+ const { auth, user, loading, error, isAuthenticated, authLoading, setAuthLoading, config, } = usePasskeymeContext();
126
+ if (!auth) {
127
+ throw new Error("PasskeyMe auth instance not available");
128
+ }
129
+ const redirectToLogin = useCallback((options) => {
130
+ return auth.redirectToLogin(options);
131
+ }, [auth]);
132
+ const redirectToOAuth = useCallback((provider, redirectUri) => {
133
+ return auth.redirectToOAuth(provider, redirectUri);
134
+ }, [auth]);
135
+ const handleAuthCallback = useCallback(async () => {
136
+ return auth.handleAuthCallback();
137
+ }, [auth]);
138
+ const handleCallback = useCallback(async () => {
139
+ return auth.handleCallback();
140
+ }, [auth]);
141
+ const handleTokenCallback = useCallback(async (token) => {
142
+ return auth.handleTokenCallback(token);
143
+ }, [auth]);
144
+ const logout = useCallback(async () => {
145
+ return auth.logout();
146
+ }, [auth]);
147
+ const getAccessToken = useCallback(async () => {
148
+ return auth.getAccessToken();
149
+ }, [auth]);
150
+ const refreshToken = useCallback(async () => {
151
+ return auth.refreshToken();
152
+ }, [auth]);
153
+ const getBaseUrl = useCallback(() => {
154
+ return auth.getBaseUrl();
155
+ }, [auth]);
156
+ const getAppId = useCallback(() => {
157
+ return auth.getAppId();
158
+ }, [auth]);
159
+ const isPasskeySupported = useCallback(() => {
160
+ return auth.isPasskeySupported();
161
+ }, [auth]);
162
+ const hasStoredPasskeys = useCallback(async (username) => {
163
+ return await auth.hasStoredPasskeys(username);
164
+ }, [auth]);
165
+ const passkeyLogin = useCallback(async (username, apiKey) => {
166
+ return auth.passkeyLogin(username, apiKey);
167
+ }, [auth]);
168
+ const smartLogin = useCallback(async (username, apiKey) => {
169
+ return auth.smartLogin(username, apiKey);
170
+ }, [auth]);
171
+ const getAppConfig = useCallback(async () => {
172
+ return auth.getAppConfig();
173
+ }, [auth]);
174
+ const triggerPasskeymeAuth = useCallback(async (options = {}) => {
175
+ var _a, _b;
176
+ const { username, apiKey, mode = "hosted", onSuccess, onError, onOAuthRequired, showNotifications = false, // Default to false for core package
177
+ forcePasskeyOnly = false, } = options;
178
+ debugLog$1(config, "triggerPasskeymeAuth", "Starting authentication with options:", {
179
+ username: username || "(discoverable)",
180
+ hasApiKey: !!(apiKey ||
181
+ config.passkeyApiKey ||
182
+ ((_a = config.passkey) === null || _a === void 0 ? void 0 : _a.apiKey)),
183
+ mode,
184
+ forcePasskeyOnly,
185
+ showNotifications,
186
+ isPasskeySupported: auth.isPasskeySupported(),
187
+ // Note: hasStoredPasskeys is now async, so we can't include it in this sync log
188
+ });
189
+ try {
190
+ setAuthLoading(true);
191
+ // Get effective API key
192
+ const effectiveApiKey = apiKey || config.passkeyApiKey || ((_b = config.passkey) === null || _b === void 0 ? void 0 : _b.apiKey);
193
+ if (forcePasskeyOnly) {
194
+ // Force passkey-only authentication
195
+ debugLog$1(config, "triggerPasskeymeAuth", "Force passkey-only mode");
196
+ if (!effectiveApiKey) {
197
+ throw new Error("API key required for passkey authentication");
198
+ }
199
+ const result = await auth.passkeyLogin(username || undefined, effectiveApiKey);
200
+ debugLog$1(config, "triggerPasskeymeAuth", "Passkey-only authentication successful");
201
+ if (onSuccess) {
202
+ onSuccess(result, "passkey");
203
+ }
204
+ }
205
+ else {
206
+ // Try passkey authentication first, then handle fallback based on mode
207
+ try {
208
+ debugLog$1(config, "triggerPasskeymeAuth", "Attempting passkey authentication");
209
+ // Validate that we have an API key for passkey authentication
210
+ if (!effectiveApiKey) {
211
+ debugLog$1(config, "triggerPasskeymeAuth", "No API key available for passkey auth, skipping to fallback");
212
+ throw new Error("No API key available for passkey authentication");
213
+ }
214
+ let authUsername = username;
215
+ // If no username provided, let smartLogin handle the logic
216
+ // (it will check app config, localStorage, discoverable credentials, etc.)
217
+ if (!authUsername) {
218
+ debugLog$1(config, "triggerPasskeymeAuth", "No username provided, letting smartLogin handle auto-detection");
219
+ }
220
+ // Attempt smart passkey authentication (handles localStorage, discoverable credentials, etc.)
221
+ debugLog$1(config, "triggerPasskeymeAuth", "Calling smartLogin with username:", authUsername || "(auto-detect)");
222
+ const result = await auth.smartLogin(authUsername, effectiveApiKey);
223
+ debugLog$1(config, "triggerPasskeymeAuth", "Smart authentication result:", result);
224
+ if (result.method === "passkey" && result.user) {
225
+ debugLog$1(config, "triggerPasskeymeAuth", "Passkey authentication successful");
226
+ if (onSuccess) {
227
+ onSuccess(result.user, "passkey");
228
+ }
229
+ }
230
+ else {
231
+ // smartLogin returned redirect method, which means it already redirected
232
+ debugLog$1(config, "triggerPasskeymeAuth", "smartLogin redirected to hosted auth");
233
+ return;
234
+ }
235
+ }
236
+ catch (passkeyError) {
237
+ // Passkey failed, handle fallback based on mode
238
+ debugLog$1(config, "triggerPasskeymeAuth", "Passkey authentication failed:", passkeyError);
239
+ // Enhanced error handling for PasskeymeError
240
+ if (passkeyError instanceof PasskeymeError) {
241
+ debugLog$1(config, "triggerPasskeymeAuth", "PasskeymeError details:", {
242
+ code: passkeyError.code,
243
+ message: passkeyError.message,
244
+ userMessage: passkeyError.userMessage,
245
+ recoverable: passkeyError.recoverable,
246
+ retryable: passkeyError.retryable,
247
+ suggestedAction: passkeyError.suggestedAction,
248
+ });
249
+ // Handle specific error codes that should not trigger fallback
250
+ if (passkeyError.code === PasskeymeErrorCode.USER_CANCELLED ||
251
+ passkeyError.code === PasskeymeErrorCode.PASSKEY_CANCELLED) {
252
+ // User cancelled - don't fallback, just call error handler
253
+ if (onError) {
254
+ onError(passkeyError.userMessage);
255
+ }
256
+ return;
257
+ }
258
+ if (passkeyError.code === PasskeymeErrorCode.PASSKEY_NOT_SUPPORTED) {
259
+ // Passkeys not supported - immediately fallback without retrying
260
+ debugLog$1(config, "triggerPasskeymeAuth", "Passkeys not supported, proceeding to fallback");
261
+ }
262
+ }
263
+ debugLog$1(config, "triggerPasskeymeAuth", "Handling fallback for mode:", mode);
264
+ if (mode === "hosted") {
265
+ // Hosted mode: redirect to hosted auth pages
266
+ debugLog$1(config, "triggerPasskeymeAuth", "Passkey failed, redirecting to hosted auth");
267
+ auth.redirectToLogin();
268
+ return;
269
+ }
270
+ else if (mode === "inline") {
271
+ // Inline mode: provide OAuth providers to developer
272
+ debugLog$1(config, "triggerPasskeymeAuth", "Passkey failed, providing OAuth options for inline mode");
273
+ if (onOAuthRequired) {
274
+ try {
275
+ // Get available OAuth providers from app config
276
+ const appConfig = await auth.getAppConfig();
277
+ const providers = appConfig.oauthProviders || [
278
+ "google",
279
+ "github",
280
+ ];
281
+ debugLog$1(config, "triggerPasskeymeAuth", "Available OAuth providers:", providers);
282
+ onOAuthRequired(providers);
283
+ return;
284
+ }
285
+ catch (configError) {
286
+ debugLog$1(config, "triggerPasskeymeAuth", "Failed to get app config, using default providers");
287
+ onOAuthRequired(["google", "github"]);
288
+ return;
289
+ }
290
+ }
291
+ else {
292
+ throw new Error("Passkey authentication failed and no onOAuthRequired callback provided for inline mode");
293
+ }
294
+ }
295
+ }
296
+ }
297
+ }
298
+ catch (error) {
299
+ console.error("[triggerPasskeymeAuth] Authentication error:", error);
300
+ let errorMessage = "Authentication failed";
301
+ // Enhanced error handling for PasskeymeError
302
+ if (error instanceof PasskeymeError) {
303
+ errorMessage = error.userMessage;
304
+ debugLog$1(config, "triggerPasskeymeAuth", "Final error handling:", {
305
+ code: error.code,
306
+ userMessage: error.userMessage,
307
+ retryable: error.retryable,
308
+ suggestedAction: error.suggestedAction,
309
+ });
310
+ }
311
+ else {
312
+ errorMessage = (error === null || error === void 0 ? void 0 : error.message) || "Authentication failed";
313
+ }
314
+ if (onError) {
315
+ onError(errorMessage);
316
+ }
317
+ }
318
+ finally {
319
+ setAuthLoading(false);
320
+ }
321
+ }, [auth, config, setAuthLoading]);
322
+ return {
323
+ user,
324
+ loading,
325
+ error,
326
+ isAuthenticated,
327
+ config,
328
+ redirectToLogin,
329
+ redirectToOAuth,
330
+ handleAuthCallback,
331
+ handleCallback,
332
+ handleTokenCallback,
333
+ logout,
334
+ getAccessToken,
335
+ refreshToken,
336
+ getBaseUrl,
337
+ getAppId,
338
+ isPasskeySupported,
339
+ hasStoredPasskeys,
340
+ passkeyLogin,
341
+ smartLogin,
342
+ getAppConfig,
343
+ triggerPasskeymeAuth,
344
+ authLoading,
345
+ auth,
346
+ };
347
+ };
348
+
9
349
  const NotificationContext = createContext(null);
10
350
  const useNotifications = () => {
11
351
  const context = useContext(NotificationContext);
@@ -6039,7 +6379,7 @@ const PasskeymeCallbackHandler = ({ loadingComponent: LoadingComponent, errorCom
6039
6379
  updateState({ passkeyRegistering: true });
6040
6380
  // Create axios instance for PasskeyMe API
6041
6381
  const axiosInstance = axios$1.create({
6042
- baseURL: `${getBaseUrl()}/api/webauthn/${config.appId}`,
6382
+ baseURL: `${getBaseUrl()}/webauthn/${config.appId}`,
6043
6383
  headers: {
6044
6384
  "x-api-key": effectivePasskeyConfig.apiKey,
6045
6385
  "Content-Type": "application/json",
@@ -8730,5 +9070,5 @@ const useVirtualScrollList = (initialItems = [], itemHeight = 50, containerHeigh
8730
9070
  };
8731
9071
  };
8732
9072
 
8733
- export { AnalyticsProvider, BundleOptimizer, DebugPanel, DevToolsDashboard, ImportAnalyzer, MockPasskeymeProvider, NotificationProvider, OptimizedStorage, PasskeymeAuthPanel, PasskeymeButton, PasskeymeCallbackHandler, PasskeymeErrorBoundary, PasskeymeErrorDisplay, PasskeymeErrorDisplayLazy, PasskeymeLoadingIndicator, PasskeymeLoadingIndicatorLazy, PasskeymeOAuthButton, PasskeymeProfiler, PasskeymeProtectedRoute, PasskeymeProvider, PasskeymeUserProfile, PerformanceDashboard as PerfDashboard, PerformanceDashboard$1 as PerformanceDashboard, PerformanceIndicator, PerformanceStats, RequestCache, SessionStorage, VirtualScrollList, accessibilityTestHelpers, buttonPresets, checkRuntimeDependencies, createLazyComponent, createMockConfig, createMockUser, createPerformanceTracker, createRenderWithPasskeymeProvider, createUsageTracker, devError, devWarn, e2eTestHelpers, enableHotReload, generateOptimizationReport, getButtonIconStyles, getEnhancedButtonStyles, getLoadingSpinnerStyles, initDevTools, logComponentTree, mockAuthResponses, performanceStore, performanceTestHelpers, requestCache, sessionStorage$1 as sessionStorage, storage, useAnalytics, useApiPerformanceMonitor, useAuth, useAuthState, useLoadingState, useMemoryMonitor, useNotifications, useOptimizedStorage, usePerformanceMonitor, usePerformanceStats, useRequestCache, useSessionStorage, useUsernameManager, useVirtualScrollList, validateProps, visualRegressionHelpers, withAuth, withDevTools, withErrorBoundary, withPerformanceProfiler, withProfiler };
9073
+ export { AnalyticsProvider, BundleOptimizer, DebugPanel, DevToolsDashboard, ImportAnalyzer, MockPasskeymeProvider, NotificationProvider, OptimizedStorage, PasskeymeAuthPanel, PasskeymeButton, PasskeymeCallbackHandler, PasskeymeErrorBoundary, PasskeymeErrorDisplay, PasskeymeErrorDisplayLazy, PasskeymeLoadingIndicator, PasskeymeLoadingIndicatorLazy, PasskeymeOAuthButton, PasskeymeProfiler, PasskeymeProtectedRoute, PasskeymeProvider, PasskeymeUserProfile, PerformanceDashboard as PerfDashboard, PerformanceDashboard$1 as PerformanceDashboard, PerformanceIndicator, PerformanceStats, RequestCache, SessionStorage, VirtualScrollList, accessibilityTestHelpers, buttonPresets, checkRuntimeDependencies, createLazyComponent, createMockConfig, createMockUser, createPerformanceTracker, createRenderWithPasskeymeProvider, createUsageTracker, devError, devWarn, e2eTestHelpers, enableHotReload, generateOptimizationReport, getButtonIconStyles, getEnhancedButtonStyles, getLoadingSpinnerStyles, initDevTools, logComponentTree, mockAuthResponses, performanceStore, performanceTestHelpers, requestCache, sessionStorage$1 as sessionStorage, storage, useAnalytics, useApiPerformanceMonitor, useAuth, useAuthState, useLoadingState, useMemoryMonitor, useNotifications, useOptimizedStorage, usePasskeyme, usePasskeymeContext, usePerformanceMonitor, usePerformanceStats, useRequestCache, useSessionStorage, useUsernameManager, useVirtualScrollList, validateProps, visualRegressionHelpers, withAuth, withDevTools, withErrorBoundary, withPerformanceProfiler, withProfiler };
8734
9074
  //# sourceMappingURL=index.esm.js.map