{"version":3,"file":"use-oauth-callback.cjs","names":[],"sources":["../../src/oauth/use-oauth-callback.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nexport interface UseOAuthCallbackOptions<T> {\n    /** Function that exchanges the provider response for an app session. Called once on mount. */\n    exchange: () => Promise<T>;\n    /** Fired with the result on success. Receives the value resolved by `exchange`. */\n    onSuccess?: (result: T) => void | Promise<void>;\n    /** Fired when `exchange` throws or rejects. */\n    onError?: (error: unknown) => void;\n}\n\nexport interface UseOAuthCallbackResult<T> {\n    /** `true` while the exchange promise is pending. */\n    loading: boolean;\n    /** Last resolved value, when `status === \"success\"`. */\n    data: T | null;\n    /** Last rejection reason, when `status === \"error\"`. */\n    error: unknown;\n    /** Aggregated state — `\"pending\"`, `\"success\"`, or `\"error\"`. */\n    status: \"pending\" | \"success\" | \"error\";\n}\n\n/**\n * Run an OAuth-callback \"exchange\" exactly once on mount. Designed for\n * `/callback` routes that receive provider redirects and need to swap a\n * code/token for an app session via the backend.\n *\n * Survives React StrictMode double-mounting in dev — uses a ref guard to\n * ensure `exchange` runs once.\n *\n * @example\n * function OAuthCallback() {\n *     const { loading, error } = useOAuthCallback({\n *         exchange: async () => {\n *             const code = new URLSearchParams(location.search).get(\"code\")!;\n *             return api.post(\"/auth/google/exchange\", { body: { code } });\n *         },\n *         onSuccess: ({ token, user }) => {\n *             useAuthStore.getState().setSession({ user, token });\n *             navigate(\"/dashboard\", { replace: true });\n *         },\n *         onError: () => navigate(\"/login?error=oauth\", { replace: true }),\n *     });\n *\n *     if (loading) return <Spinner />;\n *     if (error) return <ErrorState description=\"OAuth falhou\" />;\n *     return null;\n * }\n */\nexport function useOAuthCallback<T>(\n    options: UseOAuthCallbackOptions<T>,\n): UseOAuthCallbackResult<T> {\n    const { exchange, onSuccess, onError } = options;\n    const [data, setData] = useState<T | null>(null);\n    const [error, setError] = useState<unknown>(null);\n    const [status, setStatus] = useState<\"pending\" | \"success\" | \"error\">(\"pending\");\n    const ranRef = useRef<boolean>(false);\n\n    useEffect(() => {\n        if (ranRef.current) return;\n        ranRef.current = true;\n        let cancelled = false;\n        exchange()\n            .then((result) => {\n                if (cancelled) return;\n                setData(result);\n                setStatus(\"success\");\n                return onSuccess?.(result);\n            })\n            .catch((err) => {\n                if (cancelled) return;\n                setError(err);\n                setStatus(\"error\");\n                onError?.(err);\n            });\n        return () => {\n            cancelled = true;\n        };\n    }, [exchange, onSuccess, onError]);\n\n    return { loading: status === \"pending\", data, error, status };\n}\n"],"mappings":"uBAiDA,SAAgB,EACZ,EACyB,CACzB,GAAM,CAAE,WAAU,YAAW,WAAY,EACnC,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,CAAmB,IAAI,EACzC,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAkB,IAAI,EAC1C,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAA0C,SAAS,EACzE,GAAA,EAAS,EAAA,OAAA,CAAgB,EAAK,EAwBpC,OAtBA,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,EAAO,QAAS,OACpB,EAAO,QAAU,GACjB,IAAI,EAAY,GAchB,OAbA,EAAS,CAAC,CACL,KAAM,GAAW,CACV,MAGJ,OAFA,EAAQ,CAAM,EACd,EAAU,SAAS,EACZ,IAAY,CAAM,CAC7B,CAAC,CAAC,CACD,MAAO,GAAQ,CACR,IACJ,EAAS,CAAG,EACZ,EAAU,OAAO,EACjB,IAAU,CAAG,EACjB,CAAC,MACQ,CACT,EAAY,EAChB,CACJ,EAAG,CAAC,EAAU,EAAW,CAAO,CAAC,EAE1B,CAAE,QAAS,IAAW,UAAW,OAAM,QAAO,QAAO,CAChE"}