@forge-connect/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1179 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +310 -0
- package/dist/index.d.ts +310 -0
- package/dist/index.js +1149 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +443 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/context.ts","../src/api/client.ts","../src/utils.ts","../src/hooks/use-forge-connect.ts","../src/components/modal-overlay.tsx","../src/components/tabs/email-password.tsx","../src/components/tabs/email-otp.tsx","../src/components/tabs/wallet-connect.tsx","../src/components/tabs/oauth-buttons.tsx","../src/components/login-modal.tsx","../src/components/login-button.tsx","../src/hooks/use-user.ts","../src/hooks/use-wallets.ts","../src/hooks/use-sessions.ts"],"sourcesContent":["// Provider\nexport { ForgeConnectProvider } from './provider';\n\n// Components\nexport { LoginButton } from './components/login-button';\nexport { LoginModal } from './components/login-modal';\nexport { ModalOverlay } from './components/modal-overlay';\n\n// Hooks\nexport { useForgeConnect } from './hooks/use-forge-connect';\nexport { useUser } from './hooks/use-user';\nexport { useWallets } from './hooks/use-wallets';\nexport { useSessions } from './hooks/use-sessions';\n\n// Context (for advanced usage)\nexport { ForgeConnectContext } from './context';\nexport type { ForgeConnectContextValue } from './context';\n\n// API client (for advanced usage)\nexport { createApiClient, ForgeConnectApiError } from './api/client';\nexport type { ApiClient } from './api/client';\n\n// Types\nexport type {\n ForgeConnectConfig,\n AppearanceConfig,\n OAuthProvider,\n User,\n AuthMethod,\n AuthProvider,\n Wallet,\n Chain,\n Session,\n AuthState,\n AuthStatus,\n ModalState,\n ModalStep,\n} from './types';\n","import { useState, useCallback, useEffect, useRef, type ReactNode } from 'react';\nimport { ForgeConnectContext, type ForgeConnectContextValue } from './context';\nimport { createApiClient, ForgeConnectApiError } from './api/client';\nimport type { AuthState, ModalState, ForgeConnectConfig, User, ModalStep } from './types';\nimport { getStoredToken, setStoredToken, removeStoredToken, getRefreshDelay } from './utils';\nimport { LoginModal } from './components/login-modal';\n\ninterface ForgeConnectProviderProps {\n config: ForgeConnectConfig;\n children: ReactNode;\n /** Called when user successfully authenticates */\n onLogin?: (user: User) => void;\n /** Called when user logs out */\n onLogout?: () => void;\n}\n\nexport function ForgeConnectProvider({ config, children, onLogin, onLogout }: ForgeConnectProviderProps) {\n const [auth, setAuth] = useState<AuthState>({\n status: 'loading',\n user: null,\n accessToken: null,\n });\n\n const [modal, setModal] = useState<ModalState>({\n isOpen: false,\n step: 'method-select',\n });\n\n const apiRef = useRef(createApiClient(config.apiUrl));\n const refreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const api = apiRef.current;\n\n // ── Token Refresh Scheduling ──\n\n const scheduleRefresh = useCallback((token: string) => {\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n const delay = getRefreshDelay(token);\n if (delay === null) return;\n\n refreshTimerRef.current = setTimeout(async () => {\n try {\n const { accessToken } = await api.refresh();\n setStoredToken(accessToken);\n setAuth((prev) => ({ ...prev, accessToken }));\n scheduleRefresh(accessToken);\n } catch {\n // Refresh failed — log user out\n removeStoredToken();\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n }\n }, delay);\n }, [api]);\n\n // ── Initialize from stored token ──\n\n useEffect(() => {\n const init = async () => {\n const token = getStoredToken();\n if (!token) {\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n return;\n }\n\n try {\n const user = await api.getMe(token);\n setAuth({ status: 'authenticated', user, accessToken: token });\n scheduleRefresh(token);\n } catch (err) {\n // Token expired — try refresh\n if (err instanceof ForgeConnectApiError && err.status === 401) {\n try {\n const { accessToken } = await api.refresh();\n const user = await api.getMe(accessToken);\n setStoredToken(accessToken);\n setAuth({ status: 'authenticated', user, accessToken });\n scheduleRefresh(accessToken);\n } catch {\n removeStoredToken();\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n }\n } else {\n removeStoredToken();\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n }\n }\n };\n init();\n\n return () => {\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n };\n }, [api, scheduleRefresh]);\n\n // ── OAuth popup/callback handler ──\n\n useEffect(() => {\n // Check if THIS window is the OAuth callback popup\n if (window.location.pathname === '/__fc_oauth_callback') {\n const params = new URLSearchParams(window.location.search);\n const token = params.get('fc_token');\n if (token && window.opener) {\n window.opener.postMessage(\n { type: 'fc_oauth_callback', accessToken: token },\n window.location.origin,\n );\n window.close();\n return;\n }\n }\n\n // Listen for messages from OAuth popup\n const handleMessage = async (event: MessageEvent) => {\n if (event.origin !== window.location.origin) return;\n if (event.data?.type !== 'fc_oauth_callback') return;\n\n const token = event.data.accessToken as string;\n if (!token) return;\n\n setStoredToken(token);\n try {\n const user = await api.getMe(token);\n setAuth({ status: 'authenticated', user, accessToken: token });\n scheduleRefresh(token);\n setModal({ isOpen: false, step: 'method-select' });\n onLogin?.(user);\n } catch {\n removeStoredToken();\n }\n };\n\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [api, config.apiUrl, scheduleRefresh, onLogin]);\n\n // ── Auth Actions ──\n\n const handleAuthSuccess = useCallback(\n async (token: string) => {\n setStoredToken(token);\n const user = await api.getMe(token);\n setAuth({ status: 'authenticated', user, accessToken: token });\n scheduleRefresh(token);\n setModal({ isOpen: false, step: 'method-select' });\n onLogin?.(user);\n },\n [api, scheduleRefresh, onLogin],\n );\n\n const loginWithEmail = useCallback(\n async (email: string, password: string) => {\n const { accessToken } = await api.login(email, password);\n await handleAuthSuccess(accessToken);\n },\n [api, handleAuthSuccess],\n );\n\n const register = useCallback(\n async (email: string, password: string, displayName?: string) => {\n await api.register(email, password, displayName);\n // Registration sends verification email, no token returned\n },\n [api],\n );\n\n const sendOtp = useCallback(\n async (email: string) => {\n await api.sendOtp(email);\n },\n [api],\n );\n\n const verifyOtp = useCallback(\n async (email: string, code: string) => {\n const { accessToken } = await api.verifyOtp(email, code);\n await handleAuthSuccess(accessToken);\n },\n [api, handleAuthSuccess],\n );\n\n const loginWithWallet = useCallback(\n async (\n walletAddress: string,\n signMessage: (message: Uint8Array) => Promise<Uint8Array>,\n chain: string = 'solana',\n ) => {\n const { challengeId, nonce } = await api.walletChallenge(walletAddress, chain);\n const message = new TextEncoder().encode(nonce);\n const signatureBytes = await signMessage(message);\n // Convert Uint8Array to base58 for Solana\n const signature = chain === 'solana'\n ? uint8ArrayToBase58(signatureBytes)\n : Array.from(signatureBytes).map((b) => b.toString(16).padStart(2, '0')).join('');\n const { accessToken } = await api.walletVerify(challengeId, signature, walletAddress);\n await handleAuthSuccess(accessToken);\n },\n [api, handleAuthSuccess],\n );\n\n const loginWithOAuth = useCallback(\n (provider: string) => {\n const callbackUrl = `${config.apiUrl}/auth/oauth/${provider}`;\n const redirectUri = encodeURIComponent(window.location.origin + '/__fc_oauth_callback');\n const url = `${callbackUrl}?redirect_uri=${redirectUri}`;\n const width = 500;\n const height = 600;\n const left = window.screenX + (window.innerWidth - width) / 2;\n const top = window.screenY + (window.innerHeight - height) / 2;\n window.open(url, 'fc_oauth', `width=${width},height=${height},left=${left},top=${top}`);\n },\n [config.apiUrl],\n );\n\n const logout = useCallback(async () => {\n const token = auth.accessToken;\n removeStoredToken();\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n onLogout?.();\n if (token) {\n try {\n await api.logout(token);\n } catch {\n // Already logged out client-side\n }\n }\n }, [auth.accessToken, api, onLogout]);\n\n const logoutAll = useCallback(async () => {\n const token = auth.accessToken;\n removeStoredToken();\n if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);\n setAuth({ status: 'unauthenticated', user: null, accessToken: null });\n onLogout?.();\n if (token) {\n try {\n await api.logoutAll(token);\n } catch {\n // Already logged out client-side\n }\n }\n }, [auth.accessToken, api, onLogout]);\n\n // ── Modal Actions ──\n\n const openModal = useCallback(() => {\n setModal({ isOpen: true, step: 'method-select' });\n }, []);\n\n const closeModal = useCallback(() => {\n setModal({ isOpen: false, step: 'method-select' });\n }, []);\n\n const setModalStep = useCallback((step: ModalStep) => {\n setModal((prev) => ({ ...prev, step }));\n }, []);\n\n const getAccessToken = useCallback(() => auth.accessToken, [auth.accessToken]);\n\n // ── Context Value ──\n\n const value: ForgeConnectContextValue = {\n auth,\n modal,\n config,\n api,\n loginWithEmail,\n register,\n sendOtp,\n verifyOtp,\n loginWithWallet,\n loginWithOAuth,\n logout,\n logoutAll,\n openModal,\n closeModal,\n setModalStep,\n getAccessToken,\n };\n\n return (\n <ForgeConnectContext.Provider value={value}>\n {children}\n <LoginModal />\n </ForgeConnectContext.Provider>\n );\n}\n\n// ── Helpers ──\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n\nfunction uint8ArrayToBase58(bytes: Uint8Array): string {\n const digits = [0];\n for (const byte of bytes) {\n let carry = byte;\n for (let j = 0; j < digits.length; j++) {\n carry += digits[j] << 8;\n digits[j] = carry % 58;\n carry = (carry / 58) | 0;\n }\n while (carry > 0) {\n digits.push(carry % 58);\n carry = (carry / 58) | 0;\n }\n }\n let str = '';\n for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {\n str += '1';\n }\n for (let i = digits.length - 1; i >= 0; i--) {\n str += BASE58_ALPHABET[digits[i]];\n }\n return str;\n}\n","import { createContext } from 'react';\nimport type { AuthState, ModalState, ForgeConnectConfig } from './types';\nimport type { ApiClient } from './api/client';\n\nexport interface ForgeConnectContextValue {\n // State\n auth: AuthState;\n modal: ModalState;\n config: ForgeConnectConfig;\n api: ApiClient;\n\n // Auth actions\n loginWithEmail: (email: string, password: string) => Promise<void>;\n register: (email: string, password: string, displayName?: string) => Promise<void>;\n sendOtp: (email: string) => Promise<void>;\n verifyOtp: (email: string, code: string) => Promise<void>;\n loginWithWallet: (walletAddress: string, signMessage: (message: Uint8Array) => Promise<Uint8Array>, chain?: string) => Promise<void>;\n loginWithOAuth: (provider: string) => void;\n logout: () => Promise<void>;\n logoutAll: () => Promise<void>;\n\n // Modal actions\n openModal: () => void;\n closeModal: () => void;\n setModalStep: (step: ModalState['step']) => void;\n\n // Token\n getAccessToken: () => string | null;\n}\n\nexport const ForgeConnectContext = createContext<ForgeConnectContextValue | null>(null);\n","import type { ApiErrorBody } from '../types';\n\nexport class ForgeConnectApiError extends Error {\n public readonly status: number;\n public readonly code: string;\n\n constructor(status: number, code: string, message: string) {\n super(message);\n this.name = 'ForgeConnectApiError';\n this.status = status;\n this.code = code;\n }\n}\n\nexport function createApiClient(apiUrl: string) {\n const base = apiUrl.replace(/\\/+$/, '');\n\n async function request<T>(\n path: string,\n options: {\n method?: string;\n body?: unknown;\n token?: string | null;\n } = {},\n ): Promise<T> {\n const { method = 'GET', body, token } = options;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const res = await fetch(`${base}${path}`, {\n method,\n headers,\n credentials: 'include',\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n let errorBody: ApiErrorBody;\n try {\n errorBody = await res.json() as ApiErrorBody;\n } catch {\n throw new ForgeConnectApiError(res.status, 'UNKNOWN', res.statusText);\n }\n throw new ForgeConnectApiError(res.status, errorBody.error.code, errorBody.error.message);\n }\n\n return res.json() as Promise<T>;\n }\n\n return {\n // ── Auth: Email ──\n register(email: string, password: string, displayName?: string) {\n return request<{ success: true }>('/auth/email/register', {\n method: 'POST',\n body: { email, password, displayName },\n });\n },\n\n login(email: string, password: string) {\n return request<{ accessToken: string; user: { id: string; displayName: string | null; email: string } }>(\n '/auth/email/login',\n { method: 'POST', body: { email, password } },\n );\n },\n\n sendOtp(email: string) {\n return request<{ success: true }>('/auth/email/send-code', {\n method: 'POST',\n body: { email },\n });\n },\n\n verifyOtp(email: string, code: string) {\n return request<{ accessToken: string; user: { id: string; email: string } }>(\n '/auth/email/verify-code',\n { method: 'POST', body: { email, code } },\n );\n },\n\n // ── Auth: Wallet ──\n walletChallenge(walletAddress: string, chain: string = 'solana') {\n return request<{ challengeId: string; nonce: string }>('/auth/wallet/challenge', {\n method: 'POST',\n body: { walletAddress, chain },\n });\n },\n\n walletVerify(challengeId: string, signature: string, walletAddress: string) {\n return request<{ accessToken: string }>('/auth/wallet/verify', {\n method: 'POST',\n body: { challengeId, signature, walletAddress },\n });\n },\n\n // ── Auth: Session ──\n refresh() {\n return request<{ accessToken: string }>('/auth/refresh', { method: 'POST' });\n },\n\n logout(token: string) {\n return request<{ success: true }>('/auth/logout', { method: 'POST', token });\n },\n\n logoutAll(token: string) {\n return request<{ success: true }>('/auth/logout-all', { method: 'POST', token });\n },\n\n // ── User ──\n getMe(token: string) {\n return request<{ id: string; displayName: string | null; avatarUrl: string | null; primaryEmail: string | null; status: string; createdAt: string; updatedAt: string }>(\n '/users/me',\n { token },\n );\n },\n\n updateMe(token: string, data: { displayName?: string; avatarUrl?: string }) {\n return request<{ id: string; displayName: string | null; avatarUrl: string | null; primaryEmail: string | null; status: string; createdAt: string; updatedAt: string }>(\n '/users/me',\n { method: 'PATCH', token, body: data },\n );\n },\n\n getAuthMethods(token: string) {\n return request<Array<{ id: string; provider: string; providerId: string; isVerified: boolean; verifiedAt: string | null; createdAt: string }>>(\n '/users/me/auth-methods',\n { token },\n );\n },\n\n linkAuthMethod(token: string, data: { provider: string; email?: string; password?: string; challengeId?: string; signature?: string; walletAddress?: string }) {\n return request<{ success: true }>('/users/me/auth-methods', {\n method: 'POST',\n token,\n body: data,\n });\n },\n\n unlinkAuthMethod(token: string, id: string) {\n return request<{ success: true }>(`/users/me/auth-methods/${id}`, {\n method: 'DELETE',\n token,\n });\n },\n\n getWallets(token: string) {\n return request<Array<{ id: string; userId: string; chain: string; address: string; label: string | null; isPrimary: boolean; verifiedAt: string | null; lastUsedAt: string | null }>>(\n '/users/me/wallets',\n { token },\n );\n },\n\n updateWallet(token: string, id: string, data: { label?: string; isPrimary?: boolean }) {\n return request<{ id: string; userId: string; chain: string; address: string; label: string | null; isPrimary: boolean; verifiedAt: string | null; lastUsedAt: string | null }>(\n `/users/me/wallets/${id}`,\n { method: 'PATCH', token, body: data },\n );\n },\n\n getSessions(token: string) {\n return request<Array<{ id: string; createdAt: string; expiresAt: string; lastActiveAt: string; deviceInfo: Record<string, unknown> | null; ipAddress: string }>>(\n '/users/me/sessions',\n { token },\n );\n },\n\n revokeSession(token: string, id: string) {\n return request<{ success: true }>(`/users/me/sessions/${id}`, {\n method: 'DELETE',\n token,\n });\n },\n };\n}\n\nexport type ApiClient = ReturnType<typeof createApiClient>;\n","const TOKEN_KEY = 'fc_access_token';\n\nexport function getStoredToken(): string | null {\n try {\n return localStorage.getItem(TOKEN_KEY);\n } catch {\n return null;\n }\n}\n\nexport function setStoredToken(token: string): void {\n try {\n localStorage.setItem(TOKEN_KEY, token);\n } catch {\n // SSR or storage unavailable\n }\n}\n\nexport function removeStoredToken(): void {\n try {\n localStorage.removeItem(TOKEN_KEY);\n } catch {\n // SSR or storage unavailable\n }\n}\n\ninterface DecodedJWT {\n sub: string;\n tid?: string;\n scopes: string[];\n iat?: number;\n exp?: number;\n}\n\nexport function decodeJWT(token: string): DecodedJWT | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));\n return payload as DecodedJWT;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns milliseconds until 80% of the token's TTL has elapsed.\n * Returns null if the token cannot be decoded or has no exp.\n */\nexport function getRefreshDelay(token: string): number | null {\n const decoded = decodeJWT(token);\n if (!decoded?.exp || !decoded.iat) return null;\n const ttl = (decoded.exp - decoded.iat) * 1000;\n const elapsed = Date.now() - decoded.iat * 1000;\n const delay = ttl * 0.8 - elapsed;\n return delay > 0 ? delay : 0;\n}\n","import { useContext } from 'react';\nimport { ForgeConnectContext, type ForgeConnectContextValue } from '../context';\n\nexport function useForgeConnect(): ForgeConnectContextValue {\n const ctx = useContext(ForgeConnectContext);\n if (!ctx) {\n throw new Error('useForgeConnect must be used within a <ForgeConnectProvider>');\n }\n return ctx;\n}\n","import { useEffect, useRef, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface ModalOverlayProps {\n isOpen: boolean;\n onClose: () => void;\n children: ReactNode;\n}\n\nexport function ModalOverlay({ isOpen, onClose, children }: ModalOverlayProps) {\n const overlayRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKeyDown);\n document.body.style.overflow = 'hidden';\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = '';\n };\n }, [isOpen, onClose]);\n\n if (!isOpen) return null;\n\n const handleBackdropClick = (e: React.MouseEvent) => {\n if (e.target === overlayRef.current) onClose();\n };\n\n return createPortal(\n <div className=\"fc-overlay\" ref={overlayRef} onClick={handleBackdropClick}>\n <div className=\"fc-modal\" role=\"dialog\" aria-modal=\"true\">\n <button className=\"fc-modal-close\" onClick={onClose} aria-label=\"Close\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M15 5L5 15M5 5l10 10\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n {children}\n </div>\n </div>,\n document.body,\n );\n}\n","import { useState, type FormEvent } from 'react';\nimport { useForgeConnect } from '../../hooks/use-forge-connect';\n\nexport function EmailLoginForm() {\n const { loginWithEmail, setModalStep } = useForgeConnect();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n try {\n await loginWithEmail(email, password);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Login failed');\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Sign in with email</h3>\n <form onSubmit={handleSubmit} className=\"fc-form\">\n <label className=\"fc-label\">\n Email\n <input\n type=\"email\"\n className=\"fc-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n autoComplete=\"email\"\n />\n </label>\n <label className=\"fc-label\">\n Password\n <input\n type=\"password\"\n className=\"fc-input\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"Enter your password\"\n required\n autoComplete=\"current-password\"\n minLength={8}\n />\n </label>\n {error && <p className=\"fc-error\">{error}</p>}\n <button type=\"submit\" className=\"fc-btn fc-btn-primary\" disabled={loading}>\n {loading ? 'Signing in...' : 'Sign in'}\n </button>\n </form>\n <p className=\"fc-switch\">\n Don't have an account?{' '}\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('email-register')}>\n Sign up\n </button>\n </p>\n </div>\n );\n}\n\nexport function EmailRegisterForm() {\n const { register, setModalStep } = useForgeConnect();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [error, setError] = useState('');\n const [success, setSuccess] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n try {\n await register(email, password, displayName || undefined);\n setSuccess(true);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Registration failed');\n } finally {\n setLoading(false);\n }\n };\n\n if (success) {\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Check your email</h3>\n <p className=\"fc-text\">We sent a verification link to <strong>{email}</strong>. Click it to activate your account, then sign in.</p>\n <button type=\"button\" className=\"fc-btn fc-btn-secondary\" onClick={() => setModalStep('email-login')}>\n Back to sign in\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Create an account</h3>\n <form onSubmit={handleSubmit} className=\"fc-form\">\n <label className=\"fc-label\">\n Display name\n <input\n type=\"text\"\n className=\"fc-input\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n placeholder=\"Your name\"\n autoComplete=\"name\"\n />\n </label>\n <label className=\"fc-label\">\n Email\n <input\n type=\"email\"\n className=\"fc-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n autoComplete=\"email\"\n />\n </label>\n <label className=\"fc-label\">\n Password\n <input\n type=\"password\"\n className=\"fc-input\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"8+ characters\"\n required\n autoComplete=\"new-password\"\n minLength={8}\n />\n </label>\n {error && <p className=\"fc-error\">{error}</p>}\n <button type=\"submit\" className=\"fc-btn fc-btn-primary\" disabled={loading}>\n {loading ? 'Creating account...' : 'Create account'}\n </button>\n </form>\n <p className=\"fc-switch\">\n Already have an account?{' '}\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('email-login')}>\n Sign in\n </button>\n </p>\n </div>\n );\n}\n","import { useState, useRef, type FormEvent, type KeyboardEvent, type ClipboardEvent } from 'react';\nimport { useForgeConnect } from '../../hooks/use-forge-connect';\n\nexport function EmailOtpForm() {\n const { sendOtp, verifyOtp, setModalStep } = useForgeConnect();\n const [email, setEmail] = useState('');\n const [code, setCode] = useState(['', '', '', '', '', '']);\n const [step, setStep] = useState<'email' | 'code'>('email');\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n\n const handleSendCode = async (e: FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n try {\n await sendOtp(email);\n setStep('code');\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Failed to send code');\n } finally {\n setLoading(false);\n }\n };\n\n const handleVerify = async (digits: string[]) => {\n const codeStr = digits.join('');\n if (codeStr.length !== 6) return;\n setError('');\n setLoading(true);\n try {\n await verifyOtp(email, codeStr);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Invalid code');\n setLoading(false);\n }\n };\n\n const handleDigitChange = (index: number, value: string) => {\n if (!/^\\d*$/.test(value)) return;\n const digit = value.slice(-1);\n const newCode = [...code];\n newCode[index] = digit;\n setCode(newCode);\n\n if (digit && index < 5) {\n inputRefs.current[index + 1]?.focus();\n }\n\n if (newCode.every((d) => d !== '')) {\n handleVerify(newCode);\n }\n };\n\n const handleKeyDown = (index: number, e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Backspace' && !code[index] && index > 0) {\n inputRefs.current[index - 1]?.focus();\n }\n };\n\n const handlePaste = (e: ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n const pasted = e.clipboardData.getData('text').replace(/\\D/g, '').slice(0, 6);\n if (!pasted) return;\n const newCode = [...code];\n for (let i = 0; i < pasted.length; i++) {\n newCode[i] = pasted[i];\n }\n setCode(newCode);\n if (newCode.every((d) => d !== '')) {\n handleVerify(newCode);\n }\n };\n\n if (step === 'email') {\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Passwordless sign in</h3>\n <form onSubmit={handleSendCode} className=\"fc-form\">\n <label className=\"fc-label\">\n Email\n <input\n type=\"email\"\n className=\"fc-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n autoComplete=\"email\"\n />\n </label>\n {error && <p className=\"fc-error\">{error}</p>}\n <button type=\"submit\" className=\"fc-btn fc-btn-primary\" disabled={loading}>\n {loading ? 'Sending...' : 'Send code'}\n </button>\n </form>\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('method-select')}>\n Back\n </button>\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Enter verification code</h3>\n <p className=\"fc-text\">We sent a 6-digit code to <strong>{email}</strong></p>\n <div className=\"fc-otp-inputs\">\n {code.map((digit, i) => (\n <input\n key={i}\n ref={(el) => { inputRefs.current[i] = el; }}\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={1}\n className=\"fc-otp-digit\"\n value={digit}\n onChange={(e) => handleDigitChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={i === 0 ? handlePaste : undefined}\n autoFocus={i === 0}\n />\n ))}\n </div>\n {error && <p className=\"fc-error\">{error}</p>}\n {loading && <p className=\"fc-text\">Verifying...</p>}\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => { setStep('email'); setCode(['', '', '', '', '', '']); setError(''); }}>\n Use a different email\n </button>\n </p>\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useForgeConnect } from '../../hooks/use-forge-connect';\n\n// Type definition for the wallet adapter hook — avoids hard import\ninterface WalletContext {\n publicKey: { toBase58(): string } | null;\n signMessage: ((message: Uint8Array) => Promise<Uint8Array>) | undefined;\n wallets: Array<{ adapter: { name: string; icon: string; connected: boolean }; readyState: string }>;\n select: (name: string) => void;\n connect: () => Promise<void>;\n}\n\n/**\n * Attempts to import `@solana/wallet-adapter-react` at runtime.\n * Returns the `useWallet` hook if available, undefined otherwise.\n */\nfunction tryGetUseWallet(): (() => WalletContext) | undefined {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@solana/wallet-adapter-react');\n return mod.useWallet;\n } catch {\n return undefined;\n }\n}\n\nconst resolvedUseWallet = tryGetUseWallet();\n\nexport function WalletConnectForm() {\n const { setModalStep } = useForgeConnect();\n\n if (resolvedUseWallet) {\n return <WalletAdapterFlow useWallet={resolvedUseWallet} />;\n }\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Connect wallet</h3>\n <p className=\"fc-text\">\n Install a Solana wallet extension (Phantom, Solflare, etc.) and ensure{' '}\n <code>@solana/wallet-adapter-react</code> is configured in your app.\n </p>\n <p className=\"fc-text fc-text-muted\">\n Wallet connection requires the Solana wallet adapter provider in your app.\n </p>\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('method-select')}>\n Back\n </button>\n </p>\n </div>\n );\n}\n\nfunction WalletAdapterFlow({ useWallet }: { useWallet: () => WalletContext }) {\n const { loginWithWallet, setModalStep } = useForgeConnect();\n const wallet = useWallet();\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n\n const handleConnect = async () => {\n if (!wallet.publicKey || !wallet.signMessage) {\n setError('Please connect your wallet first');\n return;\n }\n setError('');\n setLoading(true);\n try {\n await loginWithWallet(\n wallet.publicKey.toBase58(),\n wallet.signMessage,\n 'solana',\n );\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Wallet verification failed');\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className=\"fc-tab\">\n <h3 className=\"fc-tab-title\">Connect wallet</h3>\n {wallet.publicKey ? (\n <>\n <p className=\"fc-text fc-wallet-address\">\n {wallet.publicKey.toBase58().slice(0, 4)}...{wallet.publicKey.toBase58().slice(-4)}\n </p>\n {error && <p className=\"fc-error\">{error}</p>}\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-primary\"\n onClick={handleConnect}\n disabled={loading}\n >\n {loading ? 'Signing...' : 'Sign to verify'}\n </button>\n </>\n ) : (\n <>\n <div className=\"fc-wallet-list\">\n {wallet.wallets\n .filter((w) => w.readyState === 'Installed')\n .map((w) => (\n <button\n key={w.adapter.name}\n type=\"button\"\n className=\"fc-btn fc-btn-wallet\"\n onClick={async () => {\n wallet.select(w.adapter.name as any);\n try {\n await wallet.connect();\n } catch {\n setError('Failed to connect wallet');\n }\n }}\n >\n <img src={w.adapter.icon} alt=\"\" className=\"fc-wallet-icon\" />\n {w.adapter.name}\n </button>\n ))}\n </div>\n {wallet.wallets.filter((w) => w.readyState === 'Installed').length === 0 && (\n <p className=\"fc-text\">No wallets detected. Install a Solana wallet extension.</p>\n )}\n {error && <p className=\"fc-error\">{error}</p>}\n </>\n )}\n <p className=\"fc-switch\">\n <button type=\"button\" className=\"fc-link\" onClick={() => setModalStep('method-select')}>\n Back\n </button>\n </p>\n </div>\n );\n}\n","import { useForgeConnect } from '../../hooks/use-forge-connect';\nimport type { OAuthProvider } from '../../types';\n\nconst PROVIDER_INFO: Record<OAuthProvider, { label: string; icon: string }> = {\n google: {\n label: 'Google',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" fill=\"#4285F4\"/><path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/><path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/><path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/></svg>',\n },\n discord: {\n label: 'Discord',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z\" fill=\"#5865F2\"/></svg>',\n },\n twitter: {\n label: 'Twitter',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" fill=\"currentColor\"/></svg>',\n },\n apple: {\n label: 'Apple',\n icon: '<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path d=\"M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.52-3.23 0-1.44.64-2.2.45-3.06-.4C3.79 16.17 4.36 9.02 8.8 8.78c1.27.06 2.15.72 2.91.76.93-.19 1.82-.88 2.83-.8 1.21.1 2.12.58 2.72 1.49-2.46 1.48-1.88 4.73.52 5.64-.42 1.13-.98 2.24-1.73 3.41zM12.03 8.7c-.12-2.35 1.82-4.38 4.04-4.54.29 2.56-2.34 4.68-4.04 4.54z\" fill=\"currentColor\"/></svg>',\n },\n};\n\nexport function OAuthButtons() {\n const { config, loginWithOAuth } = useForgeConnect();\n const providers = config.oauthProviders ?? [];\n\n if (providers.length === 0) return null;\n\n return (\n <div className=\"fc-oauth-buttons\">\n {providers.map((provider) => {\n const info = PROVIDER_INFO[provider];\n return (\n <button\n key={provider}\n type=\"button\"\n className=\"fc-btn fc-btn-oauth\"\n onClick={() => loginWithOAuth(provider)}\n >\n <span className=\"fc-oauth-icon\" dangerouslySetInnerHTML={{ __html: info.icon }} />\n Continue with {info.label}\n </button>\n );\n })}\n </div>\n );\n}\n","import { useForgeConnect } from '../hooks/use-forge-connect';\nimport { ModalOverlay } from './modal-overlay';\nimport { EmailLoginForm, EmailRegisterForm } from './tabs/email-password';\nimport { EmailOtpForm } from './tabs/email-otp';\nimport { WalletConnectForm } from './tabs/wallet-connect';\nimport { OAuthButtons } from './tabs/oauth-buttons';\n\nexport function LoginModal() {\n const { modal, closeModal, setModalStep, config } = useForgeConnect();\n\n const renderStep = () => {\n switch (modal.step) {\n case 'email-login':\n return <EmailLoginForm />;\n case 'email-register':\n return <EmailRegisterForm />;\n case 'email-otp':\n return <EmailOtpForm />;\n case 'wallet-connect':\n return <WalletConnectForm />;\n case 'method-select':\n default:\n return <MethodSelect />;\n }\n };\n\n return (\n <ModalOverlay isOpen={modal.isOpen} onClose={closeModal}>\n <div\n className=\"fc-modal-content\"\n style={{\n '--fc-accent': config.appearance?.accentColor ?? '#8b5cf6',\n } as React.CSSProperties}\n data-theme={config.appearance?.theme ?? 'light'}\n >\n {config.appearance?.logo && (\n <img src={config.appearance.logo} alt=\"\" className=\"fc-logo\" />\n )}\n <h2 className=\"fc-modal-title\">\n {config.appearance?.title ?? 'Sign in'}\n </h2>\n {renderStep()}\n </div>\n </ModalOverlay>\n );\n}\n\nfunction MethodSelect() {\n const { setModalStep, config } = useForgeConnect();\n\n return (\n <div className=\"fc-method-select\">\n <OAuthButtons />\n\n {(config.oauthProviders?.length ?? 0) > 0 && (\n <div className=\"fc-divider\">\n <span>or</span>\n </div>\n )}\n\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-method\"\n onClick={() => setModalStep('email-login')}\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" className=\"fc-method-icon\">\n <rect x=\"2\" y=\"4\" width=\"16\" height=\"12\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M2 6l8 5 8-5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n Continue with email\n </button>\n\n {config.passwordlessLogin !== false && (\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-method\"\n onClick={() => setModalStep('email-otp')}\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" className=\"fc-method-icon\">\n <rect x=\"3\" y=\"6\" width=\"14\" height=\"9\" rx=\"1.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <circle cx=\"6.5\" cy=\"10.5\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"10\" cy=\"10.5\" r=\"1\" fill=\"currentColor\" />\n <circle cx=\"13.5\" cy=\"10.5\" r=\"1\" fill=\"currentColor\" />\n </svg>\n Continue with code\n </button>\n )}\n\n {config.walletLogin !== false && (\n <button\n type=\"button\"\n className=\"fc-btn fc-btn-method\"\n onClick={() => setModalStep('wallet-connect')}\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" className=\"fc-method-icon\">\n <rect x=\"2\" y=\"5\" width=\"16\" height=\"11\" rx=\"2\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <rect x=\"13\" y=\"9\" width=\"5\" height=\"3\" rx=\"1\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n </svg>\n Continue with wallet\n </button>\n )}\n </div>\n );\n}\n","import { useForgeConnect } from '../hooks/use-forge-connect';\n\ninterface LoginButtonProps {\n className?: string;\n label?: string;\n}\n\nexport function LoginButton({ className, label }: LoginButtonProps) {\n const { auth, openModal, logout } = useForgeConnect();\n\n if (auth.status === 'loading') {\n return (\n <button type=\"button\" className={className ?? 'fc-btn fc-btn-login'} disabled>\n Loading...\n </button>\n );\n }\n\n if (auth.status === 'authenticated') {\n return (\n <button type=\"button\" className={className ?? 'fc-btn fc-btn-login'} onClick={logout}>\n {label ?? 'Log out'}\n </button>\n );\n }\n\n return (\n <button type=\"button\" className={className ?? 'fc-btn fc-btn-login'} onClick={openModal}>\n {label ?? 'Sign in'}\n </button>\n );\n}\n","import { useState, useCallback } from 'react';\nimport { useForgeConnect } from './use-forge-connect';\nimport type { AuthMethod } from '../types';\n\nexport function useUser() {\n const { auth, api, getAccessToken } = useForgeConnect();\n const [authMethods, setAuthMethods] = useState<AuthMethod[] | null>(null);\n const [loading, setLoading] = useState(false);\n\n const updateProfile = useCallback(\n async (data: { displayName?: string; avatarUrl?: string }) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n return api.updateMe(token, data);\n },\n [api, getAccessToken],\n );\n\n const fetchAuthMethods = useCallback(async () => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n setLoading(true);\n try {\n const methods = await api.getAuthMethods(token);\n setAuthMethods(methods as AuthMethod[]);\n return methods;\n } finally {\n setLoading(false);\n }\n }, [api, getAccessToken]);\n\n const linkAuthMethod = useCallback(\n async (data: { provider: string; email?: string; password?: string; challengeId?: string; signature?: string; walletAddress?: string }) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.linkAuthMethod(token, data);\n await fetchAuthMethods();\n },\n [api, getAccessToken, fetchAuthMethods],\n );\n\n const unlinkAuthMethod = useCallback(\n async (id: string) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.unlinkAuthMethod(token, id);\n await fetchAuthMethods();\n },\n [api, getAccessToken, fetchAuthMethods],\n );\n\n return {\n user: auth.user,\n authMethods,\n loading,\n updateProfile,\n fetchAuthMethods,\n linkAuthMethod,\n unlinkAuthMethod,\n };\n}\n","import { useState, useCallback } from 'react';\nimport { useForgeConnect } from './use-forge-connect';\nimport type { Wallet } from '../types';\n\nexport function useWallets() {\n const { api, getAccessToken } = useForgeConnect();\n const [wallets, setWallets] = useState<Wallet[] | null>(null);\n const [loading, setLoading] = useState(false);\n\n const fetchWallets = useCallback(async () => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n setLoading(true);\n try {\n const data = await api.getWallets(token);\n setWallets(data as Wallet[]);\n return data;\n } finally {\n setLoading(false);\n }\n }, [api, getAccessToken]);\n\n const updateWallet = useCallback(\n async (id: string, data: { label?: string; isPrimary?: boolean }) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.updateWallet(token, id, data);\n await fetchWallets();\n },\n [api, getAccessToken, fetchWallets],\n );\n\n return {\n wallets,\n loading,\n fetchWallets,\n updateWallet,\n };\n}\n","import { useState, useCallback } from 'react';\nimport { useForgeConnect } from './use-forge-connect';\nimport type { Session } from '../types';\n\nexport function useSessions() {\n const { api, getAccessToken } = useForgeConnect();\n const [sessions, setSessions] = useState<Session[] | null>(null);\n const [loading, setLoading] = useState(false);\n\n const fetchSessions = useCallback(async () => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n setLoading(true);\n try {\n const data = await api.getSessions(token);\n setSessions(data as Session[]);\n return data;\n } finally {\n setLoading(false);\n }\n }, [api, getAccessToken]);\n\n const revokeSession = useCallback(\n async (id: string) => {\n const token = getAccessToken();\n if (!token) throw new Error('Not authenticated');\n await api.revokeSession(token, id);\n await fetchSessions();\n },\n [api, getAccessToken, fetchSessions],\n );\n\n return {\n sessions,\n loading,\n fetchSessions,\n revokeSession,\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react","import_react"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
type OAuthProvider = 'google' | 'discord' | 'twitter' | 'apple';
|
|
6
|
+
type Chain = 'solana' | 'ethereum';
|
|
7
|
+
interface ForgeConnectConfig {
|
|
8
|
+
/** Base URL of the ForgeConnect API */
|
|
9
|
+
apiUrl: string;
|
|
10
|
+
/** OAuth providers to enable */
|
|
11
|
+
oauthProviders?: OAuthProvider[];
|
|
12
|
+
/** Enable wallet login */
|
|
13
|
+
walletLogin?: boolean;
|
|
14
|
+
/** Enable passwordless (OTP) login */
|
|
15
|
+
passwordlessLogin?: boolean;
|
|
16
|
+
/** Appearance customization */
|
|
17
|
+
appearance?: AppearanceConfig;
|
|
18
|
+
}
|
|
19
|
+
interface AppearanceConfig {
|
|
20
|
+
theme?: 'light' | 'dark';
|
|
21
|
+
accentColor?: string;
|
|
22
|
+
logo?: string;
|
|
23
|
+
title?: string;
|
|
24
|
+
}
|
|
25
|
+
interface User {
|
|
26
|
+
id: string;
|
|
27
|
+
displayName: string | null;
|
|
28
|
+
avatarUrl: string | null;
|
|
29
|
+
primaryEmail: string | null;
|
|
30
|
+
status: string;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
updatedAt: string;
|
|
33
|
+
}
|
|
34
|
+
type AuthProvider = 'email' | 'google' | 'twitter' | 'discord' | 'apple' | 'solana_wallet' | 'ethereum_wallet';
|
|
35
|
+
interface AuthMethod {
|
|
36
|
+
id: string;
|
|
37
|
+
provider: AuthProvider;
|
|
38
|
+
providerId: string;
|
|
39
|
+
isVerified: boolean;
|
|
40
|
+
verifiedAt: string | null;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
}
|
|
43
|
+
interface Wallet {
|
|
44
|
+
id: string;
|
|
45
|
+
userId: string;
|
|
46
|
+
chain: Chain;
|
|
47
|
+
address: string;
|
|
48
|
+
label: string | null;
|
|
49
|
+
isPrimary: boolean;
|
|
50
|
+
verifiedAt: string | null;
|
|
51
|
+
lastUsedAt: string | null;
|
|
52
|
+
}
|
|
53
|
+
interface Session {
|
|
54
|
+
id: string;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
expiresAt: string;
|
|
57
|
+
lastActiveAt: string;
|
|
58
|
+
deviceInfo: Record<string, unknown> | null;
|
|
59
|
+
ipAddress: string;
|
|
60
|
+
}
|
|
61
|
+
type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated';
|
|
62
|
+
interface AuthState {
|
|
63
|
+
status: AuthStatus;
|
|
64
|
+
user: User | null;
|
|
65
|
+
accessToken: string | null;
|
|
66
|
+
}
|
|
67
|
+
type ModalStep = 'method-select' | 'email-login' | 'email-register' | 'email-otp' | 'wallet-connect' | 'oauth';
|
|
68
|
+
interface ModalState {
|
|
69
|
+
isOpen: boolean;
|
|
70
|
+
step: ModalStep;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface ForgeConnectProviderProps {
|
|
74
|
+
config: ForgeConnectConfig;
|
|
75
|
+
children: ReactNode;
|
|
76
|
+
/** Called when user successfully authenticates */
|
|
77
|
+
onLogin?: (user: User) => void;
|
|
78
|
+
/** Called when user logs out */
|
|
79
|
+
onLogout?: () => void;
|
|
80
|
+
}
|
|
81
|
+
declare function ForgeConnectProvider({ config, children, onLogin, onLogout }: ForgeConnectProviderProps): react_jsx_runtime.JSX.Element;
|
|
82
|
+
|
|
83
|
+
interface LoginButtonProps {
|
|
84
|
+
className?: string;
|
|
85
|
+
label?: string;
|
|
86
|
+
}
|
|
87
|
+
declare function LoginButton({ className, label }: LoginButtonProps): react_jsx_runtime.JSX.Element;
|
|
88
|
+
|
|
89
|
+
declare function LoginModal(): react_jsx_runtime.JSX.Element;
|
|
90
|
+
|
|
91
|
+
interface ModalOverlayProps {
|
|
92
|
+
isOpen: boolean;
|
|
93
|
+
onClose: () => void;
|
|
94
|
+
children: ReactNode;
|
|
95
|
+
}
|
|
96
|
+
declare function ModalOverlay({ isOpen, onClose, children }: ModalOverlayProps): react.ReactPortal | null;
|
|
97
|
+
|
|
98
|
+
declare class ForgeConnectApiError extends Error {
|
|
99
|
+
readonly status: number;
|
|
100
|
+
readonly code: string;
|
|
101
|
+
constructor(status: number, code: string, message: string);
|
|
102
|
+
}
|
|
103
|
+
declare function createApiClient(apiUrl: string): {
|
|
104
|
+
register(email: string, password: string, displayName?: string): Promise<{
|
|
105
|
+
success: true;
|
|
106
|
+
}>;
|
|
107
|
+
login(email: string, password: string): Promise<{
|
|
108
|
+
accessToken: string;
|
|
109
|
+
user: {
|
|
110
|
+
id: string;
|
|
111
|
+
displayName: string | null;
|
|
112
|
+
email: string;
|
|
113
|
+
};
|
|
114
|
+
}>;
|
|
115
|
+
sendOtp(email: string): Promise<{
|
|
116
|
+
success: true;
|
|
117
|
+
}>;
|
|
118
|
+
verifyOtp(email: string, code: string): Promise<{
|
|
119
|
+
accessToken: string;
|
|
120
|
+
user: {
|
|
121
|
+
id: string;
|
|
122
|
+
email: string;
|
|
123
|
+
};
|
|
124
|
+
}>;
|
|
125
|
+
walletChallenge(walletAddress: string, chain?: string): Promise<{
|
|
126
|
+
challengeId: string;
|
|
127
|
+
nonce: string;
|
|
128
|
+
}>;
|
|
129
|
+
walletVerify(challengeId: string, signature: string, walletAddress: string): Promise<{
|
|
130
|
+
accessToken: string;
|
|
131
|
+
}>;
|
|
132
|
+
refresh(): Promise<{
|
|
133
|
+
accessToken: string;
|
|
134
|
+
}>;
|
|
135
|
+
logout(token: string): Promise<{
|
|
136
|
+
success: true;
|
|
137
|
+
}>;
|
|
138
|
+
logoutAll(token: string): Promise<{
|
|
139
|
+
success: true;
|
|
140
|
+
}>;
|
|
141
|
+
getMe(token: string): Promise<{
|
|
142
|
+
id: string;
|
|
143
|
+
displayName: string | null;
|
|
144
|
+
avatarUrl: string | null;
|
|
145
|
+
primaryEmail: string | null;
|
|
146
|
+
status: string;
|
|
147
|
+
createdAt: string;
|
|
148
|
+
updatedAt: string;
|
|
149
|
+
}>;
|
|
150
|
+
updateMe(token: string, data: {
|
|
151
|
+
displayName?: string;
|
|
152
|
+
avatarUrl?: string;
|
|
153
|
+
}): Promise<{
|
|
154
|
+
id: string;
|
|
155
|
+
displayName: string | null;
|
|
156
|
+
avatarUrl: string | null;
|
|
157
|
+
primaryEmail: string | null;
|
|
158
|
+
status: string;
|
|
159
|
+
createdAt: string;
|
|
160
|
+
updatedAt: string;
|
|
161
|
+
}>;
|
|
162
|
+
getAuthMethods(token: string): Promise<{
|
|
163
|
+
id: string;
|
|
164
|
+
provider: string;
|
|
165
|
+
providerId: string;
|
|
166
|
+
isVerified: boolean;
|
|
167
|
+
verifiedAt: string | null;
|
|
168
|
+
createdAt: string;
|
|
169
|
+
}[]>;
|
|
170
|
+
linkAuthMethod(token: string, data: {
|
|
171
|
+
provider: string;
|
|
172
|
+
email?: string;
|
|
173
|
+
password?: string;
|
|
174
|
+
challengeId?: string;
|
|
175
|
+
signature?: string;
|
|
176
|
+
walletAddress?: string;
|
|
177
|
+
}): Promise<{
|
|
178
|
+
success: true;
|
|
179
|
+
}>;
|
|
180
|
+
unlinkAuthMethod(token: string, id: string): Promise<{
|
|
181
|
+
success: true;
|
|
182
|
+
}>;
|
|
183
|
+
getWallets(token: string): Promise<{
|
|
184
|
+
id: string;
|
|
185
|
+
userId: string;
|
|
186
|
+
chain: string;
|
|
187
|
+
address: string;
|
|
188
|
+
label: string | null;
|
|
189
|
+
isPrimary: boolean;
|
|
190
|
+
verifiedAt: string | null;
|
|
191
|
+
lastUsedAt: string | null;
|
|
192
|
+
}[]>;
|
|
193
|
+
updateWallet(token: string, id: string, data: {
|
|
194
|
+
label?: string;
|
|
195
|
+
isPrimary?: boolean;
|
|
196
|
+
}): Promise<{
|
|
197
|
+
id: string;
|
|
198
|
+
userId: string;
|
|
199
|
+
chain: string;
|
|
200
|
+
address: string;
|
|
201
|
+
label: string | null;
|
|
202
|
+
isPrimary: boolean;
|
|
203
|
+
verifiedAt: string | null;
|
|
204
|
+
lastUsedAt: string | null;
|
|
205
|
+
}>;
|
|
206
|
+
getSessions(token: string): Promise<{
|
|
207
|
+
id: string;
|
|
208
|
+
createdAt: string;
|
|
209
|
+
expiresAt: string;
|
|
210
|
+
lastActiveAt: string;
|
|
211
|
+
deviceInfo: Record<string, unknown> | null;
|
|
212
|
+
ipAddress: string;
|
|
213
|
+
}[]>;
|
|
214
|
+
revokeSession(token: string, id: string): Promise<{
|
|
215
|
+
success: true;
|
|
216
|
+
}>;
|
|
217
|
+
};
|
|
218
|
+
type ApiClient = ReturnType<typeof createApiClient>;
|
|
219
|
+
|
|
220
|
+
interface ForgeConnectContextValue {
|
|
221
|
+
auth: AuthState;
|
|
222
|
+
modal: ModalState;
|
|
223
|
+
config: ForgeConnectConfig;
|
|
224
|
+
api: ApiClient;
|
|
225
|
+
loginWithEmail: (email: string, password: string) => Promise<void>;
|
|
226
|
+
register: (email: string, password: string, displayName?: string) => Promise<void>;
|
|
227
|
+
sendOtp: (email: string) => Promise<void>;
|
|
228
|
+
verifyOtp: (email: string, code: string) => Promise<void>;
|
|
229
|
+
loginWithWallet: (walletAddress: string, signMessage: (message: Uint8Array) => Promise<Uint8Array>, chain?: string) => Promise<void>;
|
|
230
|
+
loginWithOAuth: (provider: string) => void;
|
|
231
|
+
logout: () => Promise<void>;
|
|
232
|
+
logoutAll: () => Promise<void>;
|
|
233
|
+
openModal: () => void;
|
|
234
|
+
closeModal: () => void;
|
|
235
|
+
setModalStep: (step: ModalState['step']) => void;
|
|
236
|
+
getAccessToken: () => string | null;
|
|
237
|
+
}
|
|
238
|
+
declare const ForgeConnectContext: react.Context<ForgeConnectContextValue | null>;
|
|
239
|
+
|
|
240
|
+
declare function useForgeConnect(): ForgeConnectContextValue;
|
|
241
|
+
|
|
242
|
+
declare function useUser(): {
|
|
243
|
+
user: User | null;
|
|
244
|
+
authMethods: AuthMethod[] | null;
|
|
245
|
+
loading: boolean;
|
|
246
|
+
updateProfile: (data: {
|
|
247
|
+
displayName?: string;
|
|
248
|
+
avatarUrl?: string;
|
|
249
|
+
}) => Promise<{
|
|
250
|
+
id: string;
|
|
251
|
+
displayName: string | null;
|
|
252
|
+
avatarUrl: string | null;
|
|
253
|
+
primaryEmail: string | null;
|
|
254
|
+
status: string;
|
|
255
|
+
createdAt: string;
|
|
256
|
+
updatedAt: string;
|
|
257
|
+
}>;
|
|
258
|
+
fetchAuthMethods: () => Promise<{
|
|
259
|
+
id: string;
|
|
260
|
+
provider: string;
|
|
261
|
+
providerId: string;
|
|
262
|
+
isVerified: boolean;
|
|
263
|
+
verifiedAt: string | null;
|
|
264
|
+
createdAt: string;
|
|
265
|
+
}[]>;
|
|
266
|
+
linkAuthMethod: (data: {
|
|
267
|
+
provider: string;
|
|
268
|
+
email?: string;
|
|
269
|
+
password?: string;
|
|
270
|
+
challengeId?: string;
|
|
271
|
+
signature?: string;
|
|
272
|
+
walletAddress?: string;
|
|
273
|
+
}) => Promise<void>;
|
|
274
|
+
unlinkAuthMethod: (id: string) => Promise<void>;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
declare function useWallets(): {
|
|
278
|
+
wallets: Wallet[] | null;
|
|
279
|
+
loading: boolean;
|
|
280
|
+
fetchWallets: () => Promise<{
|
|
281
|
+
id: string;
|
|
282
|
+
userId: string;
|
|
283
|
+
chain: string;
|
|
284
|
+
address: string;
|
|
285
|
+
label: string | null;
|
|
286
|
+
isPrimary: boolean;
|
|
287
|
+
verifiedAt: string | null;
|
|
288
|
+
lastUsedAt: string | null;
|
|
289
|
+
}[]>;
|
|
290
|
+
updateWallet: (id: string, data: {
|
|
291
|
+
label?: string;
|
|
292
|
+
isPrimary?: boolean;
|
|
293
|
+
}) => Promise<void>;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
declare function useSessions(): {
|
|
297
|
+
sessions: Session[] | null;
|
|
298
|
+
loading: boolean;
|
|
299
|
+
fetchSessions: () => Promise<{
|
|
300
|
+
id: string;
|
|
301
|
+
createdAt: string;
|
|
302
|
+
expiresAt: string;
|
|
303
|
+
lastActiveAt: string;
|
|
304
|
+
deviceInfo: Record<string, unknown> | null;
|
|
305
|
+
ipAddress: string;
|
|
306
|
+
}[]>;
|
|
307
|
+
revokeSession: (id: string) => Promise<void>;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
export { type ApiClient, type AppearanceConfig, type AuthMethod, type AuthProvider, type AuthState, type AuthStatus, type Chain, ForgeConnectApiError, type ForgeConnectConfig, ForgeConnectContext, type ForgeConnectContextValue, ForgeConnectProvider, LoginButton, LoginModal, ModalOverlay, type ModalState, type ModalStep, type OAuthProvider, type Session, type User, type Wallet, createApiClient, useForgeConnect, useSessions, useUser, useWallets };
|