UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 20.1 kB
{"version":3,"file":"use-auth.cjs","sources":["../../../src/hooks/use-auth.ts"],"sourcesContent":["'use client'\n\n/**\n * @frank-auth/react - useAuth Hook\n *\n * Main authentication hook that provides access to authentication state,\n * methods, and organization context. This is the primary hook for most\n * authentication operations.\n */\n\nimport {useCallback, useMemo} from 'react';\n\nimport type {\n Organization,\n PasswordResetConfirmRequest,\n PasswordResetConfirmResponse,\n PasswordResetResponse,\n ResendVerificationRequest,\n ResendVerificationResponse,\n Session,\n User,\n ValidateTokenInputBody,\n ValidateTokenResponse, VerificationRequest, VerificationResponse,\n} from '@frank-auth/client';\n\nimport {useAuth as useAuthProvider} from '../provider/auth-provider';\nimport {useConfig} from '../provider/config-provider';\n\nimport type {\n AuthError,\n OrganizationMembership, SDKState,\n SetActiveParams,\n SignInParams,\n SignInResult,\n SignUpParams,\n SignUpResult,\n UpdateUserParams,\n} from '../provider/types';\nimport type {PasswordResetRequest} from \"@frank-auth/sdk\";\n\n// ============================================================================\n// Auth Hook Interface\n// ============================================================================\n\nexport interface UseAuthReturn {\n sdk: SDKState\n\n // Authentication state\n isLoaded: boolean;\n isLoading: boolean;\n isSignedIn: boolean;\n user: User | null;\n session: Session | null;\n\n // Organization context\n organization: Organization | null;\n organizationMemberships: OrganizationMembership[];\n activeOrganization: Organization | null;\n\n // Error handling\n error: AuthError | null;\n\n // Authentication methods\n signIn: (params: SignInParams) => Promise<SignInResult>;\n signUp: (params: SignUpParams) => Promise<SignUpResult>;\n signOut: () => Promise<void>;\n resendVerification: (request: ResendVerificationRequest) => Promise<ResendVerificationResponse>\n verifyIdentity: (type: \"email\" | \"phone\", request: VerificationRequest) => Promise<VerificationResponse>\n\n // Session management\n createSession: (token: string) => Promise<Session>;\n setActive: (params: SetActiveParams) => Promise<void>;\n\n // Organization management\n setActiveOrganization: (organizationId: string) => Promise<void>;\n switchOrganization: (organizationId: string) => Promise<void>;\n\n // User management\n updateUser: (params: UpdateUserParams) => Promise<User>;\n deleteUser: () => Promise<void>;\n\n // Utility methods\n reload: () => Promise<void>;\n\n // Recovery\n resetPassword: (params: PasswordResetConfirmRequest) => Promise<PasswordResetConfirmResponse>\n requestPasswordReset: (request: PasswordResetRequest) => Promise<PasswordResetResponse>\n\n extractEmailFromUrl: (url?: string) => (string | null)\n extractTokenFromUrl: (url?: string) => (string | null)\n validateToken: (request: ValidateTokenInputBody) => Promise<ValidateTokenResponse>\n\n // Convenience properties\n userId: string | null;\n userEmail: string | null;\n userName: string | null;\n organizationId: string | null;\n organizationName: string | null;\n userType: string | null;\n\n // Permission helpers\n hasOrganization: boolean;\n isOrganizationMember: boolean;\n isOrganizationAdmin: boolean;\n\n // Status helpers\n isAuthenticated: boolean;\n requiresVerification: boolean;\n requiresMFA: boolean;\n}\n\n// ============================================================================\n// Main useAuth Hook\n// ============================================================================\n\n/**\n * Main authentication hook providing access to all authentication functionality\n *\n * @example Basic usage\n * ```tsx\n * import { useAuth } from '@frank-auth/react';\n *\n * function MyComponent() {\n * const { user, signIn, signOut, isLoaded } = useAuth();\n *\n * if (!isLoaded) return <div>Loading...</div>;\n *\n * if (!user) {\n * return <button onClick={() => signIn({ strategy: 'password', identifier: 'user@example.com', password: 'password' })}>\n * Sign In\n * </button>;\n * }\n *\n * return (\n * <div>\n * <p>Welcome, {user.firstName}!</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example Organization management\n * ```tsx\n * function OrganizationSwitcher() {\n * const { organizationMemberships, activeOrganization, switchOrganization } = useAuth();\n *\n * return (\n * <select\n * value={activeOrganization?.id || ''}\n * onChange={(e) => switchOrganization(e.target.value)}\n * >\n * {organizationMemberships.map((membership) => (\n * <option key={membership.organization.id} value={membership.organization.id}>\n * {membership.organization.name}\n * </option>\n * ))}\n * </select>\n * );\n * }\n * ```\n */\nexport function useAuth(): UseAuthReturn {\n const authContext = useAuthProvider();\n const { userType, features } = useConfig();\n\n // Convenience properties\n const userId = useMemo(() => authContext.user?.id || null, [authContext.user]);\n const userEmail = useMemo(() => authContext.user?.primaryEmailAddress || null, [authContext.user]);\n const userName = useMemo(() => {\n if (!authContext.user) return null;\n return authContext.user.username ||\n `${authContext.user.firstName || ''} ${authContext.user.lastName || ''}`.trim() ||\n authContext.user.primaryEmailAddress ||\n null;\n }, [authContext.user]);\n\n const organizationId = useMemo(() =>\n authContext.activeOrganization?.id || null,\n [authContext.activeOrganization]\n );\n\n const organizationName = useMemo(() =>\n authContext.activeOrganization?.name || null,\n [authContext.activeOrganization]\n );\n\n // Permission helpers\n const hasOrganization = useMemo(() =>\n !!authContext.activeOrganization,\n [authContext.activeOrganization]\n );\n\n const isOrganizationMember = useMemo(() => {\n if (!authContext.activeOrganization || !authContext.user) return false;\n return authContext.organizationMemberships.some(\n membership => membership.organization.id === authContext.activeOrganization?.id\n );\n }, [authContext.activeOrganization, authContext.user, authContext.organizationMemberships]);\n\n const isOrganizationAdmin = useMemo(() => {\n if (!authContext.activeOrganization || !authContext.user) return false;\n const membership = authContext.organizationMemberships.find(\n membership => membership.organization.id === authContext.activeOrganization?.id\n );\n return membership?.role === 'admin' || membership?.role === 'owner';\n }, [authContext.activeOrganization, authContext.user, authContext.organizationMemberships]);\n\n // Status helpers\n const isAuthenticated = useMemo(() =>\n authContext.isLoaded && authContext.isSignedIn,\n [authContext.isLoaded, authContext.isSignedIn]\n );\n\n const requiresVerification = useMemo(() => {\n if (!authContext.user) return false;\n return !authContext.user.emailVerified ||\n (features.mfa && !authContext.user.mfaEnabled);\n }, [authContext.user, features.mfa]);\n\n const requiresMFA = useMemo(() => {\n if (!authContext.user) return false;\n return features.mfa && !authContext.user.mfaEnabled;\n }, [authContext.user, features.mfa]);\n\n // Enhanced sign in with validation\n const signIn = useCallback(async (params: SignInParams): Promise<SignInResult> => {\n // Validate required features\n if (params.strategy === 'oauth' && !features.oauth) {\n throw new Error('OAuth authentication is not enabled for this organization');\n }\n\n if (params.strategy === 'passkey' && !features.passkeys) {\n throw new Error('Passkey authentication is not enabled for this organization');\n }\n\n if (params.strategy === 'sso' && !features.sso) {\n throw new Error('SSO authentication is not enabled for this organization');\n }\n\n if (params.strategy === 'magic_link' && !features.magicLink) {\n throw new Error('Magic link authentication is not enabled for this organization');\n }\n\n return authContext.signIn(params);\n }, [authContext.signIn, features]);\n\n // Enhanced sign up with validation\n const signUp = useCallback(async (params: SignUpParams): Promise<SignUpResult> => {\n // Validate sign up is enabled\n if (!features.signUp) {\n throw new Error('User registration is not enabled for this organization');\n }\n\n return authContext.signUp(params);\n }, [authContext.signUp, features]);\n\n\n // Extract token from URL\n const extractEmailFromUrl = useCallback((url?: string): string | null => {\n const urlToCheck = url || window.location.href;\n\n try {\n const urlObj = new URL(urlToCheck);\n return urlObj.searchParams.get('email');\n } catch {\n return null;\n }\n }, []);\n\n // Extract token from URL\n const extractTokenFromUrl = useCallback((url?: string): string | null => {\n const urlToCheck = url || window.location.href;\n\n try {\n const urlObj = new URL(urlToCheck);\n return urlObj.searchParams.get('token');\n } catch {\n return null;\n }\n }, []);\n\n return {\n sdk: authContext.sdk,\n\n // Core authentication state\n isLoaded: authContext.isLoaded,\n isLoading: authContext.isLoading,\n isSignedIn: authContext.isSignedIn,\n user: authContext.user,\n session: authContext.session,\n\n // Organization context\n organization: authContext.organization,\n organizationMemberships: authContext.organizationMemberships,\n activeOrganization: authContext.activeOrganization,\n\n // Error state\n error: authContext.error,\n\n // Authentication methods\n signIn,\n signUp,\n signOut: authContext.signOut,\n resendVerification: authContext.resendVerification,\n verifyIdentity: authContext.verifyIdentity,\n\n // Recovery methods\n requestPasswordReset: authContext.requestPasswordReset,\n resetPassword: authContext.resetPassword,\n validateToken: authContext.validateToken,\n extractEmailFromUrl,\n extractTokenFromUrl,\n\n // Session management\n createSession: authContext.createSession,\n setActive: authContext.setActive,\n\n // Organization management\n setActiveOrganization: authContext.setActiveOrganization,\n switchOrganization: authContext.switchOrganization,\n\n // User management\n updateUser: authContext.updateUser,\n deleteUser: authContext.deleteUser,\n\n // Utility methods\n reload: authContext.reload,\n\n // Convenience properties\n userId,\n userEmail,\n userName,\n organizationId,\n organizationName,\n userType,\n\n // Permission helpers\n hasOrganization,\n isOrganizationMember,\n isOrganizationAdmin,\n\n // Status helpers\n isAuthenticated,\n requiresVerification,\n requiresMFA,\n };\n}\n\n// ============================================================================\n// Specialized Auth Hooks\n// ============================================================================\n\n/**\n * Hook for authentication state only (no methods)\n * Useful for components that only need to display auth state\n */\nexport function useAuthState() {\n const {\n isLoaded,\n isLoading,\n isSignedIn,\n user,\n session,\n organization,\n activeOrganization,\n error,\n userId,\n userEmail,\n userName,\n organizationId,\n organizationName,\n userType,\n hasOrganization,\n isOrganizationMember,\n isOrganizationAdmin,\n isAuthenticated,\n requiresVerification,\n requiresMFA,\n } = useAuth();\n\n return {\n isLoaded,\n isLoading,\n isSignedIn,\n user,\n session,\n organization,\n activeOrganization,\n error,\n userId,\n userEmail,\n userName,\n organizationId,\n organizationName,\n userType,\n hasOrganization,\n isOrganizationMember,\n isOrganizationAdmin,\n isAuthenticated,\n requiresVerification,\n requiresMFA,\n };\n}\n\n/**\n * Hook for authentication methods only\n * Useful for forms and action components\n */\nexport function useAuthActions() {\n const {\n signIn,\n signUp,\n signOut,\n createSession,\n setActive,\n setActiveOrganization,\n switchOrganization,\n updateUser,\n deleteUser,\n reload,\n } = useAuth();\n\n return {\n signIn,\n signUp,\n signOut,\n createSession,\n setActive,\n setActiveOrganization,\n switchOrganization,\n updateUser,\n deleteUser,\n reload,\n };\n}\n\n/**\n * Hook for organization-specific authentication data\n * Useful for multi-tenant applications\n */\nexport function useAuthOrganization() {\n const {\n organization,\n organizationMemberships,\n activeOrganization,\n organizationId,\n organizationName,\n hasOrganization,\n isOrganizationMember,\n isOrganizationAdmin,\n setActiveOrganization,\n switchOrganization,\n } = useAuth();\n\n return {\n organization,\n organizationMemberships,\n activeOrganization,\n organizationId,\n organizationName,\n hasOrganization,\n isOrganizationMember,\n isOrganizationAdmin,\n setActiveOrganization,\n switchOrganization,\n };\n}\n\n/**\n * Authentication status hook with loading states\n * Useful for conditional rendering based on auth status\n */\nexport function useAuthStatus() {\n const {\n isLoaded,\n isLoading,\n isSignedIn,\n isAuthenticated,\n requiresVerification,\n requiresMFA,\n error,\n } = useAuth();\n\n return {\n isLoaded,\n isLoading,\n isSignedIn,\n isAuthenticated,\n requiresVerification,\n requiresMFA,\n hasError: !!error,\n error,\n status: isLoading ? 'loading' :\n isSignedIn ? 'signed-in' :\n 'signed-out',\n };\n}"],"names":["useAuth","authContext","useAuthProvider","userType","features","useConfig","userId","useMemo","userEmail","userName","organizationId","organizationName","hasOrganization","isOrganizationMember","membership","isOrganizationAdmin","isAuthenticated","requiresVerification","requiresMFA","signIn","useCallback","params","signUp","extractEmailFromUrl","url","urlToCheck","extractTokenFromUrl","useAuthState","isLoaded","isLoading","isSignedIn","user","session","organization","activeOrganization","error","useAuthActions","signOut","createSession","setActive","setActiveOrganization","switchOrganization","updateUser","deleteUser","reload","useAuthOrganization","organizationMemberships","useAuthStatus"],"mappings":"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"}