'use client' import { useMemo } from 'react' import { useDjangoCSRClient, Auth } from 'mizan/client/react' import { useAuthContext } from './AuthContext' import { createAPI, AllauthAPI, BrowserFormAction } from '../api' /** * Browser form action for OAuth redirects. * Creates and submits a form programmatically. */ const browserFormAction: BrowserFormAction = (action: string, data: Record) => { const form = document.createElement('form') form.method = 'POST' form.action = action for (const [key, value] of Object.entries(data)) { const input = document.createElement('input') input.type = 'hidden' input.name = key input.value = value form.appendChild(input) } document.body.appendChild(form) form.submit() } /** * Hook that returns the Allauth API with automatic auth refresh on relevant responses. * * Automatically triggers auth refresh when: * - 401 with flows (authentication required) * - 410 (session gone) * - 200 with is_authenticated (successful auth) */ export function useAllauthAPI(): AllauthAPI { const client = useDjangoCSRClient(Auth.SESSION) const { refresh } = useAuthContext() return useMemo(() => { const authRequest = async (method: string, path: string, data?: any, headers?: Record) => { const resp = await client.request(method, `/_allauth/browser/v1${path}`, data, headers) if (resp.status >= 500) { throw new Error(`Allauth request failed: ${resp.status} ${resp.statusText}`) } try { return await resp.json() } catch { throw new Error(`Allauth request failed: ${resp.status} ${resp.statusText}`) } } return createAPI( async (method, path, data?, headers?) => { const resp = await authRequest(method, path, { ...(data as object), client: 'browser' }, headers) // Auto-refresh auth state on relevant responses if (resp.status === 401 && resp.data?.flows) { refresh(resp) } else if ([401, 410].includes(resp.status) || (resp.status === 200 && resp.meta?.is_authenticated)) { refresh() } return resp }, browserFormAction ) }, [client, refresh]) }