@insforge/react 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -6
- package/dist/atoms.cjs +14 -17
- package/dist/atoms.cjs.map +1 -1
- package/dist/atoms.d.cts +1 -0
- package/dist/atoms.d.ts +1 -0
- package/dist/atoms.js +13 -16
- package/dist/atoms.js.map +1 -1
- package/dist/components.cjs +23 -26
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +2 -1
- package/dist/components.d.ts +2 -1
- package/dist/components.js +22 -25
- package/dist/components.js.map +1 -1
- package/dist/forms.cjs +14 -17
- package/dist/forms.cjs.map +1 -1
- package/dist/forms.d.cts +1 -0
- package/dist/forms.d.ts +1 -0
- package/dist/forms.js +13 -16
- package/dist/forms.js.map +1 -1
- package/dist/hooks.cjs +15 -18
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +4 -5
- package/dist/hooks.d.ts +4 -5
- package/dist/hooks.js +14 -17
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +40 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -59
- package/dist/index.d.ts +7 -59
- package/dist/index.js +38 -44
- package/dist/index.js.map +1 -1
- package/dist/types.d.cts +3 -19
- package/dist/types.d.ts +3 -19
- package/package.json +98 -110
package/dist/hooks.cjs
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
require('react/jsx-runtime');
|
|
5
5
|
require('@insforge/sdk');
|
|
6
|
+
var react$1 = require('@insforge/shared/react');
|
|
6
7
|
|
|
7
8
|
// src/provider/InsforgeProvider.tsx
|
|
8
9
|
react.createContext(null);
|
|
9
|
-
var InsforgeContext = react.createContext(void 0);
|
|
10
|
-
InsforgeContext.displayName = "InsforgeContext";
|
|
11
10
|
function useInsforge() {
|
|
12
|
-
const context = react.useContext(InsforgeContext);
|
|
11
|
+
const context = react.useContext(react$1.InsforgeContext);
|
|
13
12
|
if (!context) {
|
|
14
13
|
return {
|
|
15
14
|
user: null,
|
|
@@ -17,20 +16,18 @@ function useInsforge() {
|
|
|
17
16
|
isSignedIn: false,
|
|
18
17
|
setUser: () => {
|
|
19
18
|
},
|
|
20
|
-
signIn:
|
|
21
|
-
signUp:
|
|
22
|
-
signOut:
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
getPublicAuthConfig: async () => null,
|
|
19
|
+
signIn: () => Promise.resolve({ error: "SSR mode" }),
|
|
20
|
+
signUp: () => Promise.resolve({ error: "SSR mode" }),
|
|
21
|
+
signOut: () => Promise.resolve(),
|
|
22
|
+
updateUser: () => Promise.resolve({ error: "SSR mode" }),
|
|
23
|
+
reloadAuth: () => Promise.resolve({ success: false, error: "SSR mode" }),
|
|
24
|
+
sendVerificationEmail: () => Promise.resolve(null),
|
|
25
|
+
sendResetPasswordEmail: () => Promise.resolve(null),
|
|
26
|
+
resetPassword: () => Promise.resolve(null),
|
|
27
|
+
verifyEmail: () => Promise.resolve(null),
|
|
28
|
+
exchangeResetPasswordToken: () => Promise.resolve({ error: { message: "SSR mode" } }),
|
|
29
|
+
loginWithOAuth: () => Promise.resolve(),
|
|
30
|
+
getPublicAuthConfig: () => Promise.resolve(null),
|
|
34
31
|
baseUrl: "",
|
|
35
32
|
afterSignInUrl: "/"
|
|
36
33
|
};
|
|
@@ -64,7 +61,7 @@ function usePublicAuthConfig() {
|
|
|
64
61
|
}
|
|
65
62
|
setIsLoaded(true);
|
|
66
63
|
}
|
|
67
|
-
fetchConfig();
|
|
64
|
+
void fetchConfig();
|
|
68
65
|
}, [getPublicAuthConfig]);
|
|
69
66
|
return { authConfig, isLoaded };
|
|
70
67
|
}
|
package/dist/hooks.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/navigation/NavigationContext.tsx","../src/contexts/InsforgeContext.tsx","../src/provider/InsforgeProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useUser.ts","../src/hooks/usePublicAuthConfig.ts"],"names":["createContext","useContext","useState","useEffect"],"mappings":";;;;;;;AAG0BA,oBAAwC,IAAI;ACsD/D,IAAM,eAAA,GAAkBA,oBAAgD,MAAS,CAAA;AACxF,eAAA,CAAgB,WAAA,GAAc,iBAAA;AC0GvB,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAUC,iBAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA;AAAA,MACN,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,KAAA;AAAA,MACZ,SAAS,MAAM;AAAA,MAAC,CAAA;AAAA,MAChB,MAAA,EAAQ,aAAa,EAAE,KAAA,EAAO,UAAA,EAAW,CAAA;AAAA,MACzC,MAAA,EAAQ,aAAa,EAAE,KAAA,EAAO,UAAA,EAAW,CAAA;AAAA,MACzC,SAAS,YAAY;AAAA,MAAC,CAAA;AAAA,MACtB,UAAA,EAAY,aAAa,EAAE,KAAA,EAAO,UAAA,EAAW,CAAA;AAAA,MAC7C,YAAY,aAAa,EAAE,OAAA,EAAS,KAAA,EAAO,OAAO,UAAA,EAAW,CAAA;AAAA,MAC7D,uBAAuB,YAAY,IAAA;AAAA,MACnC,wBAAwB,YAAY,IAAA;AAAA,MACpC,eAAe,YAAY,IAAA;AAAA,MAC3B,aAAa,YAAY,IAAA;AAAA,MACzB,4BAA4B,aAAa,EAAE,OAAO,EAAE,OAAA,EAAS,YAAW,EAAE,CAAA;AAAA,MAC1E,gBAAgB,YAAY;AAAA,MAAC,CAAA;AAAA,MAC7B,qBAAqB,YAAY,IAAA;AAAA,MACjC,OAAA,EAAS,EAAA;AAAA,MACT,cAAA,EAAgB;AAAA,KAClB;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;;;AC3JO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAS,QAAA,EAAU,UAAA,KAAe,WAAA,EAAY;AACtE,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,UAAU,UAAA,EAAW;AACzD;;;ACDO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,OAAA,KAAY,WAAA,EAAY;AAC5D,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,OAAA,EAAQ;AAC/C;ACLO,SAAS,mBAAA,GAGd;AACA,EAAA,MAAM,EAAE,mBAAA,EAAoB,GAAI,WAAA,EAAY;AAC5C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIC,eAA6C,IAAI,CAAA;AACrF,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,eAAS,KAAK,CAAA;AAE9C,EAAAC,gBAAU,MAAM;AACd,IAAA,eAAe,WAAA,GAAc;AAC3B,MAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,EAAoB;AACzC,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,aAAA,CAAc,MAAM,CAAA;AAAA,MACtB,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,MAAM,wDAAwD,CAAA;AACtE,QAAA,aAAA,CAAc,IAAI,CAAA;AAAA,MACpB;AACA,MAAA,WAAA,CAAY,IAAI,CAAA;AAAA,IAClB;AAEA,IAAA,WAAA,EAAY;AAAA,EACd,CAAA,EAAG,CAAC,mBAAmB,CAAC,CAAA;AAExB,EAAA,OAAO,EAAE,YAAY,QAAA,EAAS;AAChC","file":"hooks.cjs","sourcesContent":["import { createContext, useContext, ReactNode } from 'react';\nimport type { NavigationAdapter } from './types';\n\nconst NavigationContext = createContext<NavigationAdapter | null>(null);\n\nexport interface NavigationProviderProps {\n adapter: NavigationAdapter;\n children: ReactNode;\n}\n\n/**\n * Navigation Provider\n * Injects navigation adapter into the component tree\n */\nexport function NavigationProvider({ adapter, children }: NavigationProviderProps) {\n return <NavigationContext.Provider value={adapter}>{children}</NavigationContext.Provider>;\n}\n\n/**\n * Hook to access navigation adapter\n * @throws Error if used outside NavigationProvider\n */\nexport function useNavigationAdapter(): NavigationAdapter {\n const adapter = useContext(NavigationContext);\n\n if (!adapter) {\n return {\n useSearchParams: () => new URLSearchParams(),\n Link: ({ href, children }) => <a href={href}>{children}</a>,\n };\n }\n\n return adapter;\n}\n","'use client';\n\nimport { createContext } from 'react';\nimport type { UserSchema } from '@insforge/sdk';\nimport type { InsforgeUser, OAuthProvider } from '../types';\nimport type {\n CreateSessionResponse,\n CreateUserResponse,\n GetPublicAuthConfigResponse,\n ResetPasswordResponse,\n} from '@insforge/shared-schemas';\n\nexport interface InsforgeContextValue {\n // Auth state\n user: InsforgeUser | null;\n isLoaded: boolean;\n isSignedIn: boolean;\n\n // Auth methods\n setUser: (user: InsforgeUser | null) => void;\n signIn: (\n email: string,\n password: string\n ) => Promise<CreateSessionResponse | { error: string; statusCode?: number; errorCode?: string }>;\n signUp: (\n email: string,\n password: string\n ) => Promise<CreateUserResponse | { error: string; statusCode?: number; errorCode?: string }>;\n signOut: () => Promise<void>;\n updateUser: (data: Partial<InsforgeUser>) => Promise<{ error: string } | null>;\n reloadAuth: () => Promise<{ success: boolean; error?: string }>;\n\n // Email verification methods\n sendVerificationEmail: (email: string) => Promise<{ success: boolean; message: string } | null>;\n sendResetPasswordEmail: (email: string) => Promise<{ success: boolean; message: string } | null>;\n resetPassword: (token: string, newPassword: string) => Promise<ResetPasswordResponse | null>;\n verifyEmail: (\n otp: string,\n email?: string\n ) => Promise<{\n accessToken: string;\n user?: UserSchema;\n redirectTo?: string;\n error?: { message: string };\n } | null>;\n exchangeResetPasswordToken: (\n email: string,\n code: string\n ) => Promise<{ token: string; expiresAt?: string } | { error: { message: string } }>;\n loginWithOAuth: (provider: OAuthProvider, redirectTo: string) => Promise<void>;\n // Public auth config\n getPublicAuthConfig: () => Promise<GetPublicAuthConfigResponse | null>;\n // Base config\n baseUrl: string;\n afterSignInUrl: string;\n}\n\nexport const InsforgeContext = createContext<InsforgeContextValue | undefined>(undefined);\nInsforgeContext.displayName = 'InsforgeContext';\n","import { useContext, useEffect, useState, useMemo, type ReactNode } from 'react';\nimport type { InsforgeUser, OAuthProvider } from '../types';\nimport { NavigationProvider, BrowserNavigationAdapter } from '../navigation';\nimport { InsforgeManager, type InsforgeManagerState } from '../core/InsforgeManager';\nimport { InsforgeContext, type InsforgeContextValue } from '../contexts/InsforgeContext';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n /**\n * URL to redirect to after successful sign in (when token is detected in URL)\n * @default '/'\n */\n afterSignInUrl?: string;\n onAuthChange?: (user: InsforgeUser | null) => void;\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n/**\n * Unified Insforge Provider - manages authentication state and configuration\n *\n * Uses singleton InsforgeManager to manage state across packages.\n * Context only subscribes to Manager and triggers React re-renders.\n *\n * @example\n * ```tsx\n * // Basic usage (React/Vite)\n * import { InsforgeProvider } from '@insforge/react';\n *\n * export default function App() {\n * return (\n * <InsforgeProvider\n * baseUrl={import.meta.env.VITE_INSFORGE_BASE_URL}\n * >\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With cookie sync (Next.js optimization)\n * <InsforgeProvider\n * baseUrl={baseUrl}\n * onSignIn={async (authToken) => {\n * await signIn(authToken);\n * }}\n * onSignOut={async () => {\n * await signOut();\n * }}\n * >\n * {children}\n * </InsforgeProvider>\n * ```\n */\nexport function InsforgeProviderCore({\n children,\n baseUrl,\n afterSignInUrl = '/',\n onAuthChange,\n onSignIn,\n onSignOut,\n}: InsforgeProviderProps) {\n // Get singleton Manager instance\n const manager = useMemo(\n () =>\n InsforgeManager.getInstance({\n baseUrl,\n afterSignInUrl,\n onAuthChange,\n onSignIn,\n onSignOut,\n }),\n [baseUrl, afterSignInUrl, onAuthChange, onSignIn, onSignOut]\n );\n\n // Subscribe to Manager state\n const [state, setState] = useState<InsforgeManagerState>(() => manager.getState());\n\n useEffect(() => {\n const unsubscribe = manager.subscribe((newState) => {\n setState(newState);\n });\n\n manager.initialize();\n\n return unsubscribe;\n }, [manager]);\n\n // Handle OAuth callback\n useEffect(() => {\n if (typeof window !== 'undefined') {\n manager.handleOAuthCallback(state.isLoaded, state.user);\n }\n }, [manager, state.isLoaded, state.user]);\n\n // Create stable method references that delegate to manager\n const contextValue = useMemo<InsforgeContextValue>(\n () => ({\n // State from Manager\n user: state.user,\n isLoaded: state.isLoaded,\n isSignedIn: state.isSignedIn,\n\n // Methods delegated to Manager\n setUser: (user: InsforgeUser | null) => manager.setUser(user),\n signIn: (email: string, password: string) => manager.signIn(email, password),\n signUp: (email: string, password: string) => manager.signUp(email, password),\n signOut: () => manager.signOut(),\n updateUser: (data: Partial<InsforgeUser>) => manager.updateUser(data),\n reloadAuth: () => manager.reloadAuth(),\n sendVerificationEmail: (email: string) => manager.sendVerificationEmail(email),\n sendResetPasswordEmail: (email: string) => manager.sendResetPasswordEmail(email),\n resetPassword: (token: string, newPassword: string) =>\n manager.resetPassword(token, newPassword),\n verifyEmail: (otp: string, email?: string) => manager.verifyEmail(otp, email),\n exchangeResetPasswordToken: (email: string, code: string) =>\n manager.exchangeResetPasswordToken(email, code),\n loginWithOAuth: (provider: OAuthProvider, redirectTo: string) =>\n manager.loginWithOAuth(provider, redirectTo),\n getPublicAuthConfig: () => manager.getPublicAuthConfig(),\n\n // Config\n baseUrl: manager.getConfig().baseUrl,\n afterSignInUrl: manager.getConfig().afterSignInUrl || '/',\n }),\n [state, manager]\n );\n\n return <InsforgeContext.Provider value={contextValue}>{children}</InsforgeContext.Provider>;\n}\n\nexport function InsforgeProvider(props: InsforgeProviderProps) {\n return (\n <NavigationProvider adapter={BrowserNavigationAdapter}>\n <InsforgeProviderCore {...props} />\n </NavigationProvider>\n );\n}\n\n/**\n * Hook to access Insforge context\n *\n * Works seamlessly across packages thanks to singleton Manager.\n * Context instance is guaranteed to be consistent.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useInsforge(): InsforgeContextValue {\n const context = useContext(InsforgeContext);\n\n if (!context) {\n return {\n user: null,\n isLoaded: false,\n isSignedIn: false,\n setUser: () => {},\n signIn: async () => ({ error: 'SSR mode' }),\n signUp: async () => ({ error: 'SSR mode' }),\n signOut: async () => {},\n updateUser: async () => ({ error: 'SSR mode' }),\n reloadAuth: async () => ({ success: false, error: 'SSR mode' }),\n sendVerificationEmail: async () => null,\n sendResetPasswordEmail: async () => null,\n resetPassword: async () => null,\n verifyEmail: async () => null,\n exchangeResetPasswordToken: async () => ({ error: { message: 'SSR mode' } }),\n loginWithOAuth: async () => {},\n getPublicAuthConfig: async () => null,\n baseUrl: '',\n afterSignInUrl: '/',\n };\n }\n\n return context;\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access authentication methods\n *\n * @returns Object containing:\n * - `signIn`: Function to sign in with email and password\n * - `signUp`: Function to sign up with email and password\n * - `signOut`: Function to sign out the current user\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `isSignedIn`: Boolean indicating if user is currently signed in\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const { signIn, signUp, signOut, isLoaded, isSignedIn } = useAuth();\n *\n * async function handleLogin(email: string, password: string) {\n * try {\n * await signIn(email, password);\n * // User is now signed in\n * } catch (error) {\n * console.error('Sign in failed:', error);\n * }\n * }\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <form onSubmit={(e) => { e.preventDefault(); handleLogin(email, password); }}>\n * {/* form fields *\\/}\n * </form>\n * );\n * }\n * ```\n */\nexport function useAuth() {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access current user data\n *\n * @returns Object containing:\n * - `user`: Current user object (InsforgeUser | null)\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `updateUser`: Function to update user profile data (returns { error: string } | null)\n * - `setUser`: Internal function to manually set user state\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { user, isLoaded, updateUser } = useUser();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n * if (!user) return <div>Not signed in</div>;\n *\n * async function handleUpdate(name: string) {\n * const result = await updateUser({ name });\n * if (result?.error) {\n * console.error(result.error);\n * } else {\n * console.log('User updated successfully');\n * }\n * }\n *\n * return (\n * <div>\n * <p>Email: {user.email}</p>\n * {user.name && <p>Name: {user.name}</p>}\n * {user.avatarUrl && <img src={user.avatarUrl} alt=\"Avatar\" />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser() {\n const { user, isLoaded, updateUser, setUser } = useInsforge();\n return { user, isLoaded, updateUser, setUser };\n}\n","import { useState, useEffect } from 'react';\nimport type { GetPublicAuthConfigResponse } from '@insforge/shared-schemas';\nimport { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to get all public authentication configuration (OAuth + Email) from Insforge backend\n *\n * **IMPORTANT: This hook should ONLY be used in SignIn and SignUp components.**\n *\n * This hook lazily fetches all public authentication configuration from the backend\n * only when the component mounts. Using it in other components will cause unnecessary\n * API calls on every page load.\n *\n * @returns Object containing OAuth providers, email auth config, and loading state\n * - `authConfig`: Email authentication configuration object with password rules\n * - `isLoaded`: Boolean indicating if the config has been fetched\n *\n * @example\n * ```tsx\n * // ✅ Correct usage - only in SignIn/SignUp components\n * function SignUp() {\n * const { authConfig, isLoaded } = usePublicAuthConfig();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <div>\n * <p>OAuth providers: {authConfig?.oauthProviders.length}</p>\n * <p>Password min length: {authConfig?.passwordMinLength}</p>\n * </div>\n * );\n * }\n * ```\n *\n * @requires Must be used within InsforgeProvider\n */\nexport function usePublicAuthConfig(): {\n authConfig: GetPublicAuthConfigResponse | null;\n isLoaded: boolean;\n} {\n const { getPublicAuthConfig } = useInsforge();\n const [authConfig, setAuthConfig] = useState<GetPublicAuthConfigResponse | null>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n\n useEffect(() => {\n async function fetchConfig() {\n const result = await getPublicAuthConfig();\n if (result) {\n setAuthConfig(result);\n } else {\n console.error('[usePublicAuthConfig] Failed to get public auth config');\n setAuthConfig(null);\n }\n setIsLoaded(true);\n }\n\n fetchConfig();\n }, [getPublicAuthConfig]);\n\n return { authConfig, isLoaded };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/navigation/NavigationContext.tsx","../src/provider/InsforgeProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useUser.ts","../src/hooks/usePublicAuthConfig.ts"],"names":["createContext","useContext","InsforgeContext","useState","useEffect"],"mappings":"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","file":"hooks.cjs","sourcesContent":["import { createContext, useContext, ReactNode } from 'react';\nimport type { NavigationAdapter } from './types';\n\nconst NavigationContext = createContext<NavigationAdapter | null>(null);\n\nexport interface NavigationProviderProps {\n adapter: NavigationAdapter;\n children: ReactNode;\n}\n\n/**\n * Navigation Provider\n * Injects navigation adapter into the component tree\n */\nexport function NavigationProvider({ adapter, children }: NavigationProviderProps) {\n return <NavigationContext.Provider value={adapter}>{children}</NavigationContext.Provider>;\n}\n\n/**\n * Hook to access navigation adapter\n * @throws Error if used outside NavigationProvider\n */\nexport function useNavigationAdapter(): NavigationAdapter {\n const adapter = useContext(NavigationContext);\n\n if (!adapter) {\n return {\n useSearchParams: () => new URLSearchParams(),\n Link: ({ href, children }) => <a href={href}>{children}</a>,\n };\n }\n\n return adapter;\n}\n","import { useContext, useEffect, useState, useMemo, type ReactNode } from 'react';\nimport type { InsforgeUser, OAuthProvider } from '../types';\nimport { NavigationProvider, BrowserNavigationAdapter } from '../navigation';\nimport { InsforgeManager, type InsforgeManagerState } from '../core/InsforgeManager';\nimport { InsforgeContext, type InsforgeContextValue } from '../contexts';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n /**\n * URL to redirect to after successful sign in (when token is detected in URL)\n * @default '/'\n */\n afterSignInUrl?: string;\n onAuthChange?: (user: InsforgeUser | null) => void;\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n/**\n * Unified Insforge Provider - manages authentication state and configuration\n *\n * Uses singleton InsforgeManager to manage state across packages.\n * Context only subscribes to Manager and triggers React re-renders.\n *\n * @example\n * ```tsx\n * // Basic usage (React/Vite)\n * import { InsforgeProvider } from '@insforge/react';\n *\n * export default function App() {\n * return (\n * <InsforgeProvider\n * baseUrl={import.meta.env.VITE_INSFORGE_BASE_URL}\n * >\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With cookie sync (Next.js optimization)\n * <InsforgeProvider\n * baseUrl={baseUrl}\n * onSignIn={async (authToken) => {\n * await signIn(authToken);\n * }}\n * onSignOut={async () => {\n * await signOut();\n * }}\n * >\n * {children}\n * </InsforgeProvider>\n * ```\n */\nexport function InsforgeProviderCore({\n children,\n baseUrl,\n afterSignInUrl = '/',\n onAuthChange,\n onSignIn,\n onSignOut,\n}: InsforgeProviderProps) {\n // Get singleton Manager instance\n const manager = useMemo(\n () =>\n InsforgeManager.getInstance({\n baseUrl,\n afterSignInUrl,\n onAuthChange,\n onSignIn,\n onSignOut,\n }),\n [baseUrl, afterSignInUrl, onAuthChange, onSignIn, onSignOut]\n );\n\n // Subscribe to Manager state\n const [state, setState] = useState<InsforgeManagerState>(() => manager.getState());\n\n useEffect(() => {\n const unsubscribe = manager.subscribe((newState) => {\n setState(newState);\n });\n\n void manager.initialize();\n\n return unsubscribe;\n }, [manager]);\n\n // Handle OAuth callback\n useEffect(() => {\n if (typeof window !== 'undefined') {\n manager.handleOAuthCallback(state.isLoaded, state.user);\n }\n }, [manager, state.isLoaded, state.user]);\n\n // Create stable method references that delegate to manager\n const contextValue = useMemo<InsforgeContextValue>(\n () => ({\n // State from Manager\n user: state.user,\n isLoaded: state.isLoaded,\n isSignedIn: state.isSignedIn,\n\n // Methods delegated to Manager\n setUser: (user: InsforgeUser | null) => manager.setUser(user),\n signIn: (email: string, password: string) => manager.signIn(email, password),\n signUp: (email: string, password: string) => manager.signUp(email, password),\n signOut: () => manager.signOut(),\n updateUser: (data: Partial<InsforgeUser>) => manager.updateUser(data),\n reloadAuth: () => manager.reloadAuth(),\n sendVerificationEmail: (email: string) => manager.sendVerificationEmail(email),\n sendResetPasswordEmail: (email: string) => manager.sendResetPasswordEmail(email),\n resetPassword: (token: string, newPassword: string) =>\n manager.resetPassword(token, newPassword),\n verifyEmail: (otp: string, email?: string) => manager.verifyEmail(otp, email),\n exchangeResetPasswordToken: (email: string, code: string) =>\n manager.exchangeResetPasswordToken(email, code),\n loginWithOAuth: (provider: OAuthProvider, redirectTo: string) =>\n manager.loginWithOAuth(provider, redirectTo),\n getPublicAuthConfig: () => manager.getPublicAuthConfig(),\n\n // Config\n baseUrl: manager.getConfig().baseUrl,\n afterSignInUrl: manager.getConfig().afterSignInUrl || '/',\n }),\n [state, manager]\n );\n\n return <InsforgeContext.Provider value={contextValue}>{children}</InsforgeContext.Provider>;\n}\n\nexport function InsforgeProvider(props: InsforgeProviderProps) {\n return (\n <NavigationProvider adapter={BrowserNavigationAdapter}>\n <InsforgeProviderCore {...props} />\n </NavigationProvider>\n );\n}\n\n/**\n * Hook to access Insforge context\n *\n * Works seamlessly across packages thanks to singleton Manager.\n * Context instance is guaranteed to be consistent.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useInsforge(): InsforgeContextValue {\n const context = useContext(InsforgeContext);\n\n if (!context) {\n return {\n user: null,\n isLoaded: false,\n isSignedIn: false,\n setUser: () => {},\n signIn: () => Promise.resolve({ error: 'SSR mode' }),\n signUp: () => Promise.resolve({ error: 'SSR mode' }),\n signOut: () => Promise.resolve(),\n updateUser: () => Promise.resolve({ error: 'SSR mode' }),\n reloadAuth: () => Promise.resolve({ success: false, error: 'SSR mode' }),\n sendVerificationEmail: () => Promise.resolve(null),\n sendResetPasswordEmail: () => Promise.resolve(null),\n resetPassword: () => Promise.resolve(null),\n verifyEmail: () => Promise.resolve(null),\n exchangeResetPasswordToken: () => Promise.resolve({ error: { message: 'SSR mode' } }),\n loginWithOAuth: () => Promise.resolve(),\n getPublicAuthConfig: () => Promise.resolve(null),\n baseUrl: '',\n afterSignInUrl: '/',\n };\n }\n\n return context;\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access authentication methods\n *\n * @returns Object containing:\n * - `signIn`: Function to sign in with email and password\n * - `signUp`: Function to sign up with email and password\n * - `signOut`: Function to sign out the current user\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `isSignedIn`: Boolean indicating if user is currently signed in\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const { signIn, signUp, signOut, isLoaded, isSignedIn } = useAuth();\n *\n * async function handleLogin(email: string, password: string) {\n * try {\n * await signIn(email, password);\n * // User is now signed in\n * } catch (error) {\n * console.error('Sign in failed:', error);\n * }\n * }\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <form onSubmit={(e) => { e.preventDefault(); handleLogin(email, password); }}>\n * {/* form fields *\\/}\n * </form>\n * );\n * }\n * ```\n */\nexport function useAuth() {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access current user data\n *\n * @returns Object containing:\n * - `user`: Current user object (InsforgeUser | null)\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `updateUser`: Function to update user profile data (returns { error: string } | null)\n * - `setUser`: Internal function to manually set user state\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { user, isLoaded, updateUser } = useUser();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n * if (!user) return <div>Not signed in</div>;\n *\n * async function handleUpdate(name: string) {\n * const result = await updateUser({ name });\n * if (result?.error) {\n * console.error(result.error);\n * } else {\n * console.log('User updated successfully');\n * }\n * }\n *\n * return (\n * <div>\n * <p>Email: {user.email}</p>\n * {user.name && <p>Name: {user.name}</p>}\n * {user.avatarUrl && <img src={user.avatarUrl} alt=\"Avatar\" />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser() {\n const { user, isLoaded, updateUser, setUser } = useInsforge();\n return { user, isLoaded, updateUser, setUser };\n}\n","import { useState, useEffect } from 'react';\nimport type { GetPublicAuthConfigResponse } from '@insforge/shared-schemas';\nimport { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to get all public authentication configuration (OAuth + Email) from Insforge backend\n *\n * **IMPORTANT: This hook should ONLY be used in SignIn and SignUp components.**\n *\n * This hook lazily fetches all public authentication configuration from the backend\n * only when the component mounts. Using it in other components will cause unnecessary\n * API calls on every page load.\n *\n * @returns Object containing OAuth providers, email auth config, and loading state\n * - `authConfig`: Email authentication configuration object with password rules\n * - `isLoaded`: Boolean indicating if the config has been fetched\n *\n * @example\n * ```tsx\n * // ✅ Correct usage - only in SignIn/SignUp components\n * function SignUp() {\n * const { authConfig, isLoaded } = usePublicAuthConfig();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <div>\n * <p>OAuth providers: {authConfig?.oauthProviders.length}</p>\n * <p>Password min length: {authConfig?.passwordMinLength}</p>\n * </div>\n * );\n * }\n * ```\n *\n * @requires Must be used within InsforgeProvider\n */\nexport function usePublicAuthConfig(): {\n authConfig: GetPublicAuthConfigResponse | null;\n isLoaded: boolean;\n} {\n const { getPublicAuthConfig } = useInsforge();\n const [authConfig, setAuthConfig] = useState<GetPublicAuthConfigResponse | null>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n\n useEffect(() => {\n async function fetchConfig() {\n const result = await getPublicAuthConfig();\n if (result) {\n setAuthConfig(result);\n } else {\n console.error('[usePublicAuthConfig] Failed to get public auth config');\n setAuthConfig(null);\n }\n setIsLoaded(true);\n }\n\n void fetchConfig();\n }, [getPublicAuthConfig]);\n\n return { authConfig, isLoaded };\n}\n"]}
|
package/dist/hooks.d.cts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as _insforge_shared_schemas from '@insforge/shared-schemas';
|
|
2
2
|
import { GetPublicAuthConfigResponse } from '@insforge/shared-schemas';
|
|
3
|
-
import
|
|
4
|
-
import 'react';
|
|
3
|
+
import * as _insforge_shared from '@insforge/shared';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Hook to access authentication methods
|
|
@@ -90,12 +89,12 @@ declare function useAuth(): {
|
|
|
90
89
|
* ```
|
|
91
90
|
*/
|
|
92
91
|
declare function useUser(): {
|
|
93
|
-
user: InsforgeUser | null;
|
|
92
|
+
user: _insforge_shared.InsforgeUser | null;
|
|
94
93
|
isLoaded: boolean;
|
|
95
|
-
updateUser: (data: Partial<InsforgeUser>) => Promise<{
|
|
94
|
+
updateUser: (data: Partial<_insforge_shared.InsforgeUser>) => Promise<{
|
|
96
95
|
error: string;
|
|
97
96
|
} | null>;
|
|
98
|
-
setUser: (user: InsforgeUser | null) => void;
|
|
97
|
+
setUser: (user: _insforge_shared.InsforgeUser | null) => void;
|
|
99
98
|
};
|
|
100
99
|
|
|
101
100
|
/**
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as _insforge_shared_schemas from '@insforge/shared-schemas';
|
|
2
2
|
import { GetPublicAuthConfigResponse } from '@insforge/shared-schemas';
|
|
3
|
-
import
|
|
4
|
-
import 'react';
|
|
3
|
+
import * as _insforge_shared from '@insforge/shared';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Hook to access authentication methods
|
|
@@ -90,12 +89,12 @@ declare function useAuth(): {
|
|
|
90
89
|
* ```
|
|
91
90
|
*/
|
|
92
91
|
declare function useUser(): {
|
|
93
|
-
user: InsforgeUser | null;
|
|
92
|
+
user: _insforge_shared.InsforgeUser | null;
|
|
94
93
|
isLoaded: boolean;
|
|
95
|
-
updateUser: (data: Partial<InsforgeUser>) => Promise<{
|
|
94
|
+
updateUser: (data: Partial<_insforge_shared.InsforgeUser>) => Promise<{
|
|
96
95
|
error: string;
|
|
97
96
|
} | null>;
|
|
98
|
-
setUser: (user: InsforgeUser | null) => void;
|
|
97
|
+
setUser: (user: _insforge_shared.InsforgeUser | null) => void;
|
|
99
98
|
};
|
|
100
99
|
|
|
101
100
|
/**
|
package/dist/hooks.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { createContext, useState, useEffect, useContext } from 'react';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import '@insforge/sdk';
|
|
4
|
+
import { InsforgeContext } from '@insforge/shared/react';
|
|
4
5
|
|
|
5
6
|
// src/provider/InsforgeProvider.tsx
|
|
6
7
|
createContext(null);
|
|
7
|
-
var InsforgeContext = createContext(void 0);
|
|
8
|
-
InsforgeContext.displayName = "InsforgeContext";
|
|
9
8
|
function useInsforge() {
|
|
10
9
|
const context = useContext(InsforgeContext);
|
|
11
10
|
if (!context) {
|
|
@@ -15,20 +14,18 @@ function useInsforge() {
|
|
|
15
14
|
isSignedIn: false,
|
|
16
15
|
setUser: () => {
|
|
17
16
|
},
|
|
18
|
-
signIn:
|
|
19
|
-
signUp:
|
|
20
|
-
signOut:
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
-
getPublicAuthConfig: async () => null,
|
|
17
|
+
signIn: () => Promise.resolve({ error: "SSR mode" }),
|
|
18
|
+
signUp: () => Promise.resolve({ error: "SSR mode" }),
|
|
19
|
+
signOut: () => Promise.resolve(),
|
|
20
|
+
updateUser: () => Promise.resolve({ error: "SSR mode" }),
|
|
21
|
+
reloadAuth: () => Promise.resolve({ success: false, error: "SSR mode" }),
|
|
22
|
+
sendVerificationEmail: () => Promise.resolve(null),
|
|
23
|
+
sendResetPasswordEmail: () => Promise.resolve(null),
|
|
24
|
+
resetPassword: () => Promise.resolve(null),
|
|
25
|
+
verifyEmail: () => Promise.resolve(null),
|
|
26
|
+
exchangeResetPasswordToken: () => Promise.resolve({ error: { message: "SSR mode" } }),
|
|
27
|
+
loginWithOAuth: () => Promise.resolve(),
|
|
28
|
+
getPublicAuthConfig: () => Promise.resolve(null),
|
|
32
29
|
baseUrl: "",
|
|
33
30
|
afterSignInUrl: "/"
|
|
34
31
|
};
|
|
@@ -62,7 +59,7 @@ function usePublicAuthConfig() {
|
|
|
62
59
|
}
|
|
63
60
|
setIsLoaded(true);
|
|
64
61
|
}
|
|
65
|
-
fetchConfig();
|
|
62
|
+
void fetchConfig();
|
|
66
63
|
}, [getPublicAuthConfig]);
|
|
67
64
|
return { authConfig, isLoaded };
|
|
68
65
|
}
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/navigation/NavigationContext.tsx","../src/contexts/InsforgeContext.tsx","../src/provider/InsforgeProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useUser.ts","../src/hooks/usePublicAuthConfig.ts"],"names":["createContext","useContext","useState","useEffect"],"mappings":";;;;;AAG0B,cAAwC,IAAI;ACsD/D,IAAM,eAAA,GAAkBA,cAAgD,MAAS,CAAA;AACxF,eAAA,CAAgB,WAAA,GAAc,iBAAA;AC0GvB,SAAS,WAAA,GAAoC;AAClD,EAAA,MAAM,OAAA,GAAUC,WAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA;AAAA,MACN,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY,KAAA;AAAA,MACZ,SAAS,MAAM;AAAA,MAAC,CAAA;AAAA,MAChB,MAAA,EAAQ,aAAa,EAAE,KAAA,EAAO,UAAA,EAAW,CAAA;AAAA,MACzC,MAAA,EAAQ,aAAa,EAAE,KAAA,EAAO,UAAA,EAAW,CAAA;AAAA,MACzC,SAAS,YAAY;AAAA,MAAC,CAAA;AAAA,MACtB,UAAA,EAAY,aAAa,EAAE,KAAA,EAAO,UAAA,EAAW,CAAA;AAAA,MAC7C,YAAY,aAAa,EAAE,OAAA,EAAS,KAAA,EAAO,OAAO,UAAA,EAAW,CAAA;AAAA,MAC7D,uBAAuB,YAAY,IAAA;AAAA,MACnC,wBAAwB,YAAY,IAAA;AAAA,MACpC,eAAe,YAAY,IAAA;AAAA,MAC3B,aAAa,YAAY,IAAA;AAAA,MACzB,4BAA4B,aAAa,EAAE,OAAO,EAAE,OAAA,EAAS,YAAW,EAAE,CAAA;AAAA,MAC1E,gBAAgB,YAAY;AAAA,MAAC,CAAA;AAAA,MAC7B,qBAAqB,YAAY,IAAA;AAAA,MACjC,OAAA,EAAS,EAAA;AAAA,MACT,cAAA,EAAgB;AAAA,KAClB;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;;;AC3JO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAS,QAAA,EAAU,UAAA,KAAe,WAAA,EAAY;AACtE,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,UAAU,UAAA,EAAW;AACzD;;;ACDO,SAAS,OAAA,GAAU;AACxB,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,OAAA,KAAY,WAAA,EAAY;AAC5D,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,OAAA,EAAQ;AAC/C;ACLO,SAAS,mBAAA,GAGd;AACA,EAAA,MAAM,EAAE,mBAAA,EAAoB,GAAI,WAAA,EAAY;AAC5C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIC,SAA6C,IAAI,CAAA;AACrF,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,SAAS,KAAK,CAAA;AAE9C,EAAAC,UAAU,MAAM;AACd,IAAA,eAAe,WAAA,GAAc;AAC3B,MAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,EAAoB;AACzC,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,aAAA,CAAc,MAAM,CAAA;AAAA,MACtB,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,MAAM,wDAAwD,CAAA;AACtE,QAAA,aAAA,CAAc,IAAI,CAAA;AAAA,MACpB;AACA,MAAA,WAAA,CAAY,IAAI,CAAA;AAAA,IAClB;AAEA,IAAA,WAAA,EAAY;AAAA,EACd,CAAA,EAAG,CAAC,mBAAmB,CAAC,CAAA;AAExB,EAAA,OAAO,EAAE,YAAY,QAAA,EAAS;AAChC","file":"hooks.js","sourcesContent":["import { createContext, useContext, ReactNode } from 'react';\nimport type { NavigationAdapter } from './types';\n\nconst NavigationContext = createContext<NavigationAdapter | null>(null);\n\nexport interface NavigationProviderProps {\n adapter: NavigationAdapter;\n children: ReactNode;\n}\n\n/**\n * Navigation Provider\n * Injects navigation adapter into the component tree\n */\nexport function NavigationProvider({ adapter, children }: NavigationProviderProps) {\n return <NavigationContext.Provider value={adapter}>{children}</NavigationContext.Provider>;\n}\n\n/**\n * Hook to access navigation adapter\n * @throws Error if used outside NavigationProvider\n */\nexport function useNavigationAdapter(): NavigationAdapter {\n const adapter = useContext(NavigationContext);\n\n if (!adapter) {\n return {\n useSearchParams: () => new URLSearchParams(),\n Link: ({ href, children }) => <a href={href}>{children}</a>,\n };\n }\n\n return adapter;\n}\n","'use client';\n\nimport { createContext } from 'react';\nimport type { UserSchema } from '@insforge/sdk';\nimport type { InsforgeUser, OAuthProvider } from '../types';\nimport type {\n CreateSessionResponse,\n CreateUserResponse,\n GetPublicAuthConfigResponse,\n ResetPasswordResponse,\n} from '@insforge/shared-schemas';\n\nexport interface InsforgeContextValue {\n // Auth state\n user: InsforgeUser | null;\n isLoaded: boolean;\n isSignedIn: boolean;\n\n // Auth methods\n setUser: (user: InsforgeUser | null) => void;\n signIn: (\n email: string,\n password: string\n ) => Promise<CreateSessionResponse | { error: string; statusCode?: number; errorCode?: string }>;\n signUp: (\n email: string,\n password: string\n ) => Promise<CreateUserResponse | { error: string; statusCode?: number; errorCode?: string }>;\n signOut: () => Promise<void>;\n updateUser: (data: Partial<InsforgeUser>) => Promise<{ error: string } | null>;\n reloadAuth: () => Promise<{ success: boolean; error?: string }>;\n\n // Email verification methods\n sendVerificationEmail: (email: string) => Promise<{ success: boolean; message: string } | null>;\n sendResetPasswordEmail: (email: string) => Promise<{ success: boolean; message: string } | null>;\n resetPassword: (token: string, newPassword: string) => Promise<ResetPasswordResponse | null>;\n verifyEmail: (\n otp: string,\n email?: string\n ) => Promise<{\n accessToken: string;\n user?: UserSchema;\n redirectTo?: string;\n error?: { message: string };\n } | null>;\n exchangeResetPasswordToken: (\n email: string,\n code: string\n ) => Promise<{ token: string; expiresAt?: string } | { error: { message: string } }>;\n loginWithOAuth: (provider: OAuthProvider, redirectTo: string) => Promise<void>;\n // Public auth config\n getPublicAuthConfig: () => Promise<GetPublicAuthConfigResponse | null>;\n // Base config\n baseUrl: string;\n afterSignInUrl: string;\n}\n\nexport const InsforgeContext = createContext<InsforgeContextValue | undefined>(undefined);\nInsforgeContext.displayName = 'InsforgeContext';\n","import { useContext, useEffect, useState, useMemo, type ReactNode } from 'react';\nimport type { InsforgeUser, OAuthProvider } from '../types';\nimport { NavigationProvider, BrowserNavigationAdapter } from '../navigation';\nimport { InsforgeManager, type InsforgeManagerState } from '../core/InsforgeManager';\nimport { InsforgeContext, type InsforgeContextValue } from '../contexts/InsforgeContext';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n /**\n * URL to redirect to after successful sign in (when token is detected in URL)\n * @default '/'\n */\n afterSignInUrl?: string;\n onAuthChange?: (user: InsforgeUser | null) => void;\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n/**\n * Unified Insforge Provider - manages authentication state and configuration\n *\n * Uses singleton InsforgeManager to manage state across packages.\n * Context only subscribes to Manager and triggers React re-renders.\n *\n * @example\n * ```tsx\n * // Basic usage (React/Vite)\n * import { InsforgeProvider } from '@insforge/react';\n *\n * export default function App() {\n * return (\n * <InsforgeProvider\n * baseUrl={import.meta.env.VITE_INSFORGE_BASE_URL}\n * >\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With cookie sync (Next.js optimization)\n * <InsforgeProvider\n * baseUrl={baseUrl}\n * onSignIn={async (authToken) => {\n * await signIn(authToken);\n * }}\n * onSignOut={async () => {\n * await signOut();\n * }}\n * >\n * {children}\n * </InsforgeProvider>\n * ```\n */\nexport function InsforgeProviderCore({\n children,\n baseUrl,\n afterSignInUrl = '/',\n onAuthChange,\n onSignIn,\n onSignOut,\n}: InsforgeProviderProps) {\n // Get singleton Manager instance\n const manager = useMemo(\n () =>\n InsforgeManager.getInstance({\n baseUrl,\n afterSignInUrl,\n onAuthChange,\n onSignIn,\n onSignOut,\n }),\n [baseUrl, afterSignInUrl, onAuthChange, onSignIn, onSignOut]\n );\n\n // Subscribe to Manager state\n const [state, setState] = useState<InsforgeManagerState>(() => manager.getState());\n\n useEffect(() => {\n const unsubscribe = manager.subscribe((newState) => {\n setState(newState);\n });\n\n manager.initialize();\n\n return unsubscribe;\n }, [manager]);\n\n // Handle OAuth callback\n useEffect(() => {\n if (typeof window !== 'undefined') {\n manager.handleOAuthCallback(state.isLoaded, state.user);\n }\n }, [manager, state.isLoaded, state.user]);\n\n // Create stable method references that delegate to manager\n const contextValue = useMemo<InsforgeContextValue>(\n () => ({\n // State from Manager\n user: state.user,\n isLoaded: state.isLoaded,\n isSignedIn: state.isSignedIn,\n\n // Methods delegated to Manager\n setUser: (user: InsforgeUser | null) => manager.setUser(user),\n signIn: (email: string, password: string) => manager.signIn(email, password),\n signUp: (email: string, password: string) => manager.signUp(email, password),\n signOut: () => manager.signOut(),\n updateUser: (data: Partial<InsforgeUser>) => manager.updateUser(data),\n reloadAuth: () => manager.reloadAuth(),\n sendVerificationEmail: (email: string) => manager.sendVerificationEmail(email),\n sendResetPasswordEmail: (email: string) => manager.sendResetPasswordEmail(email),\n resetPassword: (token: string, newPassword: string) =>\n manager.resetPassword(token, newPassword),\n verifyEmail: (otp: string, email?: string) => manager.verifyEmail(otp, email),\n exchangeResetPasswordToken: (email: string, code: string) =>\n manager.exchangeResetPasswordToken(email, code),\n loginWithOAuth: (provider: OAuthProvider, redirectTo: string) =>\n manager.loginWithOAuth(provider, redirectTo),\n getPublicAuthConfig: () => manager.getPublicAuthConfig(),\n\n // Config\n baseUrl: manager.getConfig().baseUrl,\n afterSignInUrl: manager.getConfig().afterSignInUrl || '/',\n }),\n [state, manager]\n );\n\n return <InsforgeContext.Provider value={contextValue}>{children}</InsforgeContext.Provider>;\n}\n\nexport function InsforgeProvider(props: InsforgeProviderProps) {\n return (\n <NavigationProvider adapter={BrowserNavigationAdapter}>\n <InsforgeProviderCore {...props} />\n </NavigationProvider>\n );\n}\n\n/**\n * Hook to access Insforge context\n *\n * Works seamlessly across packages thanks to singleton Manager.\n * Context instance is guaranteed to be consistent.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useInsforge(): InsforgeContextValue {\n const context = useContext(InsforgeContext);\n\n if (!context) {\n return {\n user: null,\n isLoaded: false,\n isSignedIn: false,\n setUser: () => {},\n signIn: async () => ({ error: 'SSR mode' }),\n signUp: async () => ({ error: 'SSR mode' }),\n signOut: async () => {},\n updateUser: async () => ({ error: 'SSR mode' }),\n reloadAuth: async () => ({ success: false, error: 'SSR mode' }),\n sendVerificationEmail: async () => null,\n sendResetPasswordEmail: async () => null,\n resetPassword: async () => null,\n verifyEmail: async () => null,\n exchangeResetPasswordToken: async () => ({ error: { message: 'SSR mode' } }),\n loginWithOAuth: async () => {},\n getPublicAuthConfig: async () => null,\n baseUrl: '',\n afterSignInUrl: '/',\n };\n }\n\n return context;\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access authentication methods\n *\n * @returns Object containing:\n * - `signIn`: Function to sign in with email and password\n * - `signUp`: Function to sign up with email and password\n * - `signOut`: Function to sign out the current user\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `isSignedIn`: Boolean indicating if user is currently signed in\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const { signIn, signUp, signOut, isLoaded, isSignedIn } = useAuth();\n *\n * async function handleLogin(email: string, password: string) {\n * try {\n * await signIn(email, password);\n * // User is now signed in\n * } catch (error) {\n * console.error('Sign in failed:', error);\n * }\n * }\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <form onSubmit={(e) => { e.preventDefault(); handleLogin(email, password); }}>\n * {/* form fields *\\/}\n * </form>\n * );\n * }\n * ```\n */\nexport function useAuth() {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access current user data\n *\n * @returns Object containing:\n * - `user`: Current user object (InsforgeUser | null)\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `updateUser`: Function to update user profile data (returns { error: string } | null)\n * - `setUser`: Internal function to manually set user state\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { user, isLoaded, updateUser } = useUser();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n * if (!user) return <div>Not signed in</div>;\n *\n * async function handleUpdate(name: string) {\n * const result = await updateUser({ name });\n * if (result?.error) {\n * console.error(result.error);\n * } else {\n * console.log('User updated successfully');\n * }\n * }\n *\n * return (\n * <div>\n * <p>Email: {user.email}</p>\n * {user.name && <p>Name: {user.name}</p>}\n * {user.avatarUrl && <img src={user.avatarUrl} alt=\"Avatar\" />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser() {\n const { user, isLoaded, updateUser, setUser } = useInsforge();\n return { user, isLoaded, updateUser, setUser };\n}\n","import { useState, useEffect } from 'react';\nimport type { GetPublicAuthConfigResponse } from '@insforge/shared-schemas';\nimport { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to get all public authentication configuration (OAuth + Email) from Insforge backend\n *\n * **IMPORTANT: This hook should ONLY be used in SignIn and SignUp components.**\n *\n * This hook lazily fetches all public authentication configuration from the backend\n * only when the component mounts. Using it in other components will cause unnecessary\n * API calls on every page load.\n *\n * @returns Object containing OAuth providers, email auth config, and loading state\n * - `authConfig`: Email authentication configuration object with password rules\n * - `isLoaded`: Boolean indicating if the config has been fetched\n *\n * @example\n * ```tsx\n * // ✅ Correct usage - only in SignIn/SignUp components\n * function SignUp() {\n * const { authConfig, isLoaded } = usePublicAuthConfig();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <div>\n * <p>OAuth providers: {authConfig?.oauthProviders.length}</p>\n * <p>Password min length: {authConfig?.passwordMinLength}</p>\n * </div>\n * );\n * }\n * ```\n *\n * @requires Must be used within InsforgeProvider\n */\nexport function usePublicAuthConfig(): {\n authConfig: GetPublicAuthConfigResponse | null;\n isLoaded: boolean;\n} {\n const { getPublicAuthConfig } = useInsforge();\n const [authConfig, setAuthConfig] = useState<GetPublicAuthConfigResponse | null>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n\n useEffect(() => {\n async function fetchConfig() {\n const result = await getPublicAuthConfig();\n if (result) {\n setAuthConfig(result);\n } else {\n console.error('[usePublicAuthConfig] Failed to get public auth config');\n setAuthConfig(null);\n }\n setIsLoaded(true);\n }\n\n fetchConfig();\n }, [getPublicAuthConfig]);\n\n return { authConfig, isLoaded };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/navigation/NavigationContext.tsx","../src/provider/InsforgeProvider.tsx","../src/hooks/useAuth.ts","../src/hooks/useUser.ts","../src/hooks/usePublicAuthConfig.ts"],"names":["useContext","useState","useEffect"],"mappings":"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","file":"hooks.js","sourcesContent":["import { createContext, useContext, ReactNode } from 'react';\nimport type { NavigationAdapter } from './types';\n\nconst NavigationContext = createContext<NavigationAdapter | null>(null);\n\nexport interface NavigationProviderProps {\n adapter: NavigationAdapter;\n children: ReactNode;\n}\n\n/**\n * Navigation Provider\n * Injects navigation adapter into the component tree\n */\nexport function NavigationProvider({ adapter, children }: NavigationProviderProps) {\n return <NavigationContext.Provider value={adapter}>{children}</NavigationContext.Provider>;\n}\n\n/**\n * Hook to access navigation adapter\n * @throws Error if used outside NavigationProvider\n */\nexport function useNavigationAdapter(): NavigationAdapter {\n const adapter = useContext(NavigationContext);\n\n if (!adapter) {\n return {\n useSearchParams: () => new URLSearchParams(),\n Link: ({ href, children }) => <a href={href}>{children}</a>,\n };\n }\n\n return adapter;\n}\n","import { useContext, useEffect, useState, useMemo, type ReactNode } from 'react';\nimport type { InsforgeUser, OAuthProvider } from '../types';\nimport { NavigationProvider, BrowserNavigationAdapter } from '../navigation';\nimport { InsforgeManager, type InsforgeManagerState } from '../core/InsforgeManager';\nimport { InsforgeContext, type InsforgeContextValue } from '../contexts';\n\nexport interface InsforgeProviderProps {\n children: ReactNode;\n baseUrl: string;\n /**\n * URL to redirect to after successful sign in (when token is detected in URL)\n * @default '/'\n */\n afterSignInUrl?: string;\n onAuthChange?: (user: InsforgeUser | null) => void;\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n/**\n * Unified Insforge Provider - manages authentication state and configuration\n *\n * Uses singleton InsforgeManager to manage state across packages.\n * Context only subscribes to Manager and triggers React re-renders.\n *\n * @example\n * ```tsx\n * // Basic usage (React/Vite)\n * import { InsforgeProvider } from '@insforge/react';\n *\n * export default function App() {\n * return (\n * <InsforgeProvider\n * baseUrl={import.meta.env.VITE_INSFORGE_BASE_URL}\n * >\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With cookie sync (Next.js optimization)\n * <InsforgeProvider\n * baseUrl={baseUrl}\n * onSignIn={async (authToken) => {\n * await signIn(authToken);\n * }}\n * onSignOut={async () => {\n * await signOut();\n * }}\n * >\n * {children}\n * </InsforgeProvider>\n * ```\n */\nexport function InsforgeProviderCore({\n children,\n baseUrl,\n afterSignInUrl = '/',\n onAuthChange,\n onSignIn,\n onSignOut,\n}: InsforgeProviderProps) {\n // Get singleton Manager instance\n const manager = useMemo(\n () =>\n InsforgeManager.getInstance({\n baseUrl,\n afterSignInUrl,\n onAuthChange,\n onSignIn,\n onSignOut,\n }),\n [baseUrl, afterSignInUrl, onAuthChange, onSignIn, onSignOut]\n );\n\n // Subscribe to Manager state\n const [state, setState] = useState<InsforgeManagerState>(() => manager.getState());\n\n useEffect(() => {\n const unsubscribe = manager.subscribe((newState) => {\n setState(newState);\n });\n\n void manager.initialize();\n\n return unsubscribe;\n }, [manager]);\n\n // Handle OAuth callback\n useEffect(() => {\n if (typeof window !== 'undefined') {\n manager.handleOAuthCallback(state.isLoaded, state.user);\n }\n }, [manager, state.isLoaded, state.user]);\n\n // Create stable method references that delegate to manager\n const contextValue = useMemo<InsforgeContextValue>(\n () => ({\n // State from Manager\n user: state.user,\n isLoaded: state.isLoaded,\n isSignedIn: state.isSignedIn,\n\n // Methods delegated to Manager\n setUser: (user: InsforgeUser | null) => manager.setUser(user),\n signIn: (email: string, password: string) => manager.signIn(email, password),\n signUp: (email: string, password: string) => manager.signUp(email, password),\n signOut: () => manager.signOut(),\n updateUser: (data: Partial<InsforgeUser>) => manager.updateUser(data),\n reloadAuth: () => manager.reloadAuth(),\n sendVerificationEmail: (email: string) => manager.sendVerificationEmail(email),\n sendResetPasswordEmail: (email: string) => manager.sendResetPasswordEmail(email),\n resetPassword: (token: string, newPassword: string) =>\n manager.resetPassword(token, newPassword),\n verifyEmail: (otp: string, email?: string) => manager.verifyEmail(otp, email),\n exchangeResetPasswordToken: (email: string, code: string) =>\n manager.exchangeResetPasswordToken(email, code),\n loginWithOAuth: (provider: OAuthProvider, redirectTo: string) =>\n manager.loginWithOAuth(provider, redirectTo),\n getPublicAuthConfig: () => manager.getPublicAuthConfig(),\n\n // Config\n baseUrl: manager.getConfig().baseUrl,\n afterSignInUrl: manager.getConfig().afterSignInUrl || '/',\n }),\n [state, manager]\n );\n\n return <InsforgeContext.Provider value={contextValue}>{children}</InsforgeContext.Provider>;\n}\n\nexport function InsforgeProvider(props: InsforgeProviderProps) {\n return (\n <NavigationProvider adapter={BrowserNavigationAdapter}>\n <InsforgeProviderCore {...props} />\n </NavigationProvider>\n );\n}\n\n/**\n * Hook to access Insforge context\n *\n * Works seamlessly across packages thanks to singleton Manager.\n * Context instance is guaranteed to be consistent.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useInsforge(): InsforgeContextValue {\n const context = useContext(InsforgeContext);\n\n if (!context) {\n return {\n user: null,\n isLoaded: false,\n isSignedIn: false,\n setUser: () => {},\n signIn: () => Promise.resolve({ error: 'SSR mode' }),\n signUp: () => Promise.resolve({ error: 'SSR mode' }),\n signOut: () => Promise.resolve(),\n updateUser: () => Promise.resolve({ error: 'SSR mode' }),\n reloadAuth: () => Promise.resolve({ success: false, error: 'SSR mode' }),\n sendVerificationEmail: () => Promise.resolve(null),\n sendResetPasswordEmail: () => Promise.resolve(null),\n resetPassword: () => Promise.resolve(null),\n verifyEmail: () => Promise.resolve(null),\n exchangeResetPasswordToken: () => Promise.resolve({ error: { message: 'SSR mode' } }),\n loginWithOAuth: () => Promise.resolve(),\n getPublicAuthConfig: () => Promise.resolve(null),\n baseUrl: '',\n afterSignInUrl: '/',\n };\n }\n\n return context;\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access authentication methods\n *\n * @returns Object containing:\n * - `signIn`: Function to sign in with email and password\n * - `signUp`: Function to sign up with email and password\n * - `signOut`: Function to sign out the current user\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `isSignedIn`: Boolean indicating if user is currently signed in\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const { signIn, signUp, signOut, isLoaded, isSignedIn } = useAuth();\n *\n * async function handleLogin(email: string, password: string) {\n * try {\n * await signIn(email, password);\n * // User is now signed in\n * } catch (error) {\n * console.error('Sign in failed:', error);\n * }\n * }\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <form onSubmit={(e) => { e.preventDefault(); handleLogin(email, password); }}>\n * {/* form fields *\\/}\n * </form>\n * );\n * }\n * ```\n */\nexport function useAuth() {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n","import { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to access current user data\n *\n * @returns Object containing:\n * - `user`: Current user object (InsforgeUser | null)\n * - `isLoaded`: Boolean indicating if auth state has been loaded\n * - `updateUser`: Function to update user profile data (returns { error: string } | null)\n * - `setUser`: Internal function to manually set user state\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { user, isLoaded, updateUser } = useUser();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n * if (!user) return <div>Not signed in</div>;\n *\n * async function handleUpdate(name: string) {\n * const result = await updateUser({ name });\n * if (result?.error) {\n * console.error(result.error);\n * } else {\n * console.log('User updated successfully');\n * }\n * }\n *\n * return (\n * <div>\n * <p>Email: {user.email}</p>\n * {user.name && <p>Name: {user.name}</p>}\n * {user.avatarUrl && <img src={user.avatarUrl} alt=\"Avatar\" />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useUser() {\n const { user, isLoaded, updateUser, setUser } = useInsforge();\n return { user, isLoaded, updateUser, setUser };\n}\n","import { useState, useEffect } from 'react';\nimport type { GetPublicAuthConfigResponse } from '@insforge/shared-schemas';\nimport { useInsforge } from '../provider/InsforgeProvider';\n\n/**\n * Hook to get all public authentication configuration (OAuth + Email) from Insforge backend\n *\n * **IMPORTANT: This hook should ONLY be used in SignIn and SignUp components.**\n *\n * This hook lazily fetches all public authentication configuration from the backend\n * only when the component mounts. Using it in other components will cause unnecessary\n * API calls on every page load.\n *\n * @returns Object containing OAuth providers, email auth config, and loading state\n * - `authConfig`: Email authentication configuration object with password rules\n * - `isLoaded`: Boolean indicating if the config has been fetched\n *\n * @example\n * ```tsx\n * // ✅ Correct usage - only in SignIn/SignUp components\n * function SignUp() {\n * const { authConfig, isLoaded } = usePublicAuthConfig();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * return (\n * <div>\n * <p>OAuth providers: {authConfig?.oauthProviders.length}</p>\n * <p>Password min length: {authConfig?.passwordMinLength}</p>\n * </div>\n * );\n * }\n * ```\n *\n * @requires Must be used within InsforgeProvider\n */\nexport function usePublicAuthConfig(): {\n authConfig: GetPublicAuthConfigResponse | null;\n isLoaded: boolean;\n} {\n const { getPublicAuthConfig } = useInsforge();\n const [authConfig, setAuthConfig] = useState<GetPublicAuthConfigResponse | null>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n\n useEffect(() => {\n async function fetchConfig() {\n const result = await getPublicAuthConfig();\n if (result) {\n setAuthConfig(result);\n } else {\n console.error('[usePublicAuthConfig] Failed to get public auth config');\n setAuthConfig(null);\n }\n setIsLoaded(true);\n }\n\n void fetchConfig();\n }, [getPublicAuthConfig]);\n\n return { authConfig, isLoaded };\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -17,12 +17,11 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
|
|
17
17
|
var react = require('react');
|
|
18
18
|
var jsxRuntime = require('react/jsx-runtime');
|
|
19
19
|
var sdk = require('@insforge/sdk');
|
|
20
|
+
var react$1 = require('@insforge/shared/react');
|
|
20
21
|
var lucideReact = require('lucide-react');
|
|
21
22
|
var zod = require('zod');
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
25
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
24
|
+
// src/components/SignIn.tsx
|
|
26
25
|
var NavigationContext = react.createContext(null);
|
|
27
26
|
function NavigationProvider({ adapter, children }) {
|
|
28
27
|
return /* @__PURE__ */ jsxRuntime.jsx(NavigationContext.Provider, { value: adapter, children });
|
|
@@ -66,18 +65,20 @@ function useSearchParams() {
|
|
|
66
65
|
const adapter = useNavigationAdapter();
|
|
67
66
|
return adapter.useSearchParams();
|
|
68
67
|
}
|
|
69
|
-
var
|
|
68
|
+
var InsforgeManager = class _InsforgeManager {
|
|
69
|
+
// Static private instance
|
|
70
|
+
static instance = null;
|
|
71
|
+
// State storage
|
|
72
|
+
user = null;
|
|
73
|
+
isLoaded = false;
|
|
74
|
+
sdk;
|
|
75
|
+
listeners = /* @__PURE__ */ new Set();
|
|
76
|
+
// Config
|
|
77
|
+
config;
|
|
78
|
+
refreshIntervalRef = null;
|
|
79
|
+
hasProcessedCallbackRef = false;
|
|
70
80
|
// Private constructor (prevents external instantiation)
|
|
71
81
|
constructor(config) {
|
|
72
|
-
// State storage
|
|
73
|
-
__publicField(this, "user", null);
|
|
74
|
-
__publicField(this, "isLoaded", false);
|
|
75
|
-
__publicField(this, "sdk");
|
|
76
|
-
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
77
|
-
// Config
|
|
78
|
-
__publicField(this, "config");
|
|
79
|
-
__publicField(this, "refreshIntervalRef", null);
|
|
80
|
-
__publicField(this, "hasProcessedCallbackRef", false);
|
|
81
82
|
this.config = config;
|
|
82
83
|
this.sdk = sdk.createClient({ baseUrl: config.baseUrl });
|
|
83
84
|
}
|
|
@@ -330,9 +331,9 @@ var _InsforgeManager = class _InsforgeManager {
|
|
|
330
331
|
this.notifyListeners();
|
|
331
332
|
}
|
|
332
333
|
return null;
|
|
333
|
-
} else {
|
|
334
|
-
return { error: result.error?.message || "Failed to update user" };
|
|
335
334
|
}
|
|
335
|
+
const error = result.error;
|
|
336
|
+
return { error: error?.message || "Failed to update user" };
|
|
336
337
|
}
|
|
337
338
|
async reloadAuth() {
|
|
338
339
|
return await this.loadAuthState();
|
|
@@ -441,11 +442,6 @@ var _InsforgeManager = class _InsforgeManager {
|
|
|
441
442
|
this.listeners.clear();
|
|
442
443
|
}
|
|
443
444
|
};
|
|
444
|
-
// Static private instance
|
|
445
|
-
__publicField(_InsforgeManager, "instance", null);
|
|
446
|
-
var InsforgeManager = _InsforgeManager;
|
|
447
|
-
var InsforgeContext = react.createContext(void 0);
|
|
448
|
-
InsforgeContext.displayName = "InsforgeContext";
|
|
449
445
|
function InsforgeProviderCore({
|
|
450
446
|
children,
|
|
451
447
|
baseUrl,
|
|
@@ -469,7 +465,7 @@ function InsforgeProviderCore({
|
|
|
469
465
|
const unsubscribe = manager.subscribe((newState) => {
|
|
470
466
|
setState(newState);
|
|
471
467
|
});
|
|
472
|
-
manager.initialize();
|
|
468
|
+
void manager.initialize();
|
|
473
469
|
return unsubscribe;
|
|
474
470
|
}, [manager]);
|
|
475
471
|
react.useEffect(() => {
|
|
@@ -503,13 +499,13 @@ function InsforgeProviderCore({
|
|
|
503
499
|
}),
|
|
504
500
|
[state, manager]
|
|
505
501
|
);
|
|
506
|
-
return /* @__PURE__ */ jsxRuntime.jsx(InsforgeContext.Provider, { value: contextValue, children });
|
|
502
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react$1.InsforgeContext.Provider, { value: contextValue, children });
|
|
507
503
|
}
|
|
508
504
|
function InsforgeProvider(props) {
|
|
509
505
|
return /* @__PURE__ */ jsxRuntime.jsx(NavigationProvider, { adapter: BrowserNavigationAdapter, children: /* @__PURE__ */ jsxRuntime.jsx(InsforgeProviderCore, { ...props }) });
|
|
510
506
|
}
|
|
511
507
|
function useInsforge() {
|
|
512
|
-
const context = react.useContext(InsforgeContext);
|
|
508
|
+
const context = react.useContext(react$1.InsforgeContext);
|
|
513
509
|
if (!context) {
|
|
514
510
|
return {
|
|
515
511
|
user: null,
|
|
@@ -517,20 +513,18 @@ function useInsforge() {
|
|
|
517
513
|
isSignedIn: false,
|
|
518
514
|
setUser: () => {
|
|
519
515
|
},
|
|
520
|
-
signIn:
|
|
521
|
-
signUp:
|
|
522
|
-
signOut:
|
|
523
|
-
},
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
},
|
|
533
|
-
getPublicAuthConfig: async () => null,
|
|
516
|
+
signIn: () => Promise.resolve({ error: "SSR mode" }),
|
|
517
|
+
signUp: () => Promise.resolve({ error: "SSR mode" }),
|
|
518
|
+
signOut: () => Promise.resolve(),
|
|
519
|
+
updateUser: () => Promise.resolve({ error: "SSR mode" }),
|
|
520
|
+
reloadAuth: () => Promise.resolve({ success: false, error: "SSR mode" }),
|
|
521
|
+
sendVerificationEmail: () => Promise.resolve(null),
|
|
522
|
+
sendResetPasswordEmail: () => Promise.resolve(null),
|
|
523
|
+
resetPassword: () => Promise.resolve(null),
|
|
524
|
+
verifyEmail: () => Promise.resolve(null),
|
|
525
|
+
exchangeResetPasswordToken: () => Promise.resolve({ error: { message: "SSR mode" } }),
|
|
526
|
+
loginWithOAuth: () => Promise.resolve(),
|
|
527
|
+
getPublicAuthConfig: () => Promise.resolve(null),
|
|
534
528
|
baseUrl: "",
|
|
535
529
|
afterSignInUrl: "/"
|
|
536
530
|
};
|
|
@@ -552,7 +546,7 @@ function usePublicAuthConfig() {
|
|
|
552
546
|
}
|
|
553
547
|
setIsLoaded(true);
|
|
554
548
|
}
|
|
555
|
-
fetchConfig();
|
|
549
|
+
void fetchConfig();
|
|
556
550
|
}, [getPublicAuthConfig]);
|
|
557
551
|
return { authConfig, isLoaded };
|
|
558
552
|
}
|
|
@@ -1521,7 +1515,7 @@ function SignIn({ onError, ...uiProps }) {
|
|
|
1521
1515
|
}
|
|
1522
1516
|
function handleOAuth(provider) {
|
|
1523
1517
|
try {
|
|
1524
|
-
loginWithOAuth(provider, redirectUrl || "");
|
|
1518
|
+
void loginWithOAuth(provider, redirectUrl || "");
|
|
1525
1519
|
} catch (err) {
|
|
1526
1520
|
const errorMessage = err instanceof Error ? err.message : "OAuth login failed";
|
|
1527
1521
|
setError(errorMessage);
|
|
@@ -1540,7 +1534,7 @@ function SignIn({ onError, ...uiProps }) {
|
|
|
1540
1534
|
password,
|
|
1541
1535
|
onEmailChange: setEmail,
|
|
1542
1536
|
onPasswordChange: setPassword,
|
|
1543
|
-
onSubmit: handleSubmit,
|
|
1537
|
+
onSubmit: (e) => void handleSubmit(e),
|
|
1544
1538
|
error,
|
|
1545
1539
|
loading,
|
|
1546
1540
|
oauthLoading,
|
|
@@ -1798,7 +1792,7 @@ function SignUp({ onError, ...uiProps }) {
|
|
|
1798
1792
|
}
|
|
1799
1793
|
function handleOAuth(provider) {
|
|
1800
1794
|
try {
|
|
1801
|
-
loginWithOAuth(provider, redirectUrl || "");
|
|
1795
|
+
void loginWithOAuth(provider, redirectUrl || "");
|
|
1802
1796
|
} catch (err) {
|
|
1803
1797
|
const errorMessage = err instanceof Error ? err.message : "OAuth login failed";
|
|
1804
1798
|
setError(errorMessage);
|
|
@@ -1817,7 +1811,7 @@ function SignUp({ onError, ...uiProps }) {
|
|
|
1817
1811
|
password,
|
|
1818
1812
|
onEmailChange: setEmail,
|
|
1819
1813
|
onPasswordChange: setPassword,
|
|
1820
|
-
onSubmit: handleSubmit,
|
|
1814
|
+
onSubmit: (e) => void handleSubmit(e),
|
|
1821
1815
|
error,
|
|
1822
1816
|
loading,
|
|
1823
1817
|
oauthLoading,
|
|
@@ -2127,7 +2121,7 @@ function ForgotPassword({ onError, ...uiProps }) {
|
|
|
2127
2121
|
confirmPassword,
|
|
2128
2122
|
onNewPasswordChange: setNewPassword,
|
|
2129
2123
|
onConfirmPasswordChange: setConfirmPassword,
|
|
2130
|
-
onSubmit: handleResetPasswordSubmit,
|
|
2124
|
+
onSubmit: (e) => void handleResetPasswordSubmit(e),
|
|
2131
2125
|
error,
|
|
2132
2126
|
loading,
|
|
2133
2127
|
success,
|
|
@@ -2302,7 +2296,7 @@ function ResetPassword({ onError, ...uiProps }) {
|
|
|
2302
2296
|
confirmPassword,
|
|
2303
2297
|
onNewPasswordChange: setNewPassword,
|
|
2304
2298
|
onConfirmPasswordChange: setConfirmPassword,
|
|
2305
|
-
onSubmit: handleSubmit,
|
|
2299
|
+
onSubmit: (e) => void handleSubmit(e),
|
|
2306
2300
|
error,
|
|
2307
2301
|
loading,
|
|
2308
2302
|
success: false,
|
|
@@ -2426,7 +2420,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
|
|
|
2426
2420
|
setImageError(true);
|
|
2427
2421
|
}
|
|
2428
2422
|
};
|
|
2429
|
-
checkImageUrl();
|
|
2423
|
+
void checkImageUrl();
|
|
2430
2424
|
}, [user?.avatarUrl]);
|
|
2431
2425
|
react.useEffect(() => {
|
|
2432
2426
|
function handleClickOutside(event) {
|
|
@@ -2479,7 +2473,7 @@ function UserButton({ afterSignOutUrl = "/", mode = "detailed" }) {
|
|
|
2479
2473
|
isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "if-userButton-menu", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2480
2474
|
"button",
|
|
2481
2475
|
{
|
|
2482
|
-
onClick: handleSignOut,
|
|
2476
|
+
onClick: () => void handleSignOut(),
|
|
2483
2477
|
className: "if-userButton-menuItem if-userButton-menuItem-signout",
|
|
2484
2478
|
children: [
|
|
2485
2479
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { className: "if-userButton-menuItem-icon" }),
|