{"mappings":"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","names":["React","requestJson","subscribeTalizenConfig","TalizenHttpError","TalizenAuthError","message","register","input","options","loginRequest","authListeners","currentUserState","authErrorState","isAuthInitialized","authSnapshot","readAuthSnapshot","authRequestId","isAuthConfigSubscriptionStarted","inflightRefresh","isSameSnapshot","a","b","emitAuthChange","next","listener","subscribeAuth","ensureAuthConfigSubscription","refreshAuthState","normalizeLoginInput","password","normalizeRegisterInput","name","isUnauthenticatedError","error","isSameAuthUser","requestId","runPromise","user","fetchCurrentUser","setAuthUser","useAuth","snapshot","optionsRef","refresh","loginAndRefresh","nextUser","registerAndRefresh","logoutAndRefresh","logoutRequest","updateProfileAndRefresh","profile","updateProfile","startVerification","confirmVerification","listAuthProviders","getOAuthLoginUrl","provider","url","loginWithOAuth","target"],"sources":["../esm/npm/talizen@0.2.55/node_modules/talizen/auth.js"],"sourcesContent":["import * as React from \"react\";\nimport { getTalizenConfig, requestJson, subscribeTalizenConfig, TalizenHttpError, } from \"./core.js\";\nexport class TalizenAuthError extends Error {\n    constructor(message) {\n        super(message);\n        this.name = \"TalizenAuthError\";\n    }\n}\nexport async function register(input, options) {\n    return requestJson(\"/auth/register\", {\n        method: \"POST\",\n        body: JSON.stringify(input),\n    }, options);\n}\nasync function loginRequest(input, options) {\n    return requestJson(\"/auth/login\", {\n        method: \"POST\",\n        body: JSON.stringify(input),\n    }, options);\n}\nconst authListeners = new Set();\nlet currentUserState = null;\nlet authErrorState = null;\nlet isAuthInitialized = false;\nlet authSnapshot = readAuthSnapshot();\nlet authRequestId = 0;\nlet isAuthConfigSubscriptionStarted = false;\nlet inflightRefresh = null;\nfunction readAuthSnapshot() {\n    return {\n        user: currentUserState,\n        // `loading` is derived, not tracked: the auth state is \"loading\" exactly\n        // until the first initialization resolves. Deriving it from\n        // `isAuthInitialized` means the pre-initialization window (first render,\n        // SSR, before useAuth's mount effect fires the bootstrap /auth/me) already\n        // reports `loading: true` — so a consumer guard like `!loading \u0026\u0026 !user`\n        // can never misread \"state unknown\" as \"signed out\" and redirect-loop.\n        loading: !isAuthInitialized,\n        error: authErrorState,\n        isAuthenticated: !!currentUserState,\n        isInitialized: isAuthInitialized,\n    };\n}\nfunction isSameSnapshot(a, b) {\n    return (a.user === b.user \u0026\u0026\n        a.loading === b.loading \u0026\u0026\n        a.error === b.error \u0026\u0026\n        a.isAuthenticated === b.isAuthenticated \u0026\u0026\n        a.isInitialized === b.isInitialized);\n}\nfunction emitAuthChange() {\n    const next = readAuthSnapshot();\n    // Skip notifying subscribers when nothing actually changed. Background\n    // refreshes that return the same user must not trigger re-renders, and this\n    // keeps the `authSnapshot` reference stable for useSyncExternalStore.\n    if (isSameSnapshot(authSnapshot, next))\n        return;\n    authSnapshot = next;\n    authListeners.forEach(listener =\u003e listener());\n}\nfunction subscribeAuth(listener) {\n    authListeners.add(listener);\n    return () =\u003e {\n        authListeners.delete(listener);\n    };\n}\nfunction ensureAuthConfigSubscription() {\n    if (isAuthConfigSubscriptionStarted)\n        return;\n    isAuthConfigSubscriptionStarted = true;\n    subscribeTalizenConfig(() =\u003e {\n        void refreshAuthState().catch(() =\u003e { });\n    });\n}\nfunction normalizeLoginInput(input, password) {\n    if (typeof input === \"string\") {\n        return {\n            account: input,\n            password: password ?? \"\",\n        };\n    }\n    return input;\n}\nfunction normalizeRegisterInput(input, password, name) {\n    if (typeof input === \"string\") {\n        return {\n            account: input,\n            email: input,\n            password: password ?? \"\",\n            name,\n        };\n    }\n    return input;\n}\nfunction isUnauthenticatedError(error) {\n    return error instanceof TalizenHttpError \u0026\u0026 error.status === 401;\n}\n// AuthUser is plain JSON response data, so serialize-compare is sufficient.\nfunction isSameAuthUser(a, b) {\n    if (a === b)\n        return true;\n    if (!a || !b)\n        return false;\n    return JSON.stringify(a) === JSON.stringify(b);\n}\nasync function refreshAuthState(options) {\n    // Coalesce concurrent refreshes. Multiple mounted consumers plus config\n    // change notifications would otherwise each fire their own /auth/me; share\n    // a single in-flight request instead.\n    if (inflightRefresh)\n        return inflightRefresh;\n    const requestId = authRequestId + 1;\n    authRequestId = requestId;\n    // `loading` is derived from `isAuthInitialized` (see readAuthSnapshot), so\n    // the pre-initialization snapshot already reports `loading: true` — there is\n    // nothing to toggle here. Background refreshes (mount of another consumer,\n    // config change, manual refresh) must NOT surface a loading state, otherwise\n    // a consumer that renders a spinner while `loading` is true unmounts and\n    // remounts its whole subtree on every refresh — re-running mount effects and\n    // re-fetching in a loop.\n    if (!isAuthInitialized \u0026\u0026 authErrorState !== null) {\n        authErrorState = null;\n        emitAuthChange();\n    }\n    let runPromise;\n    runPromise = (async () =\u003e {\n        try {\n            let user = await fetchCurrentUser(options);\n            if (authRequestId === requestId) {\n                // Keep the previous reference when the payload is unchanged so `user`\n                // stays stable for React dependency arrays.\n                if (isSameAuthUser(currentUserState, user)) {\n                    user = currentUserState;\n                }\n                currentUserState = user;\n                authErrorState = null;\n                isAuthInitialized = true;\n                emitAuthChange();\n            }\n            return user;\n        }\n        catch (error) {\n            if (authRequestId === requestId) {\n                currentUserState = null;\n                authErrorState = isUnauthenticatedError(error) ? null : error;\n                isAuthInitialized = true;\n                emitAuthChange();\n            }\n            if (isUnauthenticatedError(error)) {\n                return null;\n            }\n            throw error;\n        }\n        finally {\n            if (inflightRefresh === runPromise)\n                inflightRefresh = null;\n        }\n    })();\n    inflightRefresh = runPromise;\n    return runPromise;\n}\nfunction setAuthUser(user) {\n    // Invalidate any in-flight refresh so its late result cannot overwrite the\n    // authoritative login/logout/profile state.\n    authRequestId += 1;\n    inflightRefresh = null;\n    if (!isSameAuthUser(currentUserState, user)) {\n        currentUserState = user;\n    }\n    authErrorState = null;\n    isAuthInitialized = true;\n    emitAuthChange();\n}\n/**\n * Subscribe to the current auth user.\n *\n * The hook reloads `/auth/me` whenever `setTalizenConfig()` changes runtime\n * config, which lets preview auth headers update the page without remounting.\n *\n * The returned object and its `user` keep stable references until the auth\n * state actually changes, so both are safe to use in React dependency arrays.\n */\nexport function useAuth(options) {\n    const snapshot = React.useSyncExternalStore(subscribeAuth, () =\u003e authSnapshot, () =\u003e authSnapshot);\n    const optionsRef = React.useRef(options);\n    React.useEffect(() =\u003e {\n        optionsRef.current = options;\n    }, [options]);\n    const refresh = React.useCallback(async () =\u003e {\n        return refreshAuthState(optionsRef.current);\n    }, []);\n    React.useEffect(() =\u003e {\n        ensureAuthConfigSubscription();\n        void refresh().catch(() =\u003e { });\n    }, [refresh]);\n    const loginAndRefresh = React.useCallback(async (input, password) =\u003e {\n        const nextUser = await loginRequest(normalizeLoginInput(input, password), optionsRef.current);\n        setAuthUser(nextUser);\n        return nextUser;\n    }, []);\n    const registerAndRefresh = React.useCallback(async (input, password, name) =\u003e {\n        const nextUser = await register(normalizeRegisterInput(input, password, name), optionsRef.current);\n        setAuthUser(nextUser);\n        return nextUser;\n    }, []);\n    const logoutAndRefresh = React.useCallback(async () =\u003e {\n        await logoutRequest(optionsRef.current);\n        setAuthUser(null);\n    }, []);\n    const updateProfileAndRefresh = React.useCallback(async (profile) =\u003e {\n        const nextUser = await updateProfile(profile, optionsRef.current);\n        setAuthUser(nextUser);\n        return nextUser;\n    }, []);\n    return React.useMemo(() =\u003e ({\n        ...snapshot,\n        refresh,\n        login: loginAndRefresh,\n        register: registerAndRefresh,\n        logout: logoutAndRefresh,\n        updateProfile: updateProfileAndRefresh,\n    }), [snapshot, refresh, loginAndRefresh, registerAndRefresh, logoutAndRefresh, updateProfileAndRefresh]);\n}\nasync function logoutRequest(options) {\n    await requestJson(\"/auth/logout\", {\n        method: \"POST\",\n        body: JSON.stringify({}),\n    }, options);\n}\nasync function fetchCurrentUser(options) {\n    return requestJson(\"/auth/me\", { method: \"GET\" }, options);\n}\nexport async function updateProfile(profile, options) {\n    return requestJson(\"/auth/me/profile\", {\n        method: \"PUT\",\n        body: JSON.stringify({ profile }),\n    }, options);\n}\n/**\n * Send a verification code for `purpose`.\n *\n * This is not `ctx.email.sendCode`: the outcome of confirming this code is\n * recorded by the platform and consumed by auth, so it can gate registration.\n */\nexport async function startVerification(input, options) {\n    return requestJson(\"/auth/verification/start\", { method: \"POST\", body: JSON.stringify(input) }, options);\n}\n/**\n * Confirm the code. On success the platform stores a single-use proof and sets\n * an httpOnly cookie holding an opaque ticket.\n *\n * Nothing about the proof is returned to page code, and nothing needs to be:\n * pass no extra argument to `register` — the browser carries the proof\n * automatically, and the server checks it against the project's policy. A proof\n * is bound to this exact `to` and `purpose`, is single-use, and expires in ten\n * minutes.\n */\nexport async function confirmVerification(input, options) {\n    return requestJson(\"/auth/verification/confirm\", { method: \"POST\", body: JSON.stringify(input) }, options);\n}\nexport async function listAuthProviders(options) {\n    const response = await requestJson(\"/auth/provider_list\", { method: \"GET\" }, options);\n    return response.list ?? [];\n}\nexport async function getOAuthLoginUrl(provider, options) {\n    const url = new URL(\"/auth/oauth/login_url\", \"https://talizen.local\");\n    url.searchParams.set(\"provider\", provider);\n    if (options?.redirectUrl) {\n        url.searchParams.set(\"redirect_url\", options.redirectUrl);\n    }\n    const response = await requestJson(url.pathname + url.search, { method: \"GET\" }, options);\n    return response.url;\n}\nexport async function loginWithOAuth(provider, options) {\n    const target = await getOAuthLoginUrl(provider, options);\n    if (typeof window === \"undefined\" || !window.location) {\n        throw new TalizenAuthError(\"OAuth login requires a browser window.\");\n    }\n    window.location.href = target;\n}\n"],"version":3}
