@insforge/react 0.2.4 → 0.2.6

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/router.d.mts CHANGED
@@ -13,14 +13,13 @@ interface GetInsforgeRoutesConfig {
13
13
  */
14
14
  builtInAuth?: boolean;
15
15
  /**
16
- * Custom paths for auth routes
16
+ * Custom paths for auth redirect routes
17
17
  * @default {
18
18
  * signIn: '/sign-in',
19
19
  * signUp: '/sign-up',
20
20
  * verifyEmail: '/verify-email',
21
21
  * forgotPassword: '/forgot-password',
22
- * resetPassword: '/reset-password',
23
- * callback: '/auth/callback'
22
+ * resetPassword: '/reset-password'
24
23
  * }
25
24
  */
26
25
  paths?: {
@@ -29,73 +28,58 @@ interface GetInsforgeRoutesConfig {
29
28
  verifyEmail?: string;
30
29
  forgotPassword?: string;
31
30
  resetPassword?: string;
32
- callback?: string;
33
31
  };
34
32
  }
35
33
  /**
36
- * Generates Insforge authentication routes for React Router.
34
+ * Generates Insforge authentication redirect routes for React Router.
37
35
  *
38
- * Returns an array of RouteObjects that can be spread into your router configuration.
39
- * Supports all Insforge auth pages: sign-in, sign-up, verify-email, forgot-password, reset-password.
36
+ * Returns redirect routes for sign-in, sign-up, etc. that redirect to your deployed Insforge auth pages.
37
+ *
38
+ * ⚠️ **Important**: You must manually create the `/auth/callback` route in your router
39
+ * to handle authentication callbacks. See documentation for details.
40
40
  *
41
41
  * @param config - Configuration for Insforge routes
42
- * @returns Array of RouteObject for React Router
42
+ * @returns Array of RouteObject for React Router (redirect routes only)
43
43
  *
44
44
  * @example
45
45
  * ```tsx
46
46
  * import { createBrowserRouter } from 'react-router-dom';
47
- * import { getInsforgeRoutes } from '@insforge/react';
47
+ * import { getInsforgeRoutes } from '@insforge/react/router';
48
+ * import { InsforgeCallback } from '@insforge/react';
48
49
  *
49
50
  * const router = createBrowserRouter([
50
51
  * {
51
52
  * path: '/',
52
- * element: <Home />
53
+ * element: <Layout />,
54
+ * children: [
55
+ * { index: true, element: <Home /> },
56
+ * // ✅ Required: Manually create callback route
57
+ * { path: 'auth/callback', element: <AuthCallback /> },
58
+ * { path: 'dashboard', element: <Dashboard /> }
59
+ * ]
53
60
  * },
54
- * // Add all Insforge auth routes (sign-in, sign-up, verify-email, etc.)
61
+ * // Add redirect routes (sign-in, sign-up, etc.)
55
62
  * ...getInsforgeRoutes({
56
63
  * baseUrl: 'https://your-backend.com',
57
64
  * builtInAuth: true
58
- * }),
59
- * {
60
- * path: '/dashboard',
61
- * element: <Dashboard />
62
- * }
65
+ * })
63
66
  * ]);
64
- * ```
65
67
  *
66
- * @example
67
- * ```tsx
68
- * // Don't use built-in auth, use your own components instead
69
- * import { SignIn, SignUp } from '@insforge/react';
70
- *
71
- * const router = createBrowserRouter([
72
- * // Only add callback route
73
- * ...getInsforgeRoutes({
74
- * baseUrl: 'https://your-backend.com',
75
- * builtInAuth: false
76
- * }),
77
- * // Your own auth components
78
- * {
79
- * path: '/sign-in',
80
- * element: <SignIn />
81
- * },
82
- * {
83
- * path: '/sign-up',
84
- * element: <SignUp />
85
- * }
86
- * ]);
68
+ * // src/pages/AuthCallback.tsx
69
+ * function AuthCallback() {
70
+ * return <InsforgeCallback redirectTo="/dashboard" />;
71
+ * }
87
72
  * ```
88
73
  *
89
74
  * @example
90
75
  * ```tsx
91
- * // Custom paths
76
+ * // Custom paths for redirect routes
92
77
  * ...getInsforgeRoutes({
93
78
  * baseUrl: 'https://your-backend.com',
94
79
  * builtInAuth: true,
95
80
  * paths: {
96
81
  * signIn: '/login',
97
- * signUp: '/register',
98
- * callback: '/callback'
82
+ * signUp: '/register'
99
83
  * }
100
84
  * })
101
85
  * ```
package/dist/router.d.ts CHANGED
@@ -13,14 +13,13 @@ interface GetInsforgeRoutesConfig {
13
13
  */
14
14
  builtInAuth?: boolean;
15
15
  /**
16
- * Custom paths for auth routes
16
+ * Custom paths for auth redirect routes
17
17
  * @default {
18
18
  * signIn: '/sign-in',
19
19
  * signUp: '/sign-up',
20
20
  * verifyEmail: '/verify-email',
21
21
  * forgotPassword: '/forgot-password',
22
- * resetPassword: '/reset-password',
23
- * callback: '/auth/callback'
22
+ * resetPassword: '/reset-password'
24
23
  * }
25
24
  */
26
25
  paths?: {
@@ -29,73 +28,58 @@ interface GetInsforgeRoutesConfig {
29
28
  verifyEmail?: string;
30
29
  forgotPassword?: string;
31
30
  resetPassword?: string;
32
- callback?: string;
33
31
  };
34
32
  }
35
33
  /**
36
- * Generates Insforge authentication routes for React Router.
34
+ * Generates Insforge authentication redirect routes for React Router.
37
35
  *
38
- * Returns an array of RouteObjects that can be spread into your router configuration.
39
- * Supports all Insforge auth pages: sign-in, sign-up, verify-email, forgot-password, reset-password.
36
+ * Returns redirect routes for sign-in, sign-up, etc. that redirect to your deployed Insforge auth pages.
37
+ *
38
+ * ⚠️ **Important**: You must manually create the `/auth/callback` route in your router
39
+ * to handle authentication callbacks. See documentation for details.
40
40
  *
41
41
  * @param config - Configuration for Insforge routes
42
- * @returns Array of RouteObject for React Router
42
+ * @returns Array of RouteObject for React Router (redirect routes only)
43
43
  *
44
44
  * @example
45
45
  * ```tsx
46
46
  * import { createBrowserRouter } from 'react-router-dom';
47
- * import { getInsforgeRoutes } from '@insforge/react';
47
+ * import { getInsforgeRoutes } from '@insforge/react/router';
48
+ * import { InsforgeCallback } from '@insforge/react';
48
49
  *
49
50
  * const router = createBrowserRouter([
50
51
  * {
51
52
  * path: '/',
52
- * element: <Home />
53
+ * element: <Layout />,
54
+ * children: [
55
+ * { index: true, element: <Home /> },
56
+ * // ✅ Required: Manually create callback route
57
+ * { path: 'auth/callback', element: <AuthCallback /> },
58
+ * { path: 'dashboard', element: <Dashboard /> }
59
+ * ]
53
60
  * },
54
- * // Add all Insforge auth routes (sign-in, sign-up, verify-email, etc.)
61
+ * // Add redirect routes (sign-in, sign-up, etc.)
55
62
  * ...getInsforgeRoutes({
56
63
  * baseUrl: 'https://your-backend.com',
57
64
  * builtInAuth: true
58
- * }),
59
- * {
60
- * path: '/dashboard',
61
- * element: <Dashboard />
62
- * }
65
+ * })
63
66
  * ]);
64
- * ```
65
67
  *
66
- * @example
67
- * ```tsx
68
- * // Don't use built-in auth, use your own components instead
69
- * import { SignIn, SignUp } from '@insforge/react';
70
- *
71
- * const router = createBrowserRouter([
72
- * // Only add callback route
73
- * ...getInsforgeRoutes({
74
- * baseUrl: 'https://your-backend.com',
75
- * builtInAuth: false
76
- * }),
77
- * // Your own auth components
78
- * {
79
- * path: '/sign-in',
80
- * element: <SignIn />
81
- * },
82
- * {
83
- * path: '/sign-up',
84
- * element: <SignUp />
85
- * }
86
- * ]);
68
+ * // src/pages/AuthCallback.tsx
69
+ * function AuthCallback() {
70
+ * return <InsforgeCallback redirectTo="/dashboard" />;
71
+ * }
87
72
  * ```
88
73
  *
89
74
  * @example
90
75
  * ```tsx
91
- * // Custom paths
76
+ * // Custom paths for redirect routes
92
77
  * ...getInsforgeRoutes({
93
78
  * baseUrl: 'https://your-backend.com',
94
79
  * builtInAuth: true,
95
80
  * paths: {
96
81
  * signIn: '/login',
97
- * signUp: '/register',
98
- * callback: '/callback'
82
+ * signUp: '/register'
99
83
  * }
100
84
  * })
101
85
  * ```
package/dist/router.js CHANGED
@@ -1,83 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
- require('@insforge/sdk');
5
4
  var jsxRuntime = require('react/jsx-runtime');
6
5
 
7
- var InsforgeContext = react.createContext(
8
- void 0
9
- );
10
- function useInsforge() {
11
- const context = react.useContext(InsforgeContext);
12
- if (!context) {
13
- throw new Error("useInsforge must be used within InsforgeProvider");
14
- }
15
- return context;
16
- }
17
- function InsforgeCallback({
18
- redirectTo,
19
- onSuccess,
20
- onError,
21
- loadingComponent,
22
- onRedirect
23
- }) {
24
- const isProcessingRef = react.useRef(false);
25
- const { reloadAuth } = useInsforge();
26
- react.useEffect(() => {
27
- const processCallback = async () => {
28
- if (isProcessingRef.current) return;
29
- isProcessingRef.current = true;
30
- const searchParams = new URLSearchParams(window.location.search);
31
- const error = searchParams.get("error");
32
- if (error) {
33
- if (onError) {
34
- onError(error);
35
- } else {
36
- const errorUrl = "/?error=" + encodeURIComponent(error);
37
- if (onRedirect) {
38
- onRedirect(errorUrl);
39
- } else {
40
- window.location.href = errorUrl;
41
- }
42
- }
43
- return;
44
- }
45
- const result = await reloadAuth();
46
- if (!result.success) {
47
- const errorMsg = result.error || "authentication_failed";
48
- if (onError) {
49
- onError(errorMsg);
50
- } else {
51
- const errorUrl = "/?error=" + encodeURIComponent(errorMsg);
52
- if (onRedirect) {
53
- onRedirect(errorUrl);
54
- } else {
55
- window.location.href = errorUrl;
56
- }
57
- }
58
- return;
59
- }
60
- window.history.replaceState({}, "", window.location.pathname);
61
- if (onSuccess) {
62
- onSuccess();
63
- }
64
- const destination = redirectTo || sessionStorage.getItem("auth_destination") || sessionStorage.getItem("oauth_final_destination") || "/";
65
- sessionStorage.removeItem("auth_destination");
66
- sessionStorage.removeItem("oauth_final_destination");
67
- if (onRedirect) {
68
- onRedirect(destination);
69
- } else {
70
- window.location.href = destination;
71
- }
72
- };
73
- processCallback();
74
- }, []);
75
- const defaultLoading = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
76
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-semibold mb-4", children: "Completing authentication..." }),
77
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto" })
78
- ] }) });
79
- return loadingComponent || defaultLoading;
80
- }
81
6
  function RedirectToAuth({ baseUrl, path }) {
82
7
  react.useEffect(() => {
83
8
  const callbackUrl = `${window.location.origin}/auth/callback`;
@@ -98,16 +23,9 @@ function getInsforgeRoutes(config) {
98
23
  signUp = "/sign-up",
99
24
  verifyEmail = "/verify-email",
100
25
  forgotPassword = "/forgot-password",
101
- resetPassword = "/reset-password",
102
- callback = "/auth/callback"
26
+ resetPassword = "/reset-password"
103
27
  } = paths;
104
- const routes = [
105
- // Always include callback route
106
- {
107
- path: callback,
108
- element: /* @__PURE__ */ jsxRuntime.jsx(InsforgeCallback, {})
109
- }
110
- ];
28
+ const routes = [];
111
29
  if (builtInAuth) {
112
30
  routes.push(
113
31
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider/InsforgeProvider.tsx","../src/components/InsforgeCallback.tsx","../src/router/getInsforgeRoutes.tsx"],"names":["createContext","useContext","useRef","useEffect","jsx","jsxs"],"mappings":"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","file":"router.js","sourcesContent":["\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useState,\r\n useCallback,\r\n useRef,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { createClient } from \"@insforge/sdk\";\r\nimport type { InsforgeUser } from \"../types\";\r\nimport { GetPublicAuthConfigResponse } from \"@insforge/shared-schemas\";\r\n\r\ninterface InsforgeContextValue {\r\n // Auth state\r\n user: InsforgeUser | null;\r\n isLoaded: boolean;\r\n isSignedIn: boolean;\r\n\r\n // Auth methods\r\n setUser: (user: InsforgeUser | null) => void;\r\n signIn: (\r\n email: string,\r\n password: string\r\n ) => Promise<\r\n | {\r\n user?: { id: string; email: string; name: string };\r\n accessToken: string | null;\r\n }\r\n | { error: string }\r\n >;\r\n signUp: (\r\n email: string,\r\n password: string\r\n ) => Promise<\r\n | {\r\n user?: { id: string; email: string; name: string };\r\n accessToken: string | null;\r\n }\r\n | { error: string }\r\n >;\r\n signOut: () => Promise<void>;\r\n updateUser: (data: Partial<InsforgeUser>) => Promise<void>;\r\n reloadAuth: () => Promise<{ success: boolean; error?: string }>;\r\n\r\n // Email verification methods\r\n sendPasswordResetCode: (\r\n email: string\r\n ) => Promise<{ success: boolean; message: string } | null>;\r\n resetPassword: (\r\n token: string,\r\n newPassword: string\r\n ) => Promise<{ message: string; redirectTo?: string } | null>;\r\n verifyEmail: (\r\n token: string\r\n ) => Promise<{ accessToken: string; user?: any } | null>;\r\n\r\n // Public auth config\r\n getPublicAuthConfig: () => Promise<GetPublicAuthConfigResponse | null>;\r\n // Base config\r\n baseUrl: string;\r\n}\r\n\r\nconst InsforgeContext = createContext<InsforgeContextValue | undefined>(\r\n undefined\r\n);\r\n\r\nexport interface InsforgeProviderProps {\r\n children: ReactNode;\r\n baseUrl: string;\r\n onAuthChange?: (user: InsforgeUser | null) => void;\r\n // Optional: custom token sync functions (e.g., for Next.js cookie sync)\r\n syncTokenToCookie?: (token: string) => Promise<boolean>;\r\n clearCookie?: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Unified Insforge Provider - manages authentication state and configuration\r\n *\r\n * Manages user authentication state and provides all necessary context to child components.\r\n * Works with any React framework (Next.js, Vite, Remix, etc.).\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage (React/Vite)\r\n * import { InsforgeProvider } from '@insforge/react';\r\n *\r\n * export default function App() {\r\n * return (\r\n * <InsforgeProvider baseUrl={process.env.VITE_INSFORGE_BASE_URL}>\r\n * {children}\r\n * </InsforgeProvider>\r\n * );\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With cookie sync (Next.js optimization)\r\n * <InsforgeProvider\r\n * baseUrl={baseUrl}\r\n * syncTokenToCookie={async (token) => {\r\n * await fetch('/api/auth', {\r\n * method: 'POST',\r\n * body: JSON.stringify({ token })\r\n * });\r\n * return true;\r\n * }}\r\n * clearCookie={async () => {\r\n * await fetch('/api/auth', { method: 'DELETE' });\r\n * }}\r\n * >\r\n * {children}\r\n * </InsforgeProvider>\r\n * ```\r\n */\r\nexport function InsforgeProvider({\r\n children,\r\n baseUrl,\r\n onAuthChange,\r\n syncTokenToCookie,\r\n clearCookie,\r\n}: InsforgeProviderProps) {\r\n // Auth state\r\n const [user, setUser] = useState<InsforgeUser | null>(null);\r\n const [isLoaded, setIsLoaded] = useState(false);\r\n\r\n const refreshIntervalRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n // Initialize SDK client with lazy initialization - only runs once\r\n const [insforge] = useState(() => createClient({ baseUrl }));\r\n\r\n // Load auth state - returns explicit success/error status\r\n const loadAuthState = useCallback(async (): Promise<{\r\n success: boolean;\r\n error?: string;\r\n }> => {\r\n try {\r\n // Use SDK's getCurrentSession() to check for existing session\r\n const sessionResult = insforge.auth.getCurrentSession();\r\n const session = sessionResult.data?.session;\r\n const token = session?.accessToken || null;\r\n\r\n if (!token) {\r\n // No token, user is not authenticated\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n setIsLoaded(true);\r\n return { success: false, error: \"no_session\" };\r\n }\r\n\r\n const userResult = await insforge.auth.getCurrentUser();\r\n\r\n if (userResult.data) {\r\n // Token is valid, update user state with fresh data\r\n const profile = userResult.data.profile;\r\n const userData: InsforgeUser = {\r\n id: userResult.data.user.id,\r\n email: userResult.data.user.email,\r\n name: (profile?.nickname as string | undefined) || \"\",\r\n avatarUrl: (profile?.avatarUrl as string | undefined) || \"\",\r\n };\r\n\r\n setUser(userData);\r\n\r\n if (onAuthChange) {\r\n onAuthChange(userData);\r\n }\r\n setIsLoaded(true);\r\n return { success: true };\r\n } else {\r\n // Token invalid or expired\r\n await insforge.auth.signOut();\r\n\r\n // Clear cookie if function provided\r\n if (clearCookie) {\r\n try {\r\n await clearCookie();\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n }\r\n\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n setIsLoaded(true);\r\n return { success: false, error: \"invalid_token\" };\r\n }\r\n } catch (error) {\r\n // Token validation failed\r\n console.error(\"[InsforgeProvider] Token validation failed:\", error);\r\n\r\n await insforge.auth.signOut();\r\n\r\n // Clear cookie if function provided\r\n if (clearCookie) {\r\n try {\r\n await clearCookie();\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n }\r\n\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n setIsLoaded(true);\r\n\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : \"authentication_failed\",\r\n };\r\n }\r\n }, [insforge, onAuthChange, syncTokenToCookie, clearCookie]);\r\n\r\n useEffect(() => {\r\n // Run loadAuthState only once on mount\r\n loadAuthState();\r\n\r\n return () => {\r\n if (refreshIntervalRef.current) {\r\n clearInterval(refreshIntervalRef.current);\r\n }\r\n };\r\n }, []); // Empty deps - run only on mount\r\n\r\n const getPublicAuthConfig = useCallback(async () => {\r\n try {\r\n const result = await insforge.auth.getPublicAuthConfig();\r\n if (result.data) {\r\n return result.data;\r\n } else {\r\n console.error('[InsforgeProvider] Failed to get public auth config:', result.error);\r\n return null;\r\n }\r\n } catch (error) {\r\n console.error(\r\n \"[InsforgeProvider] Failed to get public auth config:\",\r\n error\r\n );\r\n return null;\r\n }\r\n }, [insforge]);\r\n\r\n /**\r\n * Helper function to handle successful authentication\r\n */\r\n const handleAuthSuccess = useCallback(\r\n async (\r\n authToken: string,\r\n fallbackUser?: { id?: string; email?: string; name?: string }\r\n ) => {\r\n const userResult = await insforge.auth.getCurrentUser();\r\n\r\n if (userResult.data) {\r\n const profile = userResult.data.profile;\r\n const userData: InsforgeUser = {\r\n id: userResult.data.user.id,\r\n email: userResult.data.user.email,\r\n name: (profile?.nickname as string | undefined) || \"\",\r\n avatarUrl: (profile?.avatarUrl as string | undefined) || \"\",\r\n };\r\n\r\n setUser(userData);\r\n\r\n if (onAuthChange) {\r\n onAuthChange(userData);\r\n }\r\n\r\n // Try to sync token to cookie if function provided\r\n if (syncTokenToCookie) {\r\n try {\r\n await syncTokenToCookie(authToken);\r\n } catch (error) {\r\n // Cookie sync failed - that's okay\r\n }\r\n }\r\n } else if (fallbackUser) {\r\n // Fallback to basic user data if getCurrentUser fails\r\n const userData: InsforgeUser = {\r\n id: fallbackUser.id || \"\",\r\n email: fallbackUser.email || \"\",\r\n name: fallbackUser.name || \"\",\r\n avatarUrl: \"\",\r\n };\r\n\r\n setUser(userData);\r\n\r\n if (onAuthChange) {\r\n onAuthChange(userData);\r\n }\r\n }\r\n },\r\n [insforge, onAuthChange, syncTokenToCookie]\r\n );\r\n\r\n const signIn = useCallback(\r\n async (email: string, password: string) => {\r\n const sdkResult = await insforge.auth.signInWithPassword({\r\n email,\r\n password,\r\n });\r\n\r\n if (sdkResult.data) {\r\n await handleAuthSuccess(\r\n sdkResult.data.accessToken || \"\",\r\n sdkResult.data.user\r\n ? {\r\n id: sdkResult.data.user.id,\r\n email: sdkResult.data.user.email,\r\n name: sdkResult.data.user.name,\r\n }\r\n : undefined\r\n );\r\n return sdkResult.data;\r\n } else {\r\n const errorMessage =\r\n sdkResult.error?.message || \"Invalid email or password\";\r\n return { error: errorMessage };\r\n }\r\n },\r\n [insforge, handleAuthSuccess]\r\n );\r\n\r\n const signUp = useCallback(\r\n async (email: string, password: string) => {\r\n const sdkResult = await insforge.auth.signUp({ email, password });\r\n\r\n if (sdkResult.data) {\r\n await handleAuthSuccess(\r\n sdkResult.data.accessToken || \"\",\r\n sdkResult.data.user\r\n ? {\r\n id: sdkResult.data.user.id,\r\n email: sdkResult.data.user.email,\r\n name: sdkResult.data.user.name,\r\n }\r\n : undefined\r\n );\r\n return sdkResult.data;\r\n } else {\r\n const errorMessage = sdkResult.error?.message || \"Sign up failed\";\r\n return { error: errorMessage };\r\n }\r\n },\r\n [insforge, handleAuthSuccess]\r\n );\r\n\r\n const signOut = useCallback(async () => {\r\n await insforge.auth.signOut();\r\n\r\n // Clear cookie if function provided\r\n if (clearCookie) {\r\n try {\r\n await clearCookie();\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n }\r\n\r\n // Clear refresh interval if exists\r\n if (refreshIntervalRef.current) {\r\n clearInterval(refreshIntervalRef.current);\r\n }\r\n\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n }, [insforge, onAuthChange, clearCookie]);\r\n\r\n const updateUser = useCallback(\r\n async (data: Partial<InsforgeUser>) => {\r\n if (!user) throw new Error(\"No user signed in\");\r\n\r\n const profileUpdate: Record<string, any> = {\r\n nickname: data.name,\r\n avatarUrl: data.avatarUrl,\r\n };\r\n\r\n const result = await insforge.auth.setProfile(profileUpdate);\r\n\r\n if (result.data) {\r\n const userResult = await insforge.auth.getCurrentUser();\r\n if (userResult.data) {\r\n const profile = userResult.data.profile;\r\n const updatedUser: InsforgeUser = {\r\n id: userResult.data.user.id,\r\n email: userResult.data.user.email,\r\n name: (profile?.nickname as string | undefined) || \"\",\r\n avatarUrl: (profile?.avatarUrl as string | undefined) || \"\",\r\n };\r\n setUser(updatedUser);\r\n if (onAuthChange) {\r\n onAuthChange(updatedUser);\r\n }\r\n }\r\n }\r\n },\r\n [user, onAuthChange, insforge]\r\n );\r\n\r\n const sendPasswordResetCode = useCallback(\r\n async (email: string) => {\r\n const sdkResult = await insforge.auth.sendPasswordResetCode({ email });\r\n return sdkResult.data;\r\n },\r\n [insforge]\r\n );\r\n\r\n const resetPassword = useCallback(\r\n async (token: string, newPassword: string) => {\r\n const sdkResult = await insforge.auth.resetPassword({\r\n newPassword,\r\n otp: token,\r\n });\r\n return sdkResult.data;\r\n },\r\n [insforge]\r\n );\r\n\r\n const verifyEmail = useCallback(\r\n async (token: string) => {\r\n const sdkResult = await insforge.auth.verifyEmail({ otp: token });\r\n return sdkResult.data;\r\n },\r\n [insforge]\r\n );\r\n\r\n return (\r\n <InsforgeContext.Provider\r\n value={{\r\n user,\r\n isLoaded,\r\n isSignedIn: !!user,\r\n setUser,\r\n signIn,\r\n signUp,\r\n signOut,\r\n updateUser,\r\n reloadAuth: loadAuthState,\r\n baseUrl,\r\n sendPasswordResetCode,\r\n resetPassword,\r\n verifyEmail,\r\n getPublicAuthConfig,\r\n }}\r\n >\r\n {children}\r\n </InsforgeContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * Hook to access Insforge context\r\n *\r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { user, isSignedIn, signOut } = useInsforge();\r\n *\r\n * if (!isSignedIn) return <SignIn />;\r\n *\r\n * return (\r\n * <div>\r\n * <p>Welcome {user.email}</p>\r\n * <button onClick={signOut}>Sign Out</button>\r\n * </div>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function useInsforge(): InsforgeContextValue {\r\n const context = useContext(InsforgeContext);\r\n if (!context) {\r\n throw new Error(\"useInsforge must be used within InsforgeProvider\");\r\n }\r\n return context;\r\n}\r\n","'use client';\r\n\r\nimport { useEffect, useRef, type ReactNode } from 'react';\r\nimport { useInsforge } from '../provider/InsforgeProvider';\r\n\r\nexport interface InsforgeCallbackProps {\r\n /**\r\n * Redirect destination after successful authentication\r\n */\r\n redirectTo?: string;\r\n \r\n /**\r\n * Callback fired on successful authentication\r\n */\r\n onSuccess?: () => void;\r\n \r\n /**\r\n * Callback fired on authentication error\r\n */\r\n onError?: (error: string) => void;\r\n \r\n /**\r\n * Custom loading component\r\n */\r\n loadingComponent?: ReactNode;\r\n \r\n /**\r\n * Custom redirect handler (default: window.location)\r\n */\r\n onRedirect?: (url: string) => void;\r\n}\r\n\r\n/**\r\n * InsforgeCallback - Handles OAuth and email/password authentication callbacks\r\n * \r\n * Place this component on your `/auth/callback` page.\r\n * \r\n * @example\r\n * ```tsx\r\n * // Minimal usage\r\n * export default function CallbackPage() {\r\n * return <InsforgeCallback />;\r\n * }\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // With Next.js router\r\n * import { useRouter } from 'next/navigation';\r\n * \r\n * export default function CallbackPage() {\r\n * const router = useRouter();\r\n * return (\r\n * <InsforgeCallback\r\n * redirectTo=\"/dashboard\"\r\n * onRedirect={(url) => router.push(url)}\r\n * />\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function InsforgeCallback({\r\n redirectTo,\r\n onSuccess,\r\n onError,\r\n loadingComponent,\r\n onRedirect,\r\n}: InsforgeCallbackProps) {\r\n const isProcessingRef = useRef(false);\r\n const { reloadAuth } = useInsforge();\r\n\r\n useEffect(() => {\r\n const processCallback = async () => {\r\n // Prevent double-processing\r\n if (isProcessingRef.current) return;\r\n isProcessingRef.current = true;\r\n\r\n // Get search params\r\n const searchParams = new URLSearchParams(window.location.search);\r\n\r\n // Check for error from backend\r\n const error = searchParams.get('error');\r\n if (error) {\r\n if (onError) {\r\n onError(error);\r\n } else {\r\n const errorUrl = '/?error=' + encodeURIComponent(error);\r\n if (onRedirect) {\r\n onRedirect(errorUrl);\r\n } else {\r\n window.location.href = errorUrl;\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Reload auth state\r\n const result = await reloadAuth();\r\n\r\n if (!result.success) {\r\n const errorMsg = result.error || 'authentication_failed';\r\n if (onError) {\r\n onError(errorMsg);\r\n } else {\r\n const errorUrl = '/?error=' + encodeURIComponent(errorMsg);\r\n if (onRedirect) {\r\n onRedirect(errorUrl);\r\n } else {\r\n window.location.href = errorUrl;\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Authentication successful!\r\n // Clean URL\r\n window.history.replaceState({}, '', window.location.pathname);\r\n\r\n // Fire success callback\r\n if (onSuccess) {\r\n onSuccess();\r\n }\r\n\r\n // Get destination and redirect\r\n const destination = \r\n redirectTo || \r\n sessionStorage.getItem('auth_destination') || \r\n sessionStorage.getItem('oauth_final_destination') || \r\n '/';\r\n \r\n sessionStorage.removeItem('auth_destination');\r\n sessionStorage.removeItem('oauth_final_destination');\r\n\r\n if (onRedirect) {\r\n onRedirect(destination);\r\n } else {\r\n window.location.href = destination;\r\n }\r\n };\r\n\r\n processCallback();\r\n }, []); // Empty deps - run once\r\n\r\n const defaultLoading = (\r\n <div className=\"flex items-center justify-center min-h-screen\">\r\n <div className=\"text-center\">\r\n <h2 className=\"text-2xl font-semibold mb-4\">Completing authentication...</h2>\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto\"></div>\r\n </div>\r\n </div>\r\n );\r\n\r\n return loadingComponent || defaultLoading;\r\n}\r\n\r\n","'use client';\r\n\r\nimport { useEffect } from 'react';\r\nimport type { RouteObject } from 'react-router-dom';\r\nimport { InsforgeCallback } from '../components/InsforgeCallback';\r\n\r\ninterface GetInsforgeRoutesConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n \r\n /**\r\n * Whether to use built-in auth (deployed Insforge Auth)\r\n * When true: redirects to baseUrl/auth/* pages\r\n * When false: no redirect routes are added (use your own components)\r\n * @default true\r\n */\r\n builtInAuth?: boolean;\r\n \r\n /**\r\n * Custom paths for auth routes\r\n * @default {\r\n * signIn: '/sign-in',\r\n * signUp: '/sign-up',\r\n * verifyEmail: '/verify-email',\r\n * forgotPassword: '/forgot-password',\r\n * resetPassword: '/reset-password',\r\n * callback: '/auth/callback'\r\n * }\r\n */\r\n paths?: {\r\n signIn?: string;\r\n signUp?: string;\r\n verifyEmail?: string;\r\n forgotPassword?: string;\r\n resetPassword?: string;\r\n callback?: string;\r\n };\r\n}\r\n\r\n/**\r\n * Helper component for redirecting to external auth\r\n */\r\nfunction RedirectToAuth({ baseUrl, path }: { baseUrl: string; path: string }) {\r\n useEffect(() => {\r\n const callbackUrl = `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(path, baseUrl);\r\n authUrl.searchParams.set('redirect', callbackUrl);\r\n window.location.replace(authUrl.toString());\r\n }, [baseUrl, path]);\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Generates Insforge authentication routes for React Router.\r\n * \r\n * Returns an array of RouteObjects that can be spread into your router configuration.\r\n * Supports all Insforge auth pages: sign-in, sign-up, verify-email, forgot-password, reset-password.\r\n * \r\n * @param config - Configuration for Insforge routes\r\n * @returns Array of RouteObject for React Router\r\n * \r\n * @example\r\n * ```tsx\r\n * import { createBrowserRouter } from 'react-router-dom';\r\n * import { getInsforgeRoutes } from '@insforge/react';\r\n * \r\n * const router = createBrowserRouter([\r\n * {\r\n * path: '/',\r\n * element: <Home />\r\n * },\r\n * // Add all Insforge auth routes (sign-in, sign-up, verify-email, etc.)\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true\r\n * }),\r\n * {\r\n * path: '/dashboard',\r\n * element: <Dashboard />\r\n * }\r\n * ]);\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Don't use built-in auth, use your own components instead\r\n * import { SignIn, SignUp } from '@insforge/react';\r\n * \r\n * const router = createBrowserRouter([\r\n * // Only add callback route\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: false\r\n * }),\r\n * // Your own auth components\r\n * {\r\n * path: '/sign-in',\r\n * element: <SignIn />\r\n * },\r\n * {\r\n * path: '/sign-up',\r\n * element: <SignUp />\r\n * }\r\n * ]);\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Custom paths\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true,\r\n * paths: {\r\n * signIn: '/login',\r\n * signUp: '/register',\r\n * callback: '/callback'\r\n * }\r\n * })\r\n * ```\r\n */\r\nexport function getInsforgeRoutes(config: GetInsforgeRoutesConfig): RouteObject[] {\r\n const {\r\n baseUrl,\r\n builtInAuth = true,\r\n paths = {},\r\n } = config;\r\n\r\n const {\r\n signIn = '/sign-in',\r\n signUp = '/sign-up',\r\n verifyEmail = '/verify-email',\r\n forgotPassword = '/forgot-password',\r\n resetPassword = '/reset-password',\r\n callback = '/auth/callback',\r\n } = paths;\r\n\r\n const routes: RouteObject[] = [\r\n // Always include callback route\r\n {\r\n path: callback,\r\n element: <InsforgeCallback />,\r\n },\r\n ];\r\n\r\n // Only add redirect routes if using built-in auth\r\n if (builtInAuth) {\r\n routes.push(\r\n {\r\n path: signIn,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-in\" />,\r\n },\r\n {\r\n path: signUp,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-up\" />,\r\n },\r\n {\r\n path: verifyEmail,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/verify-email\" />,\r\n },\r\n {\r\n path: forgotPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/forgot-password\" />,\r\n },\r\n {\r\n path: resetPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/reset-password\" />,\r\n }\r\n );\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n"]}
1
+ {"version":3,"sources":["../src/router/getInsforgeRoutes.tsx"],"names":["useEffect","jsx"],"mappings":";;;;;AAyCA,SAAS,cAAA,CAAe,EAAE,OAAA,EAAS,IAAA,EAAK,EAAsC;AAC5E,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,WAAA,GAAc,CAAA,EAAG,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,cAAA,CAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AACrC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,WAAW,CAAA;AAChD,IAAA,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,OAAA,CAAQ,QAAA,EAAU,CAAA;AAAA,EAC5C,CAAA,EAAG,CAAC,OAAA,EAAS,IAAI,CAAC,CAAA;AAElB,EAAA,OAAO,IAAA;AACT;AAwDO,SAAS,kBAAkB,MAAA,EAAgD;AAChF,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,WAAA,GAAc,IAAA;AAAA,IACd,QAAQ;AAAC,GACX,GAAI,MAAA;AAEJ,EAAA,MAAM;AAAA,IACJ,MAAA,GAAS,UAAA;AAAA,IACT,MAAA,GAAS,UAAA;AAAA,IACT,WAAA,GAAc,eAAA;AAAA,IACd,cAAA,GAAiB,kBAAA;AAAA,IACjB,aAAA,GAAgB;AAAA,GAClB,GAAI,KAAA;AAEJ,EAAA,MAAM,SAAwB,EAAC;AAG/B,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAA,CAAO,IAAA;AAAA,MACL;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,kBAASC,cAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,eAAA,EAAgB;AAAA,OAClE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,kBAASA,cAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,eAAA,EAAgB;AAAA,OAClE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,WAAA;AAAA,QACN,OAAA,kBAASA,cAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,oBAAA,EAAqB;AAAA,OACvE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,kBAASA,cAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,uBAAA,EAAwB;AAAA,OAC1E;AAAA,MACA;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,kBAASA,cAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,sBAAA,EAAuB;AAAA;AACzE,KACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT","file":"router.js","sourcesContent":["'use client';\r\n\r\nimport { useEffect } from 'react';\r\nimport type { RouteObject } from 'react-router-dom';\r\n\r\ninterface GetInsforgeRoutesConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n \r\n /**\r\n * Whether to use built-in auth (deployed Insforge Auth)\r\n * When true: redirects to baseUrl/auth/* pages\r\n * When false: no redirect routes are added (use your own components)\r\n * @default true\r\n */\r\n builtInAuth?: boolean;\r\n \r\n /**\r\n * Custom paths for auth redirect routes\r\n * @default {\r\n * signIn: '/sign-in',\r\n * signUp: '/sign-up',\r\n * verifyEmail: '/verify-email',\r\n * forgotPassword: '/forgot-password',\r\n * resetPassword: '/reset-password'\r\n * }\r\n */\r\n paths?: {\r\n signIn?: string;\r\n signUp?: string;\r\n verifyEmail?: string;\r\n forgotPassword?: string;\r\n resetPassword?: string;\r\n };\r\n}\r\n\r\n/**\r\n * Helper component for redirecting to external auth\r\n */\r\nfunction RedirectToAuth({ baseUrl, path }: { baseUrl: string; path: string }) {\r\n useEffect(() => {\r\n const callbackUrl = `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(path, baseUrl);\r\n authUrl.searchParams.set('redirect', callbackUrl);\r\n window.location.replace(authUrl.toString());\r\n }, [baseUrl, path]);\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Generates Insforge authentication redirect routes for React Router.\r\n * \r\n * Returns redirect routes for sign-in, sign-up, etc. that redirect to your deployed Insforge auth pages.\r\n * \r\n * ⚠️ **Important**: You must manually create the `/auth/callback` route in your router\r\n * to handle authentication callbacks. See documentation for details.\r\n * \r\n * @param config - Configuration for Insforge routes\r\n * @returns Array of RouteObject for React Router (redirect routes only)\r\n * \r\n * @example\r\n * ```tsx\r\n * import { createBrowserRouter } from 'react-router-dom';\r\n * import { getInsforgeRoutes } from '@insforge/react/router';\r\n * import { InsforgeCallback } from '@insforge/react';\r\n * \r\n * const router = createBrowserRouter([\r\n * {\r\n * path: '/',\r\n * element: <Layout />,\r\n * children: [\r\n * { index: true, element: <Home /> },\r\n * // ✅ Required: Manually create callback route\r\n * { path: 'auth/callback', element: <AuthCallback /> },\r\n * { path: 'dashboard', element: <Dashboard /> }\r\n * ]\r\n * },\r\n * // Add redirect routes (sign-in, sign-up, etc.)\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true\r\n * })\r\n * ]);\r\n * \r\n * // src/pages/AuthCallback.tsx\r\n * function AuthCallback() {\r\n * return <InsforgeCallback redirectTo=\"/dashboard\" />;\r\n * }\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Custom paths for redirect routes\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true,\r\n * paths: {\r\n * signIn: '/login',\r\n * signUp: '/register'\r\n * }\r\n * })\r\n * ```\r\n */\r\nexport function getInsforgeRoutes(config: GetInsforgeRoutesConfig): RouteObject[] {\r\n const {\r\n baseUrl,\r\n builtInAuth = true,\r\n paths = {},\r\n } = config;\r\n\r\n const {\r\n signIn = '/sign-in',\r\n signUp = '/sign-up',\r\n verifyEmail = '/verify-email',\r\n forgotPassword = '/forgot-password',\r\n resetPassword = '/reset-password',\r\n } = paths;\r\n\r\n const routes: RouteObject[] = [];\r\n\r\n // Only add redirect routes if using built-in auth\r\n if (builtInAuth) {\r\n routes.push(\r\n {\r\n path: signIn,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-in\" />,\r\n },\r\n {\r\n path: signUp,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-up\" />,\r\n },\r\n {\r\n path: verifyEmail,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/verify-email\" />,\r\n },\r\n {\r\n path: forgotPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/forgot-password\" />,\r\n },\r\n {\r\n path: resetPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/reset-password\" />,\r\n }\r\n );\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n"]}
package/dist/router.mjs CHANGED
@@ -1,81 +1,6 @@
1
- import { createContext, useEffect, useRef, useContext } from 'react';
2
- import '@insforge/sdk';
3
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { useEffect } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
4
3
 
5
- var InsforgeContext = createContext(
6
- void 0
7
- );
8
- function useInsforge() {
9
- const context = useContext(InsforgeContext);
10
- if (!context) {
11
- throw new Error("useInsforge must be used within InsforgeProvider");
12
- }
13
- return context;
14
- }
15
- function InsforgeCallback({
16
- redirectTo,
17
- onSuccess,
18
- onError,
19
- loadingComponent,
20
- onRedirect
21
- }) {
22
- const isProcessingRef = useRef(false);
23
- const { reloadAuth } = useInsforge();
24
- useEffect(() => {
25
- const processCallback = async () => {
26
- if (isProcessingRef.current) return;
27
- isProcessingRef.current = true;
28
- const searchParams = new URLSearchParams(window.location.search);
29
- const error = searchParams.get("error");
30
- if (error) {
31
- if (onError) {
32
- onError(error);
33
- } else {
34
- const errorUrl = "/?error=" + encodeURIComponent(error);
35
- if (onRedirect) {
36
- onRedirect(errorUrl);
37
- } else {
38
- window.location.href = errorUrl;
39
- }
40
- }
41
- return;
42
- }
43
- const result = await reloadAuth();
44
- if (!result.success) {
45
- const errorMsg = result.error || "authentication_failed";
46
- if (onError) {
47
- onError(errorMsg);
48
- } else {
49
- const errorUrl = "/?error=" + encodeURIComponent(errorMsg);
50
- if (onRedirect) {
51
- onRedirect(errorUrl);
52
- } else {
53
- window.location.href = errorUrl;
54
- }
55
- }
56
- return;
57
- }
58
- window.history.replaceState({}, "", window.location.pathname);
59
- if (onSuccess) {
60
- onSuccess();
61
- }
62
- const destination = redirectTo || sessionStorage.getItem("auth_destination") || sessionStorage.getItem("oauth_final_destination") || "/";
63
- sessionStorage.removeItem("auth_destination");
64
- sessionStorage.removeItem("oauth_final_destination");
65
- if (onRedirect) {
66
- onRedirect(destination);
67
- } else {
68
- window.location.href = destination;
69
- }
70
- };
71
- processCallback();
72
- }, []);
73
- const defaultLoading = /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
74
- /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold mb-4", children: "Completing authentication..." }),
75
- /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto" })
76
- ] }) });
77
- return loadingComponent || defaultLoading;
78
- }
79
4
  function RedirectToAuth({ baseUrl, path }) {
80
5
  useEffect(() => {
81
6
  const callbackUrl = `${window.location.origin}/auth/callback`;
@@ -96,16 +21,9 @@ function getInsforgeRoutes(config) {
96
21
  signUp = "/sign-up",
97
22
  verifyEmail = "/verify-email",
98
23
  forgotPassword = "/forgot-password",
99
- resetPassword = "/reset-password",
100
- callback = "/auth/callback"
24
+ resetPassword = "/reset-password"
101
25
  } = paths;
102
- const routes = [
103
- // Always include callback route
104
- {
105
- path: callback,
106
- element: /* @__PURE__ */ jsx(InsforgeCallback, {})
107
- }
108
- ];
26
+ const routes = [];
109
27
  if (builtInAuth) {
110
28
  routes.push(
111
29
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider/InsforgeProvider.tsx","../src/components/InsforgeCallback.tsx","../src/router/getInsforgeRoutes.tsx"],"names":["useRef","useEffect","jsx"],"mappings":";;;;AAiEA,IAAM,eAAA,GAAkB,aAAA;AAAA,EACtB;AACF,CAAA;AA4ZO,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAU,WAAW,eAAe,CAAA;AAC1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACpE;AACA,EAAA,OAAO,OAAA;AACT;ACxaO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,UAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,eAAA,GAAkBA,OAAO,KAAK,CAAA;AACpC,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,WAAA,EAAY;AAEnC,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,kBAAkB,YAAY;AAElC,MAAA,IAAI,gBAAgB,OAAA,EAAS;AAC7B,MAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAG1B,MAAA,MAAM,YAAA,GAAe,IAAI,eAAA,CAAgB,MAAA,CAAO,SAAS,MAAM,CAAA;AAG/D,MAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,GAAA,CAAI,OAAO,CAAA;AACtC,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,QACf,CAAA,MAAO;AACL,UAAA,MAAM,QAAA,GAAW,UAAA,GAAa,kBAAA,CAAmB,KAAK,CAAA;AACtD,UAAA,IAAI,UAAA,EAAY;AACd,YAAA,UAAA,CAAW,QAAQ,CAAA;AAAA,UACrB,CAAA,MAAO;AACL,YAAA,MAAA,CAAO,SAAS,IAAA,GAAO,QAAA;AAAA,UACzB;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,EAAW;AAEhC,MAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,QAAA,MAAM,QAAA,GAAW,OAAO,KAAA,IAAS,uBAAA;AACjC,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,QAClB,CAAA,MAAO;AACL,UAAA,MAAM,QAAA,GAAW,UAAA,GAAa,kBAAA,CAAmB,QAAQ,CAAA;AACzD,UAAA,IAAI,UAAA,EAAY;AACd,YAAA,UAAA,CAAW,QAAQ,CAAA;AAAA,UACrB,CAAA,MAAO;AACL,YAAA,MAAA,CAAO,SAAS,IAAA,GAAO,QAAA;AAAA,UACzB;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAIA,MAAA,MAAA,CAAO,QAAQ,YAAA,CAAa,IAAI,EAAA,EAAI,MAAA,CAAO,SAAS,QAAQ,CAAA;AAG5D,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,SAAA,EAAU;AAAA,MACZ;AAGA,MAAA,MAAM,WAAA,GACJ,cACA,cAAA,CAAe,OAAA,CAAQ,kBAAkB,CAAA,IACzC,cAAA,CAAe,OAAA,CAAQ,yBAAyB,CAAA,IAChD,GAAA;AAEF,MAAA,cAAA,CAAe,WAAW,kBAAkB,CAAA;AAC5C,MAAA,cAAA,CAAe,WAAW,yBAAyB,CAAA;AAEnD,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,UAAA,CAAW,WAAW,CAAA;AAAA,MACxB,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,SAAS,IAAA,GAAO,WAAA;AAAA,MACzB;AAAA,IACF,CAAA;AAEA,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,cAAA,mBACJC,GAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,+CAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,aAAA,EACb,QAAA,EAAA;AAAA,oBAAAA,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,6BAAA,EAA8B,QAAA,EAAA,8BAAA,EAA4B,CAAA;AAAA,oBACxEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wEAAA,EAAyE;AAAA,GAAA,EAC1F,CAAA,EACF,CAAA;AAGF,EAAA,OAAO,gBAAA,IAAoB,cAAA;AAC7B;AC7GA,SAAS,cAAA,CAAe,EAAE,OAAA,EAAS,IAAA,EAAK,EAAsC;AAC5E,EAAAD,UAAU,MAAM;AACd,IAAA,MAAM,WAAA,GAAc,CAAA,EAAG,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,cAAA,CAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AACrC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,WAAW,CAAA;AAChD,IAAA,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,OAAA,CAAQ,QAAA,EAAU,CAAA;AAAA,EAC5C,CAAA,EAAG,CAAC,OAAA,EAAS,IAAI,CAAC,CAAA;AAElB,EAAA,OAAO,IAAA;AACT;AAsEO,SAAS,kBAAkB,MAAA,EAAgD;AAChF,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,WAAA,GAAc,IAAA;AAAA,IACd,QAAQ;AAAC,GACX,GAAI,MAAA;AAEJ,EAAA,MAAM;AAAA,IACJ,MAAA,GAAS,UAAA;AAAA,IACT,MAAA,GAAS,UAAA;AAAA,IACT,WAAA,GAAc,eAAA;AAAA,IACd,cAAA,GAAiB,kBAAA;AAAA,IACjB,aAAA,GAAgB,iBAAA;AAAA,IAChB,QAAA,GAAW;AAAA,GACb,GAAI,KAAA;AAEJ,EAAA,MAAM,MAAA,GAAwB;AAAA;AAAA,IAE5B;AAAA,MACE,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,kBAASC,GAAAA,CAAC,gBAAA,EAAA,EAAiB;AAAA;AAC7B,GACF;AAGA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAA,CAAO,IAAA;AAAA,MACL;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,yBAASA,GAAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,eAAA,EAAgB;AAAA,OAClE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,yBAASA,GAAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,eAAA,EAAgB;AAAA,OAClE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,WAAA;AAAA,QACN,yBAASA,GAAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,oBAAA,EAAqB;AAAA,OACvE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,cAAA;AAAA,QACN,yBAASA,GAAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,uBAAA,EAAwB;AAAA,OAC1E;AAAA,MACA;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,yBAASA,GAAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,sBAAA,EAAuB;AAAA;AACzE,KACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT","file":"router.mjs","sourcesContent":["\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useState,\r\n useCallback,\r\n useRef,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { createClient } from \"@insforge/sdk\";\r\nimport type { InsforgeUser } from \"../types\";\r\nimport { GetPublicAuthConfigResponse } from \"@insforge/shared-schemas\";\r\n\r\ninterface InsforgeContextValue {\r\n // Auth state\r\n user: InsforgeUser | null;\r\n isLoaded: boolean;\r\n isSignedIn: boolean;\r\n\r\n // Auth methods\r\n setUser: (user: InsforgeUser | null) => void;\r\n signIn: (\r\n email: string,\r\n password: string\r\n ) => Promise<\r\n | {\r\n user?: { id: string; email: string; name: string };\r\n accessToken: string | null;\r\n }\r\n | { error: string }\r\n >;\r\n signUp: (\r\n email: string,\r\n password: string\r\n ) => Promise<\r\n | {\r\n user?: { id: string; email: string; name: string };\r\n accessToken: string | null;\r\n }\r\n | { error: string }\r\n >;\r\n signOut: () => Promise<void>;\r\n updateUser: (data: Partial<InsforgeUser>) => Promise<void>;\r\n reloadAuth: () => Promise<{ success: boolean; error?: string }>;\r\n\r\n // Email verification methods\r\n sendPasswordResetCode: (\r\n email: string\r\n ) => Promise<{ success: boolean; message: string } | null>;\r\n resetPassword: (\r\n token: string,\r\n newPassword: string\r\n ) => Promise<{ message: string; redirectTo?: string } | null>;\r\n verifyEmail: (\r\n token: string\r\n ) => Promise<{ accessToken: string; user?: any } | null>;\r\n\r\n // Public auth config\r\n getPublicAuthConfig: () => Promise<GetPublicAuthConfigResponse | null>;\r\n // Base config\r\n baseUrl: string;\r\n}\r\n\r\nconst InsforgeContext = createContext<InsforgeContextValue | undefined>(\r\n undefined\r\n);\r\n\r\nexport interface InsforgeProviderProps {\r\n children: ReactNode;\r\n baseUrl: string;\r\n onAuthChange?: (user: InsforgeUser | null) => void;\r\n // Optional: custom token sync functions (e.g., for Next.js cookie sync)\r\n syncTokenToCookie?: (token: string) => Promise<boolean>;\r\n clearCookie?: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Unified Insforge Provider - manages authentication state and configuration\r\n *\r\n * Manages user authentication state and provides all necessary context to child components.\r\n * Works with any React framework (Next.js, Vite, Remix, etc.).\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage (React/Vite)\r\n * import { InsforgeProvider } from '@insforge/react';\r\n *\r\n * export default function App() {\r\n * return (\r\n * <InsforgeProvider baseUrl={process.env.VITE_INSFORGE_BASE_URL}>\r\n * {children}\r\n * </InsforgeProvider>\r\n * );\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With cookie sync (Next.js optimization)\r\n * <InsforgeProvider\r\n * baseUrl={baseUrl}\r\n * syncTokenToCookie={async (token) => {\r\n * await fetch('/api/auth', {\r\n * method: 'POST',\r\n * body: JSON.stringify({ token })\r\n * });\r\n * return true;\r\n * }}\r\n * clearCookie={async () => {\r\n * await fetch('/api/auth', { method: 'DELETE' });\r\n * }}\r\n * >\r\n * {children}\r\n * </InsforgeProvider>\r\n * ```\r\n */\r\nexport function InsforgeProvider({\r\n children,\r\n baseUrl,\r\n onAuthChange,\r\n syncTokenToCookie,\r\n clearCookie,\r\n}: InsforgeProviderProps) {\r\n // Auth state\r\n const [user, setUser] = useState<InsforgeUser | null>(null);\r\n const [isLoaded, setIsLoaded] = useState(false);\r\n\r\n const refreshIntervalRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n // Initialize SDK client with lazy initialization - only runs once\r\n const [insforge] = useState(() => createClient({ baseUrl }));\r\n\r\n // Load auth state - returns explicit success/error status\r\n const loadAuthState = useCallback(async (): Promise<{\r\n success: boolean;\r\n error?: string;\r\n }> => {\r\n try {\r\n // Use SDK's getCurrentSession() to check for existing session\r\n const sessionResult = insforge.auth.getCurrentSession();\r\n const session = sessionResult.data?.session;\r\n const token = session?.accessToken || null;\r\n\r\n if (!token) {\r\n // No token, user is not authenticated\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n setIsLoaded(true);\r\n return { success: false, error: \"no_session\" };\r\n }\r\n\r\n const userResult = await insforge.auth.getCurrentUser();\r\n\r\n if (userResult.data) {\r\n // Token is valid, update user state with fresh data\r\n const profile = userResult.data.profile;\r\n const userData: InsforgeUser = {\r\n id: userResult.data.user.id,\r\n email: userResult.data.user.email,\r\n name: (profile?.nickname as string | undefined) || \"\",\r\n avatarUrl: (profile?.avatarUrl as string | undefined) || \"\",\r\n };\r\n\r\n setUser(userData);\r\n\r\n if (onAuthChange) {\r\n onAuthChange(userData);\r\n }\r\n setIsLoaded(true);\r\n return { success: true };\r\n } else {\r\n // Token invalid or expired\r\n await insforge.auth.signOut();\r\n\r\n // Clear cookie if function provided\r\n if (clearCookie) {\r\n try {\r\n await clearCookie();\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n }\r\n\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n setIsLoaded(true);\r\n return { success: false, error: \"invalid_token\" };\r\n }\r\n } catch (error) {\r\n // Token validation failed\r\n console.error(\"[InsforgeProvider] Token validation failed:\", error);\r\n\r\n await insforge.auth.signOut();\r\n\r\n // Clear cookie if function provided\r\n if (clearCookie) {\r\n try {\r\n await clearCookie();\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n }\r\n\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n setIsLoaded(true);\r\n\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error.message : \"authentication_failed\",\r\n };\r\n }\r\n }, [insforge, onAuthChange, syncTokenToCookie, clearCookie]);\r\n\r\n useEffect(() => {\r\n // Run loadAuthState only once on mount\r\n loadAuthState();\r\n\r\n return () => {\r\n if (refreshIntervalRef.current) {\r\n clearInterval(refreshIntervalRef.current);\r\n }\r\n };\r\n }, []); // Empty deps - run only on mount\r\n\r\n const getPublicAuthConfig = useCallback(async () => {\r\n try {\r\n const result = await insforge.auth.getPublicAuthConfig();\r\n if (result.data) {\r\n return result.data;\r\n } else {\r\n console.error('[InsforgeProvider] Failed to get public auth config:', result.error);\r\n return null;\r\n }\r\n } catch (error) {\r\n console.error(\r\n \"[InsforgeProvider] Failed to get public auth config:\",\r\n error\r\n );\r\n return null;\r\n }\r\n }, [insforge]);\r\n\r\n /**\r\n * Helper function to handle successful authentication\r\n */\r\n const handleAuthSuccess = useCallback(\r\n async (\r\n authToken: string,\r\n fallbackUser?: { id?: string; email?: string; name?: string }\r\n ) => {\r\n const userResult = await insforge.auth.getCurrentUser();\r\n\r\n if (userResult.data) {\r\n const profile = userResult.data.profile;\r\n const userData: InsforgeUser = {\r\n id: userResult.data.user.id,\r\n email: userResult.data.user.email,\r\n name: (profile?.nickname as string | undefined) || \"\",\r\n avatarUrl: (profile?.avatarUrl as string | undefined) || \"\",\r\n };\r\n\r\n setUser(userData);\r\n\r\n if (onAuthChange) {\r\n onAuthChange(userData);\r\n }\r\n\r\n // Try to sync token to cookie if function provided\r\n if (syncTokenToCookie) {\r\n try {\r\n await syncTokenToCookie(authToken);\r\n } catch (error) {\r\n // Cookie sync failed - that's okay\r\n }\r\n }\r\n } else if (fallbackUser) {\r\n // Fallback to basic user data if getCurrentUser fails\r\n const userData: InsforgeUser = {\r\n id: fallbackUser.id || \"\",\r\n email: fallbackUser.email || \"\",\r\n name: fallbackUser.name || \"\",\r\n avatarUrl: \"\",\r\n };\r\n\r\n setUser(userData);\r\n\r\n if (onAuthChange) {\r\n onAuthChange(userData);\r\n }\r\n }\r\n },\r\n [insforge, onAuthChange, syncTokenToCookie]\r\n );\r\n\r\n const signIn = useCallback(\r\n async (email: string, password: string) => {\r\n const sdkResult = await insforge.auth.signInWithPassword({\r\n email,\r\n password,\r\n });\r\n\r\n if (sdkResult.data) {\r\n await handleAuthSuccess(\r\n sdkResult.data.accessToken || \"\",\r\n sdkResult.data.user\r\n ? {\r\n id: sdkResult.data.user.id,\r\n email: sdkResult.data.user.email,\r\n name: sdkResult.data.user.name,\r\n }\r\n : undefined\r\n );\r\n return sdkResult.data;\r\n } else {\r\n const errorMessage =\r\n sdkResult.error?.message || \"Invalid email or password\";\r\n return { error: errorMessage };\r\n }\r\n },\r\n [insforge, handleAuthSuccess]\r\n );\r\n\r\n const signUp = useCallback(\r\n async (email: string, password: string) => {\r\n const sdkResult = await insforge.auth.signUp({ email, password });\r\n\r\n if (sdkResult.data) {\r\n await handleAuthSuccess(\r\n sdkResult.data.accessToken || \"\",\r\n sdkResult.data.user\r\n ? {\r\n id: sdkResult.data.user.id,\r\n email: sdkResult.data.user.email,\r\n name: sdkResult.data.user.name,\r\n }\r\n : undefined\r\n );\r\n return sdkResult.data;\r\n } else {\r\n const errorMessage = sdkResult.error?.message || \"Sign up failed\";\r\n return { error: errorMessage };\r\n }\r\n },\r\n [insforge, handleAuthSuccess]\r\n );\r\n\r\n const signOut = useCallback(async () => {\r\n await insforge.auth.signOut();\r\n\r\n // Clear cookie if function provided\r\n if (clearCookie) {\r\n try {\r\n await clearCookie();\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n }\r\n\r\n // Clear refresh interval if exists\r\n if (refreshIntervalRef.current) {\r\n clearInterval(refreshIntervalRef.current);\r\n }\r\n\r\n setUser(null);\r\n if (onAuthChange) {\r\n onAuthChange(null);\r\n }\r\n }, [insforge, onAuthChange, clearCookie]);\r\n\r\n const updateUser = useCallback(\r\n async (data: Partial<InsforgeUser>) => {\r\n if (!user) throw new Error(\"No user signed in\");\r\n\r\n const profileUpdate: Record<string, any> = {\r\n nickname: data.name,\r\n avatarUrl: data.avatarUrl,\r\n };\r\n\r\n const result = await insforge.auth.setProfile(profileUpdate);\r\n\r\n if (result.data) {\r\n const userResult = await insforge.auth.getCurrentUser();\r\n if (userResult.data) {\r\n const profile = userResult.data.profile;\r\n const updatedUser: InsforgeUser = {\r\n id: userResult.data.user.id,\r\n email: userResult.data.user.email,\r\n name: (profile?.nickname as string | undefined) || \"\",\r\n avatarUrl: (profile?.avatarUrl as string | undefined) || \"\",\r\n };\r\n setUser(updatedUser);\r\n if (onAuthChange) {\r\n onAuthChange(updatedUser);\r\n }\r\n }\r\n }\r\n },\r\n [user, onAuthChange, insforge]\r\n );\r\n\r\n const sendPasswordResetCode = useCallback(\r\n async (email: string) => {\r\n const sdkResult = await insforge.auth.sendPasswordResetCode({ email });\r\n return sdkResult.data;\r\n },\r\n [insforge]\r\n );\r\n\r\n const resetPassword = useCallback(\r\n async (token: string, newPassword: string) => {\r\n const sdkResult = await insforge.auth.resetPassword({\r\n newPassword,\r\n otp: token,\r\n });\r\n return sdkResult.data;\r\n },\r\n [insforge]\r\n );\r\n\r\n const verifyEmail = useCallback(\r\n async (token: string) => {\r\n const sdkResult = await insforge.auth.verifyEmail({ otp: token });\r\n return sdkResult.data;\r\n },\r\n [insforge]\r\n );\r\n\r\n return (\r\n <InsforgeContext.Provider\r\n value={{\r\n user,\r\n isLoaded,\r\n isSignedIn: !!user,\r\n setUser,\r\n signIn,\r\n signUp,\r\n signOut,\r\n updateUser,\r\n reloadAuth: loadAuthState,\r\n baseUrl,\r\n sendPasswordResetCode,\r\n resetPassword,\r\n verifyEmail,\r\n getPublicAuthConfig,\r\n }}\r\n >\r\n {children}\r\n </InsforgeContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * Hook to access Insforge context\r\n *\r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { user, isSignedIn, signOut } = useInsforge();\r\n *\r\n * if (!isSignedIn) return <SignIn />;\r\n *\r\n * return (\r\n * <div>\r\n * <p>Welcome {user.email}</p>\r\n * <button onClick={signOut}>Sign Out</button>\r\n * </div>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function useInsforge(): InsforgeContextValue {\r\n const context = useContext(InsforgeContext);\r\n if (!context) {\r\n throw new Error(\"useInsforge must be used within InsforgeProvider\");\r\n }\r\n return context;\r\n}\r\n","'use client';\r\n\r\nimport { useEffect, useRef, type ReactNode } from 'react';\r\nimport { useInsforge } from '../provider/InsforgeProvider';\r\n\r\nexport interface InsforgeCallbackProps {\r\n /**\r\n * Redirect destination after successful authentication\r\n */\r\n redirectTo?: string;\r\n \r\n /**\r\n * Callback fired on successful authentication\r\n */\r\n onSuccess?: () => void;\r\n \r\n /**\r\n * Callback fired on authentication error\r\n */\r\n onError?: (error: string) => void;\r\n \r\n /**\r\n * Custom loading component\r\n */\r\n loadingComponent?: ReactNode;\r\n \r\n /**\r\n * Custom redirect handler (default: window.location)\r\n */\r\n onRedirect?: (url: string) => void;\r\n}\r\n\r\n/**\r\n * InsforgeCallback - Handles OAuth and email/password authentication callbacks\r\n * \r\n * Place this component on your `/auth/callback` page.\r\n * \r\n * @example\r\n * ```tsx\r\n * // Minimal usage\r\n * export default function CallbackPage() {\r\n * return <InsforgeCallback />;\r\n * }\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // With Next.js router\r\n * import { useRouter } from 'next/navigation';\r\n * \r\n * export default function CallbackPage() {\r\n * const router = useRouter();\r\n * return (\r\n * <InsforgeCallback\r\n * redirectTo=\"/dashboard\"\r\n * onRedirect={(url) => router.push(url)}\r\n * />\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function InsforgeCallback({\r\n redirectTo,\r\n onSuccess,\r\n onError,\r\n loadingComponent,\r\n onRedirect,\r\n}: InsforgeCallbackProps) {\r\n const isProcessingRef = useRef(false);\r\n const { reloadAuth } = useInsforge();\r\n\r\n useEffect(() => {\r\n const processCallback = async () => {\r\n // Prevent double-processing\r\n if (isProcessingRef.current) return;\r\n isProcessingRef.current = true;\r\n\r\n // Get search params\r\n const searchParams = new URLSearchParams(window.location.search);\r\n\r\n // Check for error from backend\r\n const error = searchParams.get('error');\r\n if (error) {\r\n if (onError) {\r\n onError(error);\r\n } else {\r\n const errorUrl = '/?error=' + encodeURIComponent(error);\r\n if (onRedirect) {\r\n onRedirect(errorUrl);\r\n } else {\r\n window.location.href = errorUrl;\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Reload auth state\r\n const result = await reloadAuth();\r\n\r\n if (!result.success) {\r\n const errorMsg = result.error || 'authentication_failed';\r\n if (onError) {\r\n onError(errorMsg);\r\n } else {\r\n const errorUrl = '/?error=' + encodeURIComponent(errorMsg);\r\n if (onRedirect) {\r\n onRedirect(errorUrl);\r\n } else {\r\n window.location.href = errorUrl;\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Authentication successful!\r\n // Clean URL\r\n window.history.replaceState({}, '', window.location.pathname);\r\n\r\n // Fire success callback\r\n if (onSuccess) {\r\n onSuccess();\r\n }\r\n\r\n // Get destination and redirect\r\n const destination = \r\n redirectTo || \r\n sessionStorage.getItem('auth_destination') || \r\n sessionStorage.getItem('oauth_final_destination') || \r\n '/';\r\n \r\n sessionStorage.removeItem('auth_destination');\r\n sessionStorage.removeItem('oauth_final_destination');\r\n\r\n if (onRedirect) {\r\n onRedirect(destination);\r\n } else {\r\n window.location.href = destination;\r\n }\r\n };\r\n\r\n processCallback();\r\n }, []); // Empty deps - run once\r\n\r\n const defaultLoading = (\r\n <div className=\"flex items-center justify-center min-h-screen\">\r\n <div className=\"text-center\">\r\n <h2 className=\"text-2xl font-semibold mb-4\">Completing authentication...</h2>\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto\"></div>\r\n </div>\r\n </div>\r\n );\r\n\r\n return loadingComponent || defaultLoading;\r\n}\r\n\r\n","'use client';\r\n\r\nimport { useEffect } from 'react';\r\nimport type { RouteObject } from 'react-router-dom';\r\nimport { InsforgeCallback } from '../components/InsforgeCallback';\r\n\r\ninterface GetInsforgeRoutesConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n \r\n /**\r\n * Whether to use built-in auth (deployed Insforge Auth)\r\n * When true: redirects to baseUrl/auth/* pages\r\n * When false: no redirect routes are added (use your own components)\r\n * @default true\r\n */\r\n builtInAuth?: boolean;\r\n \r\n /**\r\n * Custom paths for auth routes\r\n * @default {\r\n * signIn: '/sign-in',\r\n * signUp: '/sign-up',\r\n * verifyEmail: '/verify-email',\r\n * forgotPassword: '/forgot-password',\r\n * resetPassword: '/reset-password',\r\n * callback: '/auth/callback'\r\n * }\r\n */\r\n paths?: {\r\n signIn?: string;\r\n signUp?: string;\r\n verifyEmail?: string;\r\n forgotPassword?: string;\r\n resetPassword?: string;\r\n callback?: string;\r\n };\r\n}\r\n\r\n/**\r\n * Helper component for redirecting to external auth\r\n */\r\nfunction RedirectToAuth({ baseUrl, path }: { baseUrl: string; path: string }) {\r\n useEffect(() => {\r\n const callbackUrl = `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(path, baseUrl);\r\n authUrl.searchParams.set('redirect', callbackUrl);\r\n window.location.replace(authUrl.toString());\r\n }, [baseUrl, path]);\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Generates Insforge authentication routes for React Router.\r\n * \r\n * Returns an array of RouteObjects that can be spread into your router configuration.\r\n * Supports all Insforge auth pages: sign-in, sign-up, verify-email, forgot-password, reset-password.\r\n * \r\n * @param config - Configuration for Insforge routes\r\n * @returns Array of RouteObject for React Router\r\n * \r\n * @example\r\n * ```tsx\r\n * import { createBrowserRouter } from 'react-router-dom';\r\n * import { getInsforgeRoutes } from '@insforge/react';\r\n * \r\n * const router = createBrowserRouter([\r\n * {\r\n * path: '/',\r\n * element: <Home />\r\n * },\r\n * // Add all Insforge auth routes (sign-in, sign-up, verify-email, etc.)\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true\r\n * }),\r\n * {\r\n * path: '/dashboard',\r\n * element: <Dashboard />\r\n * }\r\n * ]);\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Don't use built-in auth, use your own components instead\r\n * import { SignIn, SignUp } from '@insforge/react';\r\n * \r\n * const router = createBrowserRouter([\r\n * // Only add callback route\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: false\r\n * }),\r\n * // Your own auth components\r\n * {\r\n * path: '/sign-in',\r\n * element: <SignIn />\r\n * },\r\n * {\r\n * path: '/sign-up',\r\n * element: <SignUp />\r\n * }\r\n * ]);\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Custom paths\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true,\r\n * paths: {\r\n * signIn: '/login',\r\n * signUp: '/register',\r\n * callback: '/callback'\r\n * }\r\n * })\r\n * ```\r\n */\r\nexport function getInsforgeRoutes(config: GetInsforgeRoutesConfig): RouteObject[] {\r\n const {\r\n baseUrl,\r\n builtInAuth = true,\r\n paths = {},\r\n } = config;\r\n\r\n const {\r\n signIn = '/sign-in',\r\n signUp = '/sign-up',\r\n verifyEmail = '/verify-email',\r\n forgotPassword = '/forgot-password',\r\n resetPassword = '/reset-password',\r\n callback = '/auth/callback',\r\n } = paths;\r\n\r\n const routes: RouteObject[] = [\r\n // Always include callback route\r\n {\r\n path: callback,\r\n element: <InsforgeCallback />,\r\n },\r\n ];\r\n\r\n // Only add redirect routes if using built-in auth\r\n if (builtInAuth) {\r\n routes.push(\r\n {\r\n path: signIn,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-in\" />,\r\n },\r\n {\r\n path: signUp,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-up\" />,\r\n },\r\n {\r\n path: verifyEmail,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/verify-email\" />,\r\n },\r\n {\r\n path: forgotPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/forgot-password\" />,\r\n },\r\n {\r\n path: resetPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/reset-password\" />,\r\n }\r\n );\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n"]}
1
+ {"version":3,"sources":["../src/router/getInsforgeRoutes.tsx"],"names":[],"mappings":";;;AAyCA,SAAS,cAAA,CAAe,EAAE,OAAA,EAAS,IAAA,EAAK,EAAsC;AAC5E,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,WAAA,GAAc,CAAA,EAAG,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,cAAA,CAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AACrC,IAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,WAAW,CAAA;AAChD,IAAA,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,OAAA,CAAQ,QAAA,EAAU,CAAA;AAAA,EAC5C,CAAA,EAAG,CAAC,OAAA,EAAS,IAAI,CAAC,CAAA;AAElB,EAAA,OAAO,IAAA;AACT;AAwDO,SAAS,kBAAkB,MAAA,EAAgD;AAChF,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,WAAA,GAAc,IAAA;AAAA,IACd,QAAQ;AAAC,GACX,GAAI,MAAA;AAEJ,EAAA,MAAM;AAAA,IACJ,MAAA,GAAS,UAAA;AAAA,IACT,MAAA,GAAS,UAAA;AAAA,IACT,WAAA,GAAc,eAAA;AAAA,IACd,cAAA,GAAiB,kBAAA;AAAA,IACjB,aAAA,GAAgB;AAAA,GAClB,GAAI,KAAA;AAEJ,EAAA,MAAM,SAAwB,EAAC;AAG/B,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAA,CAAO,IAAA;AAAA,MACL;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,kBAAS,GAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,eAAA,EAAgB;AAAA,OAClE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,kBAAS,GAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,eAAA,EAAgB;AAAA,OAClE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,WAAA;AAAA,QACN,OAAA,kBAAS,GAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,oBAAA,EAAqB;AAAA,OACvE;AAAA,MACA;AAAA,QACE,IAAA,EAAM,cAAA;AAAA,QACN,OAAA,kBAAS,GAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,uBAAA,EAAwB;AAAA,OAC1E;AAAA,MACA;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,kBAAS,GAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAkB,MAAK,sBAAA,EAAuB;AAAA;AACzE,KACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT","file":"router.mjs","sourcesContent":["'use client';\r\n\r\nimport { useEffect } from 'react';\r\nimport type { RouteObject } from 'react-router-dom';\r\n\r\ninterface GetInsforgeRoutesConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n \r\n /**\r\n * Whether to use built-in auth (deployed Insforge Auth)\r\n * When true: redirects to baseUrl/auth/* pages\r\n * When false: no redirect routes are added (use your own components)\r\n * @default true\r\n */\r\n builtInAuth?: boolean;\r\n \r\n /**\r\n * Custom paths for auth redirect routes\r\n * @default {\r\n * signIn: '/sign-in',\r\n * signUp: '/sign-up',\r\n * verifyEmail: '/verify-email',\r\n * forgotPassword: '/forgot-password',\r\n * resetPassword: '/reset-password'\r\n * }\r\n */\r\n paths?: {\r\n signIn?: string;\r\n signUp?: string;\r\n verifyEmail?: string;\r\n forgotPassword?: string;\r\n resetPassword?: string;\r\n };\r\n}\r\n\r\n/**\r\n * Helper component for redirecting to external auth\r\n */\r\nfunction RedirectToAuth({ baseUrl, path }: { baseUrl: string; path: string }) {\r\n useEffect(() => {\r\n const callbackUrl = `${window.location.origin}/auth/callback`;\r\n const authUrl = new URL(path, baseUrl);\r\n authUrl.searchParams.set('redirect', callbackUrl);\r\n window.location.replace(authUrl.toString());\r\n }, [baseUrl, path]);\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Generates Insforge authentication redirect routes for React Router.\r\n * \r\n * Returns redirect routes for sign-in, sign-up, etc. that redirect to your deployed Insforge auth pages.\r\n * \r\n * ⚠️ **Important**: You must manually create the `/auth/callback` route in your router\r\n * to handle authentication callbacks. See documentation for details.\r\n * \r\n * @param config - Configuration for Insforge routes\r\n * @returns Array of RouteObject for React Router (redirect routes only)\r\n * \r\n * @example\r\n * ```tsx\r\n * import { createBrowserRouter } from 'react-router-dom';\r\n * import { getInsforgeRoutes } from '@insforge/react/router';\r\n * import { InsforgeCallback } from '@insforge/react';\r\n * \r\n * const router = createBrowserRouter([\r\n * {\r\n * path: '/',\r\n * element: <Layout />,\r\n * children: [\r\n * { index: true, element: <Home /> },\r\n * // ✅ Required: Manually create callback route\r\n * { path: 'auth/callback', element: <AuthCallback /> },\r\n * { path: 'dashboard', element: <Dashboard /> }\r\n * ]\r\n * },\r\n * // Add redirect routes (sign-in, sign-up, etc.)\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true\r\n * })\r\n * ]);\r\n * \r\n * // src/pages/AuthCallback.tsx\r\n * function AuthCallback() {\r\n * return <InsforgeCallback redirectTo=\"/dashboard\" />;\r\n * }\r\n * ```\r\n * \r\n * @example\r\n * ```tsx\r\n * // Custom paths for redirect routes\r\n * ...getInsforgeRoutes({\r\n * baseUrl: 'https://your-backend.com',\r\n * builtInAuth: true,\r\n * paths: {\r\n * signIn: '/login',\r\n * signUp: '/register'\r\n * }\r\n * })\r\n * ```\r\n */\r\nexport function getInsforgeRoutes(config: GetInsforgeRoutesConfig): RouteObject[] {\r\n const {\r\n baseUrl,\r\n builtInAuth = true,\r\n paths = {},\r\n } = config;\r\n\r\n const {\r\n signIn = '/sign-in',\r\n signUp = '/sign-up',\r\n verifyEmail = '/verify-email',\r\n forgotPassword = '/forgot-password',\r\n resetPassword = '/reset-password',\r\n } = paths;\r\n\r\n const routes: RouteObject[] = [];\r\n\r\n // Only add redirect routes if using built-in auth\r\n if (builtInAuth) {\r\n routes.push(\r\n {\r\n path: signIn,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-in\" />,\r\n },\r\n {\r\n path: signUp,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/sign-up\" />,\r\n },\r\n {\r\n path: verifyEmail,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/verify-email\" />,\r\n },\r\n {\r\n path: forgotPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/forgot-password\" />,\r\n },\r\n {\r\n path: resetPassword,\r\n element: <RedirectToAuth baseUrl={baseUrl} path=\"/auth/reset-password\" />,\r\n }\r\n );\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n"]}
package/dist/types.d.mts CHANGED
@@ -536,7 +536,6 @@ interface VerifyEmailStatusProps {
536
536
  * Props for the SignIn component
537
537
  */
538
538
  interface SignInProps {
539
- afterSignInUrl?: string;
540
539
  /** Hierarchical appearance configuration for deep customization */
541
540
  appearance?: SignInAppearance;
542
541
  title?: string;
@@ -559,13 +558,11 @@ interface SignInProps {
559
558
  name: string;
560
559
  }, accessToken: string) => void;
561
560
  onError?: (error: Error) => void;
562
- onRedirect?: (url: string) => void;
563
561
  }
564
562
  /**
565
563
  * Props for the SignUp component
566
564
  */
567
565
  interface SignUpProps {
568
- afterSignUpUrl?: string;
569
566
  /** Hierarchical appearance configuration for deep customization */
570
567
  appearance?: SignUpAppearance;
571
568
  title?: string;
@@ -586,7 +583,6 @@ interface SignUpProps {
586
583
  name: string;
587
584
  }, accessToken: string) => void;
588
585
  onError?: (error: Error) => void;
589
- onRedirect?: (url: string) => void;
590
586
  }
591
587
  /**
592
588
  * Props for Protect component