@netlify/identity 0.3.0-alpha.7 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/environment.ts","../src/errors.ts","../src/cookies.ts","../src/nextjs.ts","../src/events.ts","../src/auth.ts","../src/user.ts","../src/config.ts","../src/account.ts","../src/admin.ts"],"sourcesContent":["export type { User } from './user.js'\nexport { getUser, isAuthenticated } from './user.js'\nexport { getIdentityConfig, getSettings } from './config.js'\nexport type { AuthCallback, AuthEvent } from './events.js'\nexport { AUTH_EVENTS, onAuthChange } from './events.js'\nexport type { CallbackResult } from './auth.js'\nexport { login, signup, logout, oauthLogin, handleAuthCallback, hydrateSession } from './auth.js'\nexport { AuthError, MissingIdentityError } from './errors.js'\nexport type {\n AdminUserUpdates,\n AppMetadata,\n AuthProvider,\n CreateUserParams,\n IdentityConfig,\n ListUsersOptions,\n Settings,\n UserUpdates,\n SignupData,\n} from './types.js'\nexport type { Admin } from './admin.js'\nexport {\n requestPasswordRecovery,\n recoverPassword,\n confirmEmail,\n acceptInvite,\n verifyEmailChange,\n updateUser,\n} from './account.js'\nexport { admin } from './admin.js'\n","/** The supported OAuth and authentication providers. */\nexport const AUTH_PROVIDERS = ['google', 'github', 'gitlab', 'bitbucket', 'facebook', 'saml', 'email'] as const\n\n/** A supported authentication provider name (e.g., `'google'`, `'github'`, `'email'`). */\nexport type AuthProvider = (typeof AUTH_PROVIDERS)[number]\n\n/**\n * Provider and role metadata stored in a user's `app_metadata` field.\n * GoTrue sets `provider` automatically on signup; `roles` controls authorization.\n * Additional keys may be present depending on your Identity configuration.\n *\n * @example\n * ```ts\n * const meta: AppMetadata = {\n * provider: 'github',\n * roles: ['admin'],\n * custom_claim: 'value',\n * }\n * ```\n */\nexport interface AppMetadata {\n provider: AuthProvider\n roles?: string[]\n [key: string]: unknown\n}\n\n/**\n * Identity endpoint configuration for the current environment.\n * In the browser, `url` is derived from `window.location.origin`.\n * On the server, `token` is the operator token for admin operations.\n */\nexport interface IdentityConfig {\n /** The GoTrue API endpoint URL (e.g., `https://example.com/.netlify/identity`). */\n url: string\n /** Operator token for server-side admin requests. Only available in Netlify Functions. */\n token?: string\n}\n\n/**\n * Project-level Identity settings returned by {@link getSettings}.\n * Reflects the configuration in your Netlify dashboard.\n */\nexport interface Settings {\n /** Whether new signups are auto-confirmed (no confirmation email sent). */\n autoconfirm: boolean\n /** Whether new signups are disabled entirely. */\n disableSignup: boolean\n /** Map of provider names to whether they are enabled. */\n providers: Record<AuthProvider, boolean>\n}\n\n/**\n * Fields accepted by {@link updateUser}. All fields are optional.\n * Pass `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).\n *\n * @example\n * ```ts\n * await updateUser({ data: { full_name: 'Jane Doe' } })\n * await updateUser({ email: 'new@example.com' })\n * await updateUser({ password: 'new-password' })\n * ```\n */\nexport interface UserUpdates {\n email?: string\n password?: string\n data?: Record<string, unknown>\n [key: string]: unknown\n}\n\n/**\n * User metadata passed during signup (e.g., `{ full_name: 'Jane Doe' }`).\n * Stored in the user's `user_metadata` field.\n */\nexport type SignupData = Record<string, unknown>\n\n/** GoTrue OAuth2 token response from the /token endpoint. */\nexport interface TokenResponse {\n access_token: string\n token_type: string\n expires_in: number\n refresh_token?: string\n}\n\n/**\n * Fields accepted by {@link admin.updateUser}. All fields are optional.\n *\n * Unlike {@link UserUpdates} (used by the self-service `updateUser`), admin updates\n * can set `role`, force-confirm a user, and write to `app_metadata`.\n *\n * @example\n * ```ts\n * await admin.updateUser(userId, {\n * role: 'editor',\n * confirm: true,\n * app_metadata: { plan: 'pro' },\n * })\n * ```\n */\nexport interface AdminUserUpdates {\n email?: string\n password?: string\n /** The user's role (e.g., `'admin'`, `'editor'`). */\n role?: string\n /** Set to `true` to force-confirm the user's email without sending a confirmation email. */\n confirm?: boolean\n /** Server-managed metadata. Only writable via admin operations. */\n app_metadata?: Record<string, unknown>\n /** User-managed metadata (display name, avatar, preferences, etc.). */\n user_metadata?: Record<string, unknown>\n [key: string]: unknown\n}\n\n/** GoTrue error response body. */\nexport interface GoTrueErrorBody {\n msg?: string\n error_description?: string\n}\n\n/**\n * Options for {@link admin.listUsers}. Only used on the server;\n * pagination is ignored in the browser (gotrue-js limitation).\n */\nexport interface ListUsersOptions {\n /** 1-based page number. */\n page?: number\n /** Number of users per page. */\n perPage?: number\n}\n\n/**\n * Parameters for {@link admin.createUser}.\n *\n * The optional `data` fields are spread as top-level attributes in the GoTrue\n * request body (not nested under `user_metadata`). Use this to set `app_metadata`,\n * `user_metadata`, `role`, or other GoTrue user fields at creation time.\n *\n * @example\n * ```ts\n * await admin.createUser({\n * email: 'jane@example.com',\n * password: 'secret',\n * data: { role: 'editor', user_metadata: { full_name: 'Jane Doe' } },\n * })\n * ```\n */\nexport interface CreateUserParams {\n email: string\n password: string\n /** Additional GoTrue user fields spread into the request body. */\n data?: Record<string, unknown>\n}\n\n/**\n * Cookie interface provided by the Netlify Functions runtime.\n * Used internally for server-side auth cookie management.\n */\nexport interface NetlifyCookies {\n get(name: string): string | undefined\n set(options: {\n name: string\n value: string\n httpOnly: boolean\n secure: boolean\n path: string\n sameSite: 'Strict' | 'Lax' | 'None'\n }): void\n delete(name: string): void\n}\n","import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\nimport { MissingIdentityError } from './errors.js'\n\nexport const IDENTITY_PATH = '/.netlify/identity'\n\nlet goTrueClient: GoTrue | null = null\nlet cachedApiUrl: string | null | undefined\nlet warnedMissingUrl = false\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.location !== 'undefined'\n\n/**\n * Discovers and caches the GoTrue API URL.\n *\n * Browser: uses `window.location.origin` + IDENTITY_PATH.\n * Server: reads from `globalThis.netlifyIdentityContext`.\n */\nconst discoverApiUrl = (): string | null => {\n if (cachedApiUrl !== undefined) return cachedApiUrl\n\n if (isBrowser()) {\n cachedApiUrl = `${window.location.origin}${IDENTITY_PATH}`\n } else {\n const identityContext = getIdentityContext()\n if (identityContext?.url) {\n cachedApiUrl = identityContext.url\n } else if (globalThis.Netlify?.context?.url) {\n cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href\n } else if (typeof process !== 'undefined' && process.env?.URL) {\n cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href\n }\n }\n\n return cachedApiUrl ?? null\n}\n\n/**\n * Returns (and lazily creates) a singleton gotrue-js client.\n * Returns `null` and logs a warning if no identity URL can be discovered.\n */\nexport const getGoTrueClient = (): GoTrue | null => {\n if (goTrueClient) return goTrueClient\n\n const apiUrl = discoverApiUrl()\n if (!apiUrl) {\n if (!warnedMissingUrl) {\n console.warn(\n '@netlify/identity: Could not determine the Identity endpoint URL. ' +\n 'Make sure your site has Netlify Identity enabled, or run your app with `netlify dev`.',\n )\n warnedMissingUrl = true\n }\n return null\n }\n\n goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: false })\n return goTrueClient\n}\n\n/**\n * Returns the singleton gotrue-js client, or throws if Identity is not configured.\n */\nexport const getClient = (): GoTrue => {\n const client = getGoTrueClient()\n if (!client) throw new MissingIdentityError()\n return client\n}\n\n/**\n * Reads the server-side identity context set by the Netlify bootstrap.\n * Returns `null` outside the Netlify serverless environment.\n */\nexport const getIdentityContext = (): IdentityConfig | null => {\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url) {\n return {\n url: identityContext.url,\n token: identityContext.token,\n }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href }\n }\n\n // Fallback: Netlify sets the URL env var on all deployed sites\n const siteUrl = typeof process !== 'undefined' ? process.env?.URL : undefined\n if (siteUrl) {\n return { url: new URL(IDENTITY_PATH, siteUrl).href }\n }\n\n return null\n}\n\n/** Reset cached state for tests. */\nexport const resetTestGoTrueClient = (): void => {\n goTrueClient = null\n cachedApiUrl = undefined\n warnedMissingUrl = false\n}\n","/**\n * Thrown by auth operations when something goes wrong: invalid credentials,\n * network failures, missing runtime context, etc.\n *\n * The `status` field contains the HTTP status code from GoTrue when available\n * (e.g., 401 for bad credentials, 422 for validation errors).\n * The `cause` field preserves the original error for debugging.\n *\n * @example\n * ```ts\n * try {\n * await login(email, password)\n * } catch (error) {\n * if (error instanceof AuthError) {\n * console.error(error.message, error.status)\n * }\n * }\n * ```\n */\nexport class AuthError extends Error {\n override name = 'AuthError'\n /** HTTP status code from GoTrue, if the error originated from an API response. */\n status?: number\n declare cause?: unknown\n\n constructor(message: string, status?: number, options?: { cause?: unknown }) {\n super(message)\n this.status = status\n if (options && 'cause' in options) {\n this.cause = options.cause\n }\n }\n\n static from(error: unknown): AuthError {\n if (error instanceof AuthError) return error\n const message = error instanceof Error ? error.message : String(error)\n return new AuthError(message, undefined, { cause: error })\n }\n}\n\n/**\n * Thrown when a function requires a gotrue-js client but Netlify Identity\n * is not configured (no endpoint URL could be discovered).\n *\n * This typically means the site does not have Identity enabled, or the app\n * is not running via `netlify dev` / deployed on Netlify.\n */\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Netlify Identity is not available.') {\n super(message)\n }\n}\n","import type { NetlifyCookies } from './types.js'\n\nexport const NF_JWT_COOKIE = 'nf_jwt'\nexport const NF_REFRESH_COOKIE = 'nf_refresh'\n\n/** Reads a cookie value from `document.cookie` by name. Returns `null` if not found or not in a browser. */\nexport const getCookie = (name: string): string | null => {\n if (typeof document === 'undefined') return null\n const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}=([^;]*)`))\n if (!match) return null\n try {\n return decodeURIComponent(match[1])\n } catch {\n return match[1]\n }\n}\n\n/** Sets the `nf_jwt` and (optionally) `nf_refresh` auth cookies via the Netlify runtime. */\nexport const setAuthCookies = (cookies: NetlifyCookies, accessToken: string, refreshToken?: string): void => {\n cookies.set({\n name: NF_JWT_COOKIE,\n value: accessToken,\n httpOnly: false,\n secure: true,\n path: '/',\n sameSite: 'Lax',\n })\n\n if (refreshToken) {\n // httpOnly: false because browser-side hydration (backgroundHydrate, hydrateSession)\n // reads nf_refresh via document.cookie to bootstrap the gotrue-js session.\n cookies.set({\n name: NF_REFRESH_COOKIE,\n value: refreshToken,\n httpOnly: false,\n secure: true,\n path: '/',\n sameSite: 'Lax',\n })\n }\n}\n\n/** Deletes both auth cookies via the Netlify runtime. */\nexport const deleteAuthCookies = (cookies: NetlifyCookies): void => {\n cookies.delete(NF_JWT_COOKIE)\n cookies.delete(NF_REFRESH_COOKIE)\n}\n\n/** Sets auth cookies via document.cookie (browser-side). No-op on the server. */\nexport const setBrowserAuthCookies = (accessToken: string, refreshToken?: string): void => {\n if (typeof document === 'undefined') return\n document.cookie = `${NF_JWT_COOKIE}=${encodeURIComponent(accessToken)}; path=/; secure; samesite=lax`\n if (refreshToken) {\n document.cookie = `${NF_REFRESH_COOKIE}=${encodeURIComponent(refreshToken)}; path=/; secure; samesite=lax`\n }\n}\n\n/** Deletes auth cookies via document.cookie (browser-side). No-op on the server. */\nexport const deleteBrowserAuthCookies = (): void => {\n if (typeof document === 'undefined') return\n document.cookie = `${NF_JWT_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`\n document.cookie = `${NF_REFRESH_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`\n}\n\n/** Reads a cookie from the server-side Netlify runtime. Returns `null` if not available. */\nexport const getServerCookie = (name: string): string | null => {\n const cookies = globalThis.Netlify?.context?.cookies\n if (!cookies || typeof cookies.get !== 'function') return null\n return cookies.get(name) ?? null\n}\n","// Minimal declaration so we can use require() without @types/node\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ndeclare const require: ((id: string) => any) | undefined\n\n/**\n * Calls `headers()` from `next/headers` if available, to opt Next.js RSC\n * routes into dynamic rendering. Without this, Next.js may statically\n * optimize pages that call functions in this package, caching the build-time result.\n *\n * Re-throws DynamicServerError so Next.js can catch it and switch to\n * dynamic rendering. Silently ignores if not in a Next.js environment.\n */\nlet nextHeadersFn: (() => unknown) | null | undefined\nexport const triggerNextjsDynamic = (): void => {\n if (nextHeadersFn === null) return\n\n if (nextHeadersFn === undefined) {\n try {\n if (typeof require === 'undefined') {\n nextHeadersFn = null\n return\n }\n const mod = require('next/headers')\n nextHeadersFn = mod.headers\n } catch {\n nextHeadersFn = null\n return\n }\n }\n\n const fn = nextHeadersFn\n if (!fn) return\n\n try {\n fn()\n } catch (e: unknown) {\n // Re-throw DynamicServerError so Next.js can opt into dynamic rendering.\n // These errors have a `digest` property containing 'DYNAMIC_SERVER_USAGE'\n // or a message about bailing out of prerendering.\n if (e instanceof Error && ('digest' in e || /bail\\s*out.*prerende/i.test(e.message))) {\n throw e\n }\n }\n}\n\n/** Reset cached state and optionally inject a headers function. Test use only. */\nexport const resetNextjsState = (headersFn?: (() => unknown) | null): void => {\n nextHeadersFn = headersFn === null ? null : (headersFn ?? undefined)\n}\n","import { getGoTrueClient, isBrowser } from './environment.js'\nimport { toUser, type User } from './user.js'\n\n/**\n * Constants for the auth events emitted by the library.\n * Use these instead of string literals when comparing event types.\n *\n * @example\n * ```ts\n * onAuthChange((event, user) => {\n * if (event === AUTH_EVENTS.LOGIN) console.log('Logged in:', user)\n * if (event === AUTH_EVENTS.RECOVERY) redirect('/reset-password')\n * })\n * ```\n */\nexport const AUTH_EVENTS = {\n LOGIN: 'login',\n LOGOUT: 'logout',\n TOKEN_REFRESH: 'token_refresh',\n USER_UPDATED: 'user_updated',\n RECOVERY: 'recovery',\n} as const\n\n/**\n * Union of all auth event names: `'login' | 'logout' | 'token_refresh' | 'user_updated' | 'recovery'`.\n * Passed as the first argument to {@link AuthCallback} subscribers.\n */\nexport type AuthEvent = (typeof AUTH_EVENTS)[keyof typeof AUTH_EVENTS]\n\n/**\n * Callback function signature for {@link onAuthChange} subscribers.\n * `user` is `null` on logout events.\n */\nexport type AuthCallback = (event: AuthEvent, user: User | null) => void\n\nconst GOTRUE_STORAGE_KEY = 'gotrue.user'\n\nconst listeners = new Set<AuthCallback>()\n\nexport const emitAuthEvent = (event: AuthEvent, user: User | null): void => {\n for (const listener of listeners) {\n try {\n listener(event, user)\n } catch {\n // Prevent one subscriber from breaking others\n }\n }\n}\n\nlet storageListenerAttached = false\n\nconst attachStorageListener = (): void => {\n if (storageListenerAttached || !isBrowser()) return\n storageListenerAttached = true\n\n window.addEventListener('storage', (event: StorageEvent) => {\n if (event.key !== GOTRUE_STORAGE_KEY) return\n\n if (event.newValue) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser()\n emitAuthEvent(AUTH_EVENTS.LOGIN, currentUser ? toUser(currentUser) : null)\n } else {\n emitAuthEvent(AUTH_EVENTS.LOGOUT, null)\n }\n })\n}\n\n/**\n * Subscribes to auth state changes (login, logout, token refresh, user updates,\n * and recovery). Returns an unsubscribe function. No-op on the server.\n *\n * The `'recovery'` event fires when {@link handleAuthCallback} processes a\n * password recovery token. The user is logged in but has not yet set a new\n * password. Redirect them to a password reset form and call\n * `updateUser({ password })` to complete the flow.\n */\nexport const onAuthChange = (callback: AuthCallback): (() => void) => {\n if (!isBrowser()) {\n return () => {}\n }\n\n listeners.add(callback)\n attachStorageListener()\n\n return () => {\n listeners.delete(callback)\n }\n}\n","import type GoTrue from 'gotrue-js'\nimport type { UserData } from 'gotrue-js'\nimport type { NetlifyCookies, SignupData, TokenResponse, GoTrueErrorBody } from './types.js'\nimport { toUser, decodeJwtPayload } from './user.js'\n\nimport { getClient, getIdentityContext, isBrowser, IDENTITY_PATH } from './environment.js'\nimport {\n getCookie,\n setAuthCookies,\n deleteAuthCookies,\n setBrowserAuthCookies,\n deleteBrowserAuthCookies,\n NF_JWT_COOKIE,\n NF_REFRESH_COOKIE,\n} from './cookies.js'\nimport { AuthError } from './errors.js'\nimport { AUTH_EVENTS, emitAuthEvent } from './events.js'\n\nconst getCookies = (): NetlifyCookies => {\n const cookies = globalThis.Netlify?.context?.cookies\n if (!cookies) {\n throw new AuthError('Server-side auth requires Netlify Functions runtime')\n }\n return cookies\n}\n\nconst getServerIdentityUrl = (): string => {\n const ctx = getIdentityContext()\n if (!ctx?.url) {\n throw new AuthError('Could not determine the Identity endpoint URL on the server')\n }\n return ctx.url\n}\n\n/** Persist the session to localStorage so it survives page reloads. */\nexport const persistSession = true\n\n/**\n * Logs in with email and password. Works in both browser and server contexts.\n *\n * On success, sets `nf_jwt` and `nf_refresh` cookies and returns the authenticated {@link User}.\n * In the browser, also emits a `'login'` event via {@link onAuthChange}.\n *\n * @throws {AuthError} On invalid credentials, network failure, or missing Netlify runtime.\n *\n * @remarks\n * In Next.js server actions, call `redirect()` **after** `login()` returns, not inside a\n * try/catch. Next.js implements `redirect()` by throwing a special error; wrapping it in\n * try/catch will swallow the redirect.\n *\n * @example\n * ```ts\n * // Next.js server action\n * const user = await login(email, password)\n * redirect('/dashboard') // after login, not inside try/catch\n * ```\n */\nexport const login = async (email: string, password: string): Promise<import('./user.js').User> => {\n if (!isBrowser()) {\n const identityUrl = getServerIdentityUrl()\n const cookies = getCookies()\n\n const body = new URLSearchParams({\n grant_type: 'password',\n username: email,\n password,\n })\n\n let res: Response\n try {\n res = await fetch(`${identityUrl}/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!res.ok) {\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || errorBody.error_description || `Login failed (${res.status})`, res.status)\n }\n\n const data = (await res.json()) as TokenResponse\n const accessToken = data.access_token\n\n let userRes: Response\n try {\n userRes = await fetch(`${identityUrl}/user`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!userRes.ok) {\n const errorBody = (await userRes.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || `Failed to fetch user data (${userRes.status})`, userRes.status)\n }\n\n const userData = (await userRes.json()) as UserData\n const user = toUser(userData)\n\n setAuthCookies(cookies, accessToken, data.refresh_token)\n\n return user\n }\n\n const client = getClient()\n\n try {\n const gotrueUser = await client.login(email, password, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token)\n const user = toUser(gotrueUser)\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Creates a new account. Works in both browser and server contexts.\n *\n * If autoconfirm is enabled in your Identity settings, the user is logged in immediately:\n * cookies are set and a `'login'` event is emitted. If autoconfirm is **disabled** (the default),\n * the user receives a confirmation email and must click the link before they can log in.\n * In that case, no cookies are set and no auth event is emitted.\n *\n * @throws {AuthError} On duplicate email, validation failure, network error, or missing Netlify runtime.\n */\nexport const signup = async (email: string, password: string, data?: SignupData): Promise<import('./user.js').User> => {\n if (!isBrowser()) {\n const identityUrl = getServerIdentityUrl()\n const cookies = getCookies()\n\n let res: Response\n try {\n res = await fetch(`${identityUrl}/signup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password, data }),\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!res.ok) {\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || `Signup failed (${res.status})`, res.status)\n }\n\n const responseData = (await res.json()) as UserData & Partial<TokenResponse>\n const user = toUser(responseData)\n\n if (responseData.confirmed_at) {\n const accessToken = responseData.access_token\n if (accessToken) {\n setAuthCookies(cookies, accessToken, responseData.refresh_token)\n }\n }\n\n return user\n }\n\n const client = getClient()\n\n try {\n const response = await client.signup(email, password, data)\n const user = toUser(response as UserData)\n if (response.confirmed_at) {\n const jwt = await (response as { jwt?: () => Promise<string> }).jwt?.()\n if (jwt) {\n const refreshToken = (response as { tokenDetails?: () => { refresh_token: string } | null }).tokenDetails?.()\n ?.refresh_token\n setBrowserAuthCookies(jwt, refreshToken)\n }\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n }\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Logs out the current user and clears the session. Works in both browser and server contexts.\n *\n * Always deletes `nf_jwt` and `nf_refresh` cookies, even if the server-side token\n * invalidation request fails. In the browser, emits a `'logout'` event via {@link onAuthChange}.\n *\n * @throws {AuthError} On missing Netlify runtime (server) or logout failure (browser).\n */\nexport const logout = async (): Promise<void> => {\n if (!isBrowser()) {\n const identityUrl = getServerIdentityUrl()\n const cookies = getCookies()\n\n const jwt = cookies.get(NF_JWT_COOKIE)\n if (jwt) {\n try {\n await fetch(`${identityUrl}/logout`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${jwt}` },\n })\n } catch {\n // Best-effort: token invalidation may fail, but we always clear cookies below\n }\n }\n\n deleteAuthCookies(cookies)\n return\n }\n\n const client = getClient()\n\n try {\n const currentUser = client.currentUser()\n if (currentUser) {\n await currentUser.logout()\n }\n deleteBrowserAuthCookies()\n emitAuthEvent(AUTH_EVENTS.LOGOUT, null)\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Initiates an OAuth login by redirecting to the given provider (e.g., `'google'`, `'github'`).\n * The page navigates away; this function never returns normally. Browser only.\n *\n * After the provider redirects back, call {@link handleAuthCallback} on page load\n * to complete the login and obtain the {@link User}.\n *\n * @throws {AuthError} If called on the server.\n */\nexport const oauthLogin = (provider: string): never => {\n if (!isBrowser()) {\n throw new AuthError('oauthLogin() is only available in the browser')\n }\n const client = getClient()\n\n window.location.href = client.loginExternalUrl(provider)\n throw new AuthError('Redirecting to OAuth provider')\n}\n\n/**\n * Result returned by {@link handleAuthCallback} after processing a URL hash.\n *\n * - `'oauth'`: OAuth provider redirect completed. `user` is the authenticated user.\n * - `'confirmation'`: Email confirmed via token. `user` is the confirmed user.\n * - `'recovery'`: Password recovery token redeemed. `user` is logged in but must set a new password.\n * - `'invite'`: Invite token found. `user` is `null`; `token` contains the invite token for {@link acceptInvite}.\n * - `'email_change'`: Email change verified. `user` reflects the updated email.\n *\n * @example\n * ```ts\n * const result = await handleAuthCallback()\n * if (result?.type === 'recovery') {\n * redirect('/reset-password')\n * } else if (result?.type === 'invite') {\n * redirect(`/join?token=${result.token}`)\n * }\n * ```\n */\nexport interface CallbackResult {\n /** The type of auth callback that was processed. */\n type: 'oauth' | 'confirmation' | 'recovery' | 'invite' | 'email_change'\n /** The authenticated user, or `null` for invite callbacks. */\n user: import('./user.js').User | null\n /** The invite token, only present when `type` is `'invite'`. */\n token?: string\n}\n\n/**\n * Processes the URL hash after an OAuth redirect, email confirmation, password\n * recovery, invite acceptance, or email change. Call on page load. Browser only.\n * Returns `null` if the hash contains no auth parameters.\n *\n * Call this early in your app's initialization (e.g., in a layout component or\n * root loader), **not** inside a route that requires authentication, because\n * the callback URL must match the page where this function runs.\n *\n * For recovery callbacks (`result.type === 'recovery'`), the user is logged in\n * but has **not** set a new password yet. Your app must check the result type\n * and redirect to a password form that calls `updateUser({ password })`.\n * A `'recovery'` event (not `'login'`) is emitted via {@link onAuthChange}.\n *\n * @throws {AuthError} If the callback token is invalid or the verification request fails.\n */\nexport const handleAuthCallback = async (): Promise<CallbackResult | null> => {\n if (!isBrowser()) return null\n\n const hash = window.location.hash.substring(1)\n if (!hash) return null\n\n const client = getClient()\n const params = new URLSearchParams(hash)\n\n try {\n const accessToken = params.get('access_token')\n if (accessToken) return await handleOAuthCallback(client, params, accessToken)\n\n const confirmationToken = params.get('confirmation_token')\n if (confirmationToken) return await handleConfirmationCallback(client, confirmationToken)\n\n const recoveryToken = params.get('recovery_token')\n if (recoveryToken) return await handleRecoveryCallback(client, recoveryToken)\n\n const inviteToken = params.get('invite_token')\n if (inviteToken) return handleInviteCallback(inviteToken)\n\n const emailChangeToken = params.get('email_change_token')\n if (emailChangeToken) return await handleEmailChangeCallback(client, emailChangeToken)\n\n return null\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw AuthError.from(error)\n }\n}\n\nconst handleOAuthCallback = async (\n client: GoTrue,\n params: URLSearchParams,\n accessToken: string,\n): Promise<CallbackResult> => {\n const refreshToken = params.get('refresh_token') ?? ''\n const expiresIn = parseInt(params.get('expires_in') ?? '', 10)\n const expiresAt = parseInt(params.get('expires_at') ?? '', 10)\n const gotrueUser = await client.createUser(\n {\n access_token: accessToken,\n token_type: (params.get('token_type') as 'bearer') ?? 'bearer',\n expires_in: isFinite(expiresIn) ? expiresIn : 3600,\n expires_at: isFinite(expiresAt) ? expiresAt : Math.floor(Date.now() / 1000) + 3600,\n refresh_token: refreshToken,\n },\n persistSession,\n )\n setBrowserAuthCookies(accessToken, refreshToken || undefined)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return { type: 'oauth', user }\n}\n\nconst handleConfirmationCallback = async (client: GoTrue, token: string): Promise<CallbackResult> => {\n const gotrueUser = await client.confirm(token, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return { type: 'confirmation', user }\n}\n\nconst handleRecoveryCallback = async (client: GoTrue, token: string): Promise<CallbackResult> => {\n const gotrueUser = await client.recover(token, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent(AUTH_EVENTS.RECOVERY, user)\n return { type: 'recovery', user }\n}\n\nconst handleInviteCallback = (token: string): CallbackResult => {\n clearHash()\n return { type: 'invite', user: null, token }\n}\n\nconst handleEmailChangeCallback = async (client: GoTrue, emailChangeToken: string): Promise<CallbackResult> => {\n const currentUser = client.currentUser()\n if (!currentUser) {\n throw new AuthError('Email change verification requires an active browser session')\n }\n\n const jwt = await currentUser.jwt()\n const identityUrl = `${window.location.origin}${IDENTITY_PATH}`\n\n const emailChangeRes = await fetch(`${identityUrl}/user`, {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${jwt}`,\n },\n body: JSON.stringify({ email_change_token: emailChangeToken }),\n })\n\n if (!emailChangeRes.ok) {\n const errorBody = (await emailChangeRes.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(\n errorBody.msg || `Email change verification failed (${emailChangeRes.status})`,\n emailChangeRes.status,\n )\n }\n\n const emailChangeData = (await emailChangeRes.json()) as UserData\n const user = toUser(emailChangeData)\n clearHash()\n emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user)\n return { type: 'email_change', user }\n}\n\nconst clearHash = (): void => {\n history.replaceState(null, '', window.location.pathname + window.location.search)\n}\n\n/**\n * Hydrates the browser-side gotrue-js session from server-set auth cookies.\n * Call this on page load when using server-side login to enable browser\n * account operations (updateUser, verifyEmailChange, etc.).\n *\n * No-op if a browser session already exists or no auth cookies are present.\n * No-op on the server.\n */\nexport const hydrateSession = async (): Promise<import('./user.js').User | null> => {\n if (!isBrowser()) return null\n\n const client = getClient()\n const currentUser = client.currentUser()\n if (currentUser) return toUser(currentUser)\n\n const accessToken = getCookie(NF_JWT_COOKIE)\n if (!accessToken) return null\n\n const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? ''\n\n const decoded = decodeJwtPayload(accessToken)\n const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1000) + 3600\n const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1000))\n\n let gotrueUser\n try {\n gotrueUser = await client.createUser(\n {\n access_token: accessToken,\n token_type: 'bearer',\n expires_in: expiresIn,\n expires_at: expiresAt,\n refresh_token: refreshToken,\n },\n persistSession,\n )\n } catch {\n deleteBrowserAuthCookies()\n return null\n }\n\n const user = toUser(gotrueUser)\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n}\n","import type { UserData } from 'gotrue-js'\nimport { AUTH_PROVIDERS, type AuthProvider } from './types.js'\nimport { getGoTrueClient, getIdentityContext, isBrowser, IDENTITY_PATH } from './environment.js'\nimport { getCookie, getServerCookie, NF_JWT_COOKIE } from './cookies.js'\nimport { triggerNextjsDynamic } from './nextjs.js'\nimport { hydrateSession } from './auth.js'\n\n/** Decoded JWT claims from the Identity token. Used internally to construct {@link User}. */\nexport interface IdentityUser {\n sub?: string\n email?: string\n exp?: number\n app_metadata?: Record<string, unknown>\n user_metadata?: Record<string, unknown>\n [key: string]: unknown\n}\n\nconst toAuthProvider = (value: unknown): AuthProvider | undefined =>\n typeof value === 'string' && (AUTH_PROVIDERS as readonly string[]).includes(value)\n ? (value as AuthProvider)\n : undefined\n\nconst toRoles = (appMeta: Record<string, unknown>): string[] | undefined => {\n const roles = appMeta.roles\n if (Array.isArray(roles) && roles.every((r) => typeof r === 'string')) {\n return roles as string[]\n }\n return undefined\n}\n\n/**\n * A normalized user object returned by all auth and admin functions.\n * Provides a consistent shape regardless of whether the user was loaded\n * from gotrue-js, a JWT cookie, or the server-side identity context.\n *\n * @example\n * ```ts\n * const user = await getUser()\n * if (user) {\n * console.log(user.email, user.name, user.roles)\n * }\n * ```\n */\nexport interface User {\n /** The user's unique identifier (GoTrue UUID). */\n id: string\n /** The user's email address. */\n email?: string\n /** `true` if the user's email has been confirmed. */\n emailVerified?: boolean\n /** ISO 8601 timestamp of when the account was created. */\n createdAt?: string\n /** ISO 8601 timestamp of the last account update. */\n updatedAt?: string\n /** The authentication provider used to create the account. */\n provider?: AuthProvider\n /** Display name from `user_metadata.full_name` or `user_metadata.name`. */\n name?: string\n /** Avatar URL from `user_metadata.avatar_url`. */\n pictureUrl?: string\n /** Roles from `app_metadata.roles`, set via the admin API or Netlify UI. */\n roles?: string[]\n /** The full `user_metadata` object. */\n metadata?: Record<string, unknown>\n /** The raw GoTrue user data, for accessing fields not mapped to this interface. */\n rawGoTrueData?: Record<string, unknown>\n}\n\nexport const toUser = (userData: UserData): User => {\n const userMeta = userData.user_metadata ?? {}\n const appMeta = userData.app_metadata ?? {}\n const name = userMeta.full_name || userMeta.name\n const pictureUrl = userMeta.avatar_url\n\n return {\n id: userData.id,\n email: userData.email,\n emailVerified: !!userData.confirmed_at,\n createdAt: userData.created_at,\n updatedAt: userData.updated_at,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n roles: toRoles(appMeta),\n metadata: userMeta,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts JWT claims into a User. Used as a fallback when the full GoTrue\n * user object is unavailable (e.g., GoTrue is unreachable on the server).\n */\nconst claimsToUser = (claims: IdentityUser): User => {\n const appMeta = claims.app_metadata ?? {}\n const userMeta = claims.user_metadata ?? {}\n const name = userMeta.full_name || userMeta.name\n const pictureUrl = userMeta.avatar_url\n\n return {\n id: claims.sub ?? '',\n email: claims.email,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n roles: toRoles(appMeta),\n metadata: userMeta,\n }\n}\n\n/** Decodes a JWT payload without verifying the signature. */\nexport const decodeJwtPayload = (token: string): IdentityUser | null => {\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return null\n const payload = atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))\n return JSON.parse(payload) as IdentityUser\n } catch {\n return null\n }\n}\n\n/**\n * Fetches the full user object from GoTrue using the JWT.\n * Returns null if the fetch fails (GoTrue unreachable, invalid token, etc.).\n */\nconst fetchFullUser = async (identityUrl: string, jwt: string): Promise<User | null> => {\n try {\n const res = await fetch(`${identityUrl}/user`, {\n headers: { Authorization: `Bearer ${jwt}` },\n })\n if (!res.ok) return null\n const userData = (await res.json()) as UserData\n return toUser(userData)\n } catch {\n return null\n }\n}\n\n/**\n * Resolves the Identity URL from available sources, or null if not discoverable.\n */\nconst resolveIdentityUrl = (): string | null => {\n const identityContext = getIdentityContext()\n if (identityContext?.url) return identityContext.url\n\n if (globalThis.Netlify?.context?.url) {\n return new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href\n }\n\n const siteUrl = typeof process !== 'undefined' ? process.env?.URL : undefined\n if (siteUrl) {\n return new URL(IDENTITY_PATH, siteUrl).href\n }\n\n return null\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n *\n * Always returns a full {@link User} object with all available fields\n * (email, roles, timestamps, metadata, etc.) regardless of whether the\n * call happens in the browser or on the server.\n *\n * In the browser, checks gotrue-js localStorage first. If no localStorage\n * session exists, hydrates from the `nf_jwt` cookie (set by server-side login).\n *\n * On the server, fetches the full user from GoTrue using the JWT from\n * the request. Falls back to JWT claims if GoTrue is unreachable.\n *\n * On the server in a Next.js App Router context, calls `headers()` from\n * `next/headers` to opt the route into dynamic rendering. Without this,\n * Next.js may statically cache the page at build time.\n */\nexport const getUser = async (): Promise<User | null> => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n\n if (currentUser) {\n // If gotrue-js has a localStorage session but the nf_jwt cookie is gone,\n // the server logged us out. Clear the stale localStorage session.\n const jwt = getCookie(NF_JWT_COOKIE)\n if (!jwt) {\n try {\n currentUser.clearSession()\n } catch {\n // best-effort cleanup\n }\n return null\n }\n return toUser(currentUser)\n }\n\n // No gotrue-js session but cookie exists: hydrate to get the full user\n const jwt = getCookie(NF_JWT_COOKIE)\n if (!jwt) return null\n\n // Verify the cookie contains a decodable JWT before attempting hydration\n const claims = decodeJwtPayload(jwt)\n if (!claims) return null\n\n const hydrated = await hydrateSession()\n if (hydrated) return hydrated\n\n // Hydration failed: fall back to JWT claims\n return claimsToUser(claims)\n }\n\n // Trigger Next.js dynamic rendering if in a Next.js RSC context\n triggerNextjsDynamic()\n\n // Get the JWT from the identity context header or cookie\n const identityContext = globalThis.netlifyIdentityContext\n const serverJwt = identityContext?.token || getServerCookie(NF_JWT_COOKIE)\n\n // Try to fetch the full user from GoTrue for a complete User object\n if (serverJwt) {\n const identityUrl = resolveIdentityUrl()\n if (identityUrl) {\n const fullUser = await fetchFullUser(identityUrl, serverJwt)\n if (fullUser) return fullUser\n }\n }\n\n // Fallback: use JWT claims from identity context or decoded cookie\n const claims = identityContext?.user ?? (serverJwt ? decodeJwtPayload(serverJwt) : null)\n return claims ? claimsToUser(claims) : null\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = async (): Promise<boolean> => (await getUser()) !== null\n","import type { AuthProvider, IdentityConfig, Settings } from './types.js'\nimport { getClient, getIdentityContext, IDENTITY_PATH, isBrowser } from './environment.js'\nimport { AuthError } from './errors.js'\n\n/**\n * Returns the identity configuration for the current environment.\n * Browser: always returns `{ url }` derived from `window.location.origin`.\n * Server: returns `{ url, token }` from the identity context, or `null` if unavailable.\n * Never throws.\n */\nexport const getIdentityConfig = (): IdentityConfig | null => {\n if (isBrowser()) {\n return { url: `${window.location.origin}${IDENTITY_PATH}` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches your project's Identity settings (enabled providers, autoconfirm, signup disabled).\n *\n * @throws {MissingIdentityError} If Identity is not configured.\n * @throws {AuthError} If the endpoint is unreachable.\n */\nexport const getSettings = async (): Promise<Settings> => {\n const client = getClient()\n\n try {\n const raw = await client.settings()\n const external: Partial<Record<AuthProvider, boolean>> = raw.external ?? {}\n return {\n autoconfirm: raw.autoconfirm,\n disableSignup: raw.disable_signup,\n providers: {\n google: external.google ?? false,\n github: external.github ?? false,\n gitlab: external.gitlab ?? false,\n bitbucket: external.bitbucket ?? false,\n facebook: external.facebook ?? false,\n email: external.email ?? false,\n saml: external.saml ?? false,\n },\n }\n } catch (err) {\n throw new AuthError(err instanceof Error ? err.message : 'Failed to fetch identity settings', 502, { cause: err })\n }\n}\n","import type { UserData, User as GoTrueUser } from 'gotrue-js'\n\nimport type { UserUpdates, GoTrueErrorBody } from './types.js'\nimport type { User } from './user.js'\nimport { toUser } from './user.js'\nimport { getClient, isBrowser, IDENTITY_PATH } from './environment.js'\nimport { persistSession, hydrateSession } from './auth.js'\nimport { AUTH_EVENTS, emitAuthEvent } from './events.js'\nimport { AuthError } from './errors.js'\n\n/**\n * Returns the current gotrue-js user, attempting hydration from cookies if\n * no in-memory session exists. Throws if no user can be resolved.\n */\nconst resolveCurrentUser = async (): Promise<GoTrueUser> => {\n const client = getClient()\n\n let currentUser = client.currentUser()\n if (!currentUser && isBrowser()) {\n try {\n await hydrateSession()\n } catch {\n // hydration failed (e.g. expired cookie, network error) — fall through\n }\n currentUser = client.currentUser()\n }\n if (!currentUser) throw new AuthError('No user is currently logged in')\n\n return currentUser\n}\n\n/**\n * Sends a password recovery email to the given address.\n *\n * @throws {AuthError} On network failure or if the request is rejected.\n */\nexport const requestPasswordRecovery = async (email: string): Promise<void> => {\n const client = getClient()\n\n try {\n await client.requestPasswordRecovery(email)\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Redeems a recovery token and sets a new password. Logs the user in on success.\n *\n * @throws {AuthError} If the token is invalid, expired, or the update fails.\n */\nexport const recoverPassword = async (token: string, newPassword: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.recover(token, persistSession)\n const updatedUser = await gotrueUser.update({ password: newPassword })\n const user = toUser(updatedUser)\n // Emits LOGIN because the recovery is fully complete\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Confirms an email address using the token from a confirmation email. Logs the user in on success.\n *\n * @throws {AuthError} If the token is invalid or expired.\n */\nexport const confirmEmail = async (token: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.confirm(token, persistSession)\n const user = toUser(gotrueUser)\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Accepts an invite token and sets a password for the new account. Logs the user in on success.\n *\n * @throws {AuthError} If the token is invalid or expired.\n */\nexport const acceptInvite = async (token: string, password: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.acceptInvite(token, password, persistSession)\n const user = toUser(gotrueUser)\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Verifies an email change using the token from a verification email.\n * Auto-hydrates from auth cookies if no browser session exists. Browser only.\n *\n * @throws {AuthError} If called on the server, no user is logged in, or the token is invalid.\n */\nexport const verifyEmailChange = async (token: string): Promise<User> => {\n if (!isBrowser()) throw new AuthError('verifyEmailChange() is only available in the browser')\n\n const currentUser = await resolveCurrentUser()\n\n try {\n const jwt = await currentUser.jwt()\n const identityUrl = `${window.location.origin}${IDENTITY_PATH}`\n\n const res = await fetch(`${identityUrl}/user`, {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${jwt}`,\n },\n body: JSON.stringify({ email_change_token: token }),\n })\n\n if (!res.ok) {\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || `Email change verification failed (${res.status})`, res.status)\n }\n\n const userData = (await res.json()) as UserData\n const user = toUser(userData)\n emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user)\n return user\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw AuthError.from(error)\n }\n}\n\n/**\n * Updates the current user's email, password, or user metadata.\n * Auto-hydrates from auth cookies if no browser session exists.\n *\n * @param updates - Fields to update. Pass `email` or `password` to change credentials,\n * or `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).\n * @throws {AuthError} If no user is logged in or the update fails.\n */\nexport const updateUser = async (updates: UserUpdates): Promise<User> => {\n const currentUser = await resolveCurrentUser()\n\n try {\n const updatedUser = await currentUser.update(updates)\n const user = toUser(updatedUser)\n emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n","import type { UserData } from 'gotrue-js'\n\nimport { isBrowser, getClient, getIdentityContext } from './environment.js'\nimport { AuthError } from './errors.js'\nimport type { AdminUserUpdates, CreateUserParams, GoTrueErrorBody, ListUsersOptions } from './types.js'\nimport { toUser, type User } from './user.js'\n\n/**\n * Returns the operator token and Identity URL for server-side admin requests.\n * @throws {AuthError} If the Identity endpoint URL or operator token is unavailable.\n */\nconst getAdminAuth = (): { url: string; token: string } => {\n const ctx = getIdentityContext()\n if (!ctx?.url) {\n throw new AuthError('Could not determine the Identity endpoint URL on the server')\n }\n if (!ctx.token) {\n throw new AuthError('Admin operations require an operator token (only available in Netlify Functions)')\n }\n return { url: ctx.url, token: ctx.token }\n}\n\n/**\n * Makes an authenticated admin request to GoTrue on the server.\n * @throws {AuthError} If the request fails or GoTrue returns a non-OK status.\n */\nconst adminFetch = async (path: string, options: RequestInit = {}): Promise<Response> => {\n const { url, token } = getAdminAuth()\n let res: Response\n try {\n res = await fetch(`${url}${path}`, {\n ...options,\n headers: {\n ...options.headers,\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n })\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n if (!res.ok) {\n const errorBody = await res.json().catch(() => ({}))\n throw new AuthError((errorBody as GoTrueErrorBody).msg || `Admin request failed (${res.status})`, res.status)\n }\n return res\n}\n\n/** Returns the current user (browser only), throwing if not logged in. */\nconst getAdminUser = () => {\n const client = getClient()\n const user = client.currentUser()\n if (!user) {\n throw new AuthError('Admin operations require a logged-in user with admin role')\n }\n return user\n}\n\n/**\n * Lists all users. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users` with the operator token. Pagination\n * options (`page`, `perPage`) are forwarded as query parameters.\n *\n * **Browser:** calls gotrue-js `user.admin.listUsers()`. The logged-in user must\n * have an admin role. Pagination options are ignored (gotrue-js does not support them).\n *\n * @throws {AuthError} If the operator token is missing (server) or no admin user is logged in (browser).\n */\nconst listUsers = async (options?: ListUsersOptions): Promise<User[]> => {\n if (!isBrowser()) {\n const params = new URLSearchParams()\n if (options?.page != null) params.set('page', String(options.page))\n if (options?.perPage != null) params.set('per_page', String(options.perPage))\n const query = params.toString()\n const path = `/admin/users${query ? `?${query}` : ''}`\n\n const res = await adminFetch(path)\n const body = (await res.json()) as { users: UserData[] }\n return body.users.map(toUser)\n }\n\n try {\n const user = getAdminUser()\n const users = await user.admin.listUsers('')\n return (users as UserData[]).map(toUser)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Gets a single user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.getUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\nconst getUser = async (userId: string): Promise<User> => {\n if (!isBrowser()) {\n const res = await adminFetch(`/admin/users/${userId}`)\n const userData = (await res.json()) as UserData\n return toUser(userData)\n }\n\n try {\n const user = getAdminUser()\n const userData = await user.admin.getUser({ id: userId } as UserData)\n return toUser(userData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Creates a new user. The user is auto-confirmed (no confirmation email is sent).\n * Works in both server and browser contexts.\n *\n * The optional `data` fields are spread as **top-level attributes** in the GoTrue\n * request body (not nested under `user_metadata`). Use this to set `app_metadata`,\n * `user_metadata`, `role`, or any other GoTrue user field at creation time.\n *\n * **Server:** calls GoTrue `POST /admin/users` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.createUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the email already exists, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\nconst createUser = async (params: CreateUserParams): Promise<User> => {\n if (!isBrowser()) {\n const res = await adminFetch('/admin/users', {\n method: 'POST',\n body: JSON.stringify({\n email: params.email,\n password: params.password,\n ...params.data,\n confirm: true,\n }),\n })\n const userData = (await res.json()) as UserData\n return toUser(userData)\n }\n\n try {\n const user = getAdminUser()\n const userData = await user.admin.createUser(params.email, params.password, {\n ...params.data,\n confirm: true,\n })\n return toUser(userData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Updates an existing user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `PUT /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.updateUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the update fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\nconst updateUser = async (userId: string, attributes: AdminUserUpdates): Promise<User> => {\n if (!isBrowser()) {\n const res = await adminFetch(`/admin/users/${userId}`, {\n method: 'PUT',\n body: JSON.stringify(attributes),\n })\n const userData = (await res.json()) as UserData\n return toUser(userData)\n }\n\n try {\n const user = getAdminUser()\n const userData = await user.admin.updateUser({ id: userId } as UserData, attributes)\n return toUser(userData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Deletes a user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `DELETE /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.deleteUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the deletion fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\nconst deleteUser = async (userId: string): Promise<void> => {\n if (!isBrowser()) {\n await adminFetch(`/admin/users/${userId}`, { method: 'DELETE' })\n return\n }\n\n try {\n const user = getAdminUser()\n await user.admin.deleteUser({ id: userId } as UserData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * The admin namespace for privileged user management operations.\n * All methods work in both server and browser contexts.\n *\n * **Server:** uses the operator token (automatically available in Netlify Functions).\n * **Browser:** requires a logged-in user with an admin role.\n */\nexport interface Admin {\n /**\n * Lists all users. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users` with the operator token. Pagination\n * options (`page`, `perPage`) are forwarded as query parameters.\n *\n * **Browser:** calls gotrue-js `user.admin.listUsers()`. The logged-in user must\n * have an admin role. Pagination options are ignored (gotrue-js does not support them).\n *\n * @throws {AuthError} If the operator token is missing (server) or no admin user is logged in (browser).\n */\n listUsers: (options?: ListUsersOptions) => Promise<User[]>\n\n /**\n * Gets a single user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.getUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\n getUser: (userId: string) => Promise<User>\n\n /**\n * Creates a new user. The user is auto-confirmed (no confirmation email is sent).\n * Works in both server and browser contexts.\n *\n * The optional `data` fields are spread as **top-level attributes** in the GoTrue\n * request body (not nested under `user_metadata`). Use this to set `app_metadata`,\n * `user_metadata`, `role`, or any other GoTrue user field at creation time.\n *\n * **Server:** calls GoTrue `POST /admin/users` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.createUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the email already exists, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\n createUser: (params: CreateUserParams) => Promise<User>\n\n /**\n * Updates an existing user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `PUT /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.updateUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the update fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\n updateUser: (userId: string, attributes: AdminUserUpdates) => Promise<User>\n\n /**\n * Deletes a user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `DELETE /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.deleteUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the deletion fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\n deleteUser: (userId: string) => Promise<void>\n}\n\nexport const admin: Admin = { listUsers, getUser, createUser, updateUser, deleteUser }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCO,IAAM,iBAAiB,CAAC,UAAU,UAAU,UAAU,aAAa,YAAY,QAAQ,OAAO;;;ACDrG,uBAAmB;;;ACmBZ,IAAM,YAAN,MAAM,mBAAkB,MAAM;AAAA,EAMnC,YAAY,SAAiB,QAAiB,SAA+B;AAC3E,UAAM,OAAO;AANf,SAAS,OAAO;AAOd,SAAK,SAAS;AACd,QAAI,WAAW,WAAW,SAAS;AACjC,WAAK,QAAQ,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,OAAO,KAAK,OAA2B;AACrC,QAAI,iBAAiB,WAAW,QAAO;AACvC,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO,IAAI,WAAU,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3D;AACF;AASO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YAAY,UAAU,sCAAsC;AAC1D,UAAM,OAAO;AAHf,SAAS,OAAO;AAAA,EAIhB;AACF;;;ADhDO,IAAM,gBAAgB;AAE7B,IAAI,eAA8B;AAClC,IAAI;AACJ,IAAI,mBAAmB;AAEhB,IAAM,YAAY,MAAe,OAAO,WAAW,eAAe,OAAO,OAAO,aAAa;AAQpG,IAAM,iBAAiB,MAAqB;AAC1C,MAAI,iBAAiB,OAAW,QAAO;AAEvC,MAAI,UAAU,GAAG;AACf,mBAAe,GAAG,OAAO,SAAS,MAAM,GAAG,aAAa;AAAA,EAC1D,OAAO;AACL,UAAM,kBAAkB,mBAAmB;AAC3C,QAAI,iBAAiB,KAAK;AACxB,qBAAe,gBAAgB;AAAA,IACjC,WAAW,WAAW,SAAS,SAAS,KAAK;AAC3C,qBAAe,IAAI,IAAI,eAAe,WAAW,QAAQ,QAAQ,GAAG,EAAE;AAAA,IACxE,WAAW,OAAO,YAAY,eAAe,QAAQ,KAAK,KAAK;AAC7D,qBAAe,IAAI,IAAI,eAAe,QAAQ,IAAI,GAAG,EAAE;AAAA,IACzD;AAAA,EACF;AAEA,SAAO,gBAAgB;AACzB;AAMO,IAAM,kBAAkB,MAAqB;AAClD,MAAI,aAAc,QAAO;AAEzB,QAAM,SAAS,eAAe;AAC9B,MAAI,CAAC,QAAQ;AACX,QAAI,CAAC,kBAAkB;AACrB,cAAQ;AAAA,QACN;AAAA,MAEF;AACA,yBAAmB;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAEA,iBAAe,IAAI,iBAAAA,QAAO,EAAE,QAAQ,QAAQ,WAAW,MAAM,CAAC;AAC9D,SAAO;AACT;AAKO,IAAM,YAAY,MAAc;AACrC,QAAM,SAAS,gBAAgB;AAC/B,MAAI,CAAC,OAAQ,OAAM,IAAI,qBAAqB;AAC5C,SAAO;AACT;AAMO,IAAM,qBAAqB,MAA6B;AAC7D,QAAM,kBAAkB,WAAW;AACnC,MAAI,iBAAiB,KAAK;AACxB,WAAO;AAAA,MACL,KAAK,gBAAgB;AAAA,MACrB,OAAO,gBAAgB;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,WAAW,SAAS,SAAS,KAAK;AACpC,WAAO,EAAE,KAAK,IAAI,IAAI,eAAe,WAAW,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,EAC5E;AAGA,QAAM,UAAU,OAAO,YAAY,cAAc,QAAQ,KAAK,MAAM;AACpE,MAAI,SAAS;AACX,WAAO,EAAE,KAAK,IAAI,IAAI,eAAe,OAAO,EAAE,KAAK;AAAA,EACrD;AAEA,SAAO;AACT;;;AE5FO,IAAM,gBAAgB;AACtB,IAAM,oBAAoB;AAG1B,IAAM,YAAY,CAAC,SAAgC;AACxD,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,QAAQ,SAAS,OAAO,MAAM,IAAI,OAAO,WAAW,KAAK,QAAQ,uBAAuB,MAAM,CAAC,UAAU,CAAC;AAChH,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,WAAO,mBAAmB,MAAM,CAAC,CAAC;AAAA,EACpC,QAAQ;AACN,WAAO,MAAM,CAAC;AAAA,EAChB;AACF;AAGO,IAAM,iBAAiB,CAAC,SAAyB,aAAqB,iBAAgC;AAC3G,UAAQ,IAAI;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,cAAc;AAGhB,YAAQ,IAAI;AAAA,MACV,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AACF;AAGO,IAAM,oBAAoB,CAAC,YAAkC;AAClE,UAAQ,OAAO,aAAa;AAC5B,UAAQ,OAAO,iBAAiB;AAClC;AAGO,IAAM,wBAAwB,CAAC,aAAqB,iBAAgC;AACzF,MAAI,OAAO,aAAa,YAAa;AACrC,WAAS,SAAS,GAAG,aAAa,IAAI,mBAAmB,WAAW,CAAC;AACrE,MAAI,cAAc;AAChB,aAAS,SAAS,GAAG,iBAAiB,IAAI,mBAAmB,YAAY,CAAC;AAAA,EAC5E;AACF;AAGO,IAAM,2BAA2B,MAAY;AAClD,MAAI,OAAO,aAAa,YAAa;AACrC,WAAS,SAAS,GAAG,aAAa;AAClC,WAAS,SAAS,GAAG,iBAAiB;AACxC;AAGO,IAAM,kBAAkB,CAAC,SAAgC;AAC9D,QAAM,UAAU,WAAW,SAAS,SAAS;AAC7C,MAAI,CAAC,WAAW,OAAO,QAAQ,QAAQ,WAAY,QAAO;AAC1D,SAAO,QAAQ,IAAI,IAAI,KAAK;AAC9B;;;ACzDA,IAAI;AACG,IAAM,uBAAuB,MAAY;AAC9C,MAAI,kBAAkB,KAAM;AAE5B,MAAI,kBAAkB,QAAW;AAC/B,QAAI;AACF,UAAI,OAAO,YAAY,aAAa;AAClC,wBAAgB;AAChB;AAAA,MACF;AACA,YAAM,MAAM,QAAQ,cAAc;AAClC,sBAAgB,IAAI;AAAA,IACtB,QAAQ;AACN,sBAAgB;AAChB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,KAAK;AACX,MAAI,CAAC,GAAI;AAET,MAAI;AACF,OAAG;AAAA,EACL,SAAS,GAAY;AAInB,QAAI,aAAa,UAAU,YAAY,KAAK,wBAAwB,KAAK,EAAE,OAAO,IAAI;AACpF,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AC5BO,IAAM,cAAc;AAAA,EACzB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,cAAc;AAAA,EACd,UAAU;AACZ;AAcA,IAAM,qBAAqB;AAE3B,IAAM,YAAY,oBAAI,IAAkB;AAEjC,IAAM,gBAAgB,CAAC,OAAkB,SAA4B;AAC1E,aAAW,YAAY,WAAW;AAChC,QAAI;AACF,eAAS,OAAO,IAAI;AAAA,IACtB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEA,IAAI,0BAA0B;AAE9B,IAAM,wBAAwB,MAAY;AACxC,MAAI,2BAA2B,CAAC,UAAU,EAAG;AAC7C,4BAA0B;AAE1B,SAAO,iBAAiB,WAAW,CAAC,UAAwB;AAC1D,QAAI,MAAM,QAAQ,mBAAoB;AAEtC,QAAI,MAAM,UAAU;AAClB,YAAM,SAAS,gBAAgB;AAC/B,YAAM,cAAc,QAAQ,YAAY;AACxC,oBAAc,YAAY,OAAO,cAAc,OAAO,WAAW,IAAI,IAAI;AAAA,IAC3E,OAAO;AACL,oBAAc,YAAY,QAAQ,IAAI;AAAA,IACxC;AAAA,EACF,CAAC;AACH;AAWO,IAAM,eAAe,CAAC,aAAyC;AACpE,MAAI,CAAC,UAAU,GAAG;AAChB,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,YAAU,IAAI,QAAQ;AACtB,wBAAsB;AAEtB,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AAAA,EAC3B;AACF;;;ACtEA,IAAM,aAAa,MAAsB;AACvC,QAAM,UAAU,WAAW,SAAS,SAAS;AAC7C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,UAAU,qDAAqD;AAAA,EAC3E;AACA,SAAO;AACT;AAEA,IAAM,uBAAuB,MAAc;AACzC,QAAM,MAAM,mBAAmB;AAC/B,MAAI,CAAC,KAAK,KAAK;AACb,UAAM,IAAI,UAAU,6DAA6D;AAAA,EACnF;AACA,SAAO,IAAI;AACb;AAGO,IAAM,iBAAiB;AAsBvB,IAAM,QAAQ,OAAO,OAAe,aAAwD;AACjG,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,cAAc,qBAAqB;AACzC,UAAM,UAAU,WAAW;AAE3B,UAAM,OAAO,IAAI,gBAAgB;AAAA,MAC/B,YAAY;AAAA,MACZ,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAED,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,MAAM,GAAG,WAAW,UAAU;AAAA,QACxC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,QAC/D,MAAM,KAAK,SAAS;AAAA,MACtB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,UAAU,KAAK,KAAK;AAAA,IAC5B;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,YAAa,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,UAAU,UAAU,OAAO,UAAU,qBAAqB,iBAAiB,IAAI,MAAM,KAAK,IAAI,MAAM;AAAA,IAChH;AAEA,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,UAAM,cAAc,KAAK;AAEzB,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,MAAM,GAAG,WAAW,SAAS;AAAA,QAC3C,SAAS,EAAE,eAAe,UAAU,WAAW,GAAG;AAAA,MACpD,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,UAAU,KAAK,KAAK;AAAA,IAC5B;AAEA,QAAI,CAAC,QAAQ,IAAI;AACf,YAAM,YAAa,MAAM,QAAQ,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACxD,YAAM,IAAI,UAAU,UAAU,OAAO,8BAA8B,QAAQ,MAAM,KAAK,QAAQ,MAAM;AAAA,IACtG;AAEA,UAAM,WAAY,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,OAAO,QAAQ;AAE5B,mBAAe,SAAS,aAAa,KAAK,aAAa;AAEvD,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,aAAa,MAAM,OAAO,MAAM,OAAO,UAAU,cAAc;AACrE,UAAM,MAAM,MAAM,WAAW,IAAI;AACjC,0BAAsB,KAAK,WAAW,aAAa,GAAG,aAAa;AACnE,UAAM,OAAO,OAAO,UAAU;AAC9B,kBAAc,YAAY,OAAO,IAAI;AACrC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAYO,IAAM,SAAS,OAAO,OAAe,UAAkB,SAAyD;AACrH,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,cAAc,qBAAqB;AACzC,UAAM,UAAU,WAAW;AAE3B,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,MAAM,GAAG,WAAW,WAAW;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,UAAU,KAAK,CAAC;AAAA,MAChD,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,UAAU,KAAK,KAAK;AAAA,IAC5B;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,YAAa,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,UAAU,UAAU,OAAO,kBAAkB,IAAI,MAAM,KAAK,IAAI,MAAM;AAAA,IAClF;AAEA,UAAM,eAAgB,MAAM,IAAI,KAAK;AACrC,UAAM,OAAO,OAAO,YAAY;AAEhC,QAAI,aAAa,cAAc;AAC7B,YAAM,cAAc,aAAa;AACjC,UAAI,aAAa;AACf,uBAAe,SAAS,aAAa,aAAa,aAAa;AAAA,MACjE;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,OAAO,OAAO,UAAU,IAAI;AAC1D,UAAM,OAAO,OAAO,QAAoB;AACxC,QAAI,SAAS,cAAc;AACzB,YAAM,MAAM,MAAO,SAA6C,MAAM;AACtE,UAAI,KAAK;AACP,cAAM,eAAgB,SAAuE,eAAe,GACxG;AACJ,8BAAsB,KAAK,YAAY;AAAA,MACzC;AACA,oBAAc,YAAY,OAAO,IAAI;AAAA,IACvC;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAUO,IAAM,SAAS,YAA2B;AAC/C,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,cAAc,qBAAqB;AACzC,UAAM,UAAU,WAAW;AAE3B,UAAM,MAAM,QAAQ,IAAI,aAAa;AACrC,QAAI,KAAK;AACP,UAAI;AACF,cAAM,MAAM,GAAG,WAAW,WAAW;AAAA,UACnC,QAAQ;AAAA,UACR,SAAS,EAAE,eAAe,UAAU,GAAG,GAAG;AAAA,QAC5C,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,sBAAkB,OAAO;AACzB;AAAA,EACF;AAEA,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,cAAc,OAAO,YAAY;AACvC,QAAI,aAAa;AACf,YAAM,YAAY,OAAO;AAAA,IAC3B;AACA,6BAAyB;AACzB,kBAAc,YAAY,QAAQ,IAAI;AAAA,EACxC,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAWO,IAAM,aAAa,CAAC,aAA4B;AACrD,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,IAAI,UAAU,+CAA+C;AAAA,EACrE;AACA,QAAM,SAAS,UAAU;AAEzB,SAAO,SAAS,OAAO,OAAO,iBAAiB,QAAQ;AACvD,QAAM,IAAI,UAAU,+BAA+B;AACrD;AA8CO,IAAM,qBAAqB,YAA4C;AAC5E,MAAI,CAAC,UAAU,EAAG,QAAO;AAEzB,QAAM,OAAO,OAAO,SAAS,KAAK,UAAU,CAAC;AAC7C,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,IAAI,gBAAgB,IAAI;AAEvC,MAAI;AACF,UAAM,cAAc,OAAO,IAAI,cAAc;AAC7C,QAAI,YAAa,QAAO,MAAM,oBAAoB,QAAQ,QAAQ,WAAW;AAE7E,UAAM,oBAAoB,OAAO,IAAI,oBAAoB;AACzD,QAAI,kBAAmB,QAAO,MAAM,2BAA2B,QAAQ,iBAAiB;AAExF,UAAM,gBAAgB,OAAO,IAAI,gBAAgB;AACjD,QAAI,cAAe,QAAO,MAAM,uBAAuB,QAAQ,aAAa;AAE5E,UAAM,cAAc,OAAO,IAAI,cAAc;AAC7C,QAAI,YAAa,QAAO,qBAAqB,WAAW;AAExD,UAAM,mBAAmB,OAAO,IAAI,oBAAoB;AACxD,QAAI,iBAAkB,QAAO,MAAM,0BAA0B,QAAQ,gBAAgB;AAErF,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAEA,IAAM,sBAAsB,OAC1B,QACA,QACA,gBAC4B;AAC5B,QAAM,eAAe,OAAO,IAAI,eAAe,KAAK;AACpD,QAAM,YAAY,SAAS,OAAO,IAAI,YAAY,KAAK,IAAI,EAAE;AAC7D,QAAM,YAAY,SAAS,OAAO,IAAI,YAAY,KAAK,IAAI,EAAE;AAC7D,QAAM,aAAa,MAAM,OAAO;AAAA,IAC9B;AAAA,MACE,cAAc;AAAA,MACd,YAAa,OAAO,IAAI,YAAY,KAAkB;AAAA,MACtD,YAAY,SAAS,SAAS,IAAI,YAAY;AAAA,MAC9C,YAAY,SAAS,SAAS,IAAI,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAAA,MAC9E,eAAe;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,wBAAsB,aAAa,gBAAgB,MAAS;AAC5D,QAAM,OAAO,OAAO,UAAU;AAC9B,YAAU;AACV,gBAAc,YAAY,OAAO,IAAI;AACrC,SAAO,EAAE,MAAM,SAAS,KAAK;AAC/B;AAEA,IAAM,6BAA6B,OAAO,QAAgB,UAA2C;AACnG,QAAM,aAAa,MAAM,OAAO,QAAQ,OAAO,cAAc;AAC7D,QAAM,MAAM,MAAM,WAAW,IAAI;AACjC,wBAAsB,KAAK,WAAW,aAAa,GAAG,aAAa;AACnE,QAAM,OAAO,OAAO,UAAU;AAC9B,YAAU;AACV,gBAAc,YAAY,OAAO,IAAI;AACrC,SAAO,EAAE,MAAM,gBAAgB,KAAK;AACtC;AAEA,IAAM,yBAAyB,OAAO,QAAgB,UAA2C;AAC/F,QAAM,aAAa,MAAM,OAAO,QAAQ,OAAO,cAAc;AAC7D,QAAM,MAAM,MAAM,WAAW,IAAI;AACjC,wBAAsB,KAAK,WAAW,aAAa,GAAG,aAAa;AACnE,QAAM,OAAO,OAAO,UAAU;AAC9B,YAAU;AACV,gBAAc,YAAY,UAAU,IAAI;AACxC,SAAO,EAAE,MAAM,YAAY,KAAK;AAClC;AAEA,IAAM,uBAAuB,CAAC,UAAkC;AAC9D,YAAU;AACV,SAAO,EAAE,MAAM,UAAU,MAAM,MAAM,MAAM;AAC7C;AAEA,IAAM,4BAA4B,OAAO,QAAgB,qBAAsD;AAC7G,QAAM,cAAc,OAAO,YAAY;AACvC,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,UAAU,8DAA8D;AAAA,EACpF;AAEA,QAAM,MAAM,MAAM,YAAY,IAAI;AAClC,QAAM,cAAc,GAAG,OAAO,SAAS,MAAM,GAAG,aAAa;AAE7D,QAAM,iBAAiB,MAAM,MAAM,GAAG,WAAW,SAAS;AAAA,IACxD,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,eAAe,UAAU,GAAG;AAAA,IAC9B;AAAA,IACA,MAAM,KAAK,UAAU,EAAE,oBAAoB,iBAAiB,CAAC;AAAA,EAC/D,CAAC;AAED,MAAI,CAAC,eAAe,IAAI;AACtB,UAAM,YAAa,MAAM,eAAe,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/D,UAAM,IAAI;AAAA,MACR,UAAU,OAAO,qCAAqC,eAAe,MAAM;AAAA,MAC3E,eAAe;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,kBAAmB,MAAM,eAAe,KAAK;AACnD,QAAM,OAAO,OAAO,eAAe;AACnC,YAAU;AACV,gBAAc,YAAY,cAAc,IAAI;AAC5C,SAAO,EAAE,MAAM,gBAAgB,KAAK;AACtC;AAEA,IAAM,YAAY,MAAY;AAC5B,UAAQ,aAAa,MAAM,IAAI,OAAO,SAAS,WAAW,OAAO,SAAS,MAAM;AAClF;AAUO,IAAM,iBAAiB,YAAsD;AAClF,MAAI,CAAC,UAAU,EAAG,QAAO;AAEzB,QAAM,SAAS,UAAU;AACzB,QAAM,cAAc,OAAO,YAAY;AACvC,MAAI,YAAa,QAAO,OAAO,WAAW;AAE1C,QAAM,cAAc,UAAU,aAAa;AAC3C,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,eAAe,UAAU,iBAAiB,KAAK;AAErD,QAAM,UAAU,iBAAiB,WAAW;AAC5C,QAAM,YAAY,SAAS,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAClE,QAAM,YAAY,KAAK,IAAI,GAAG,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,CAAC;AAEvE,MAAI;AACJ,MAAI;AACF,iBAAa,MAAM,OAAO;AAAA,MACxB;AAAA,QACE,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,eAAe;AAAA,MACjB;AAAA,MACA;AAAA,IACF;AAAA,EACF,QAAQ;AACN,6BAAyB;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,OAAO,UAAU;AAC9B,gBAAc,YAAY,OAAO,IAAI;AACrC,SAAO;AACT;;;ACvbA,IAAM,iBAAiB,CAAC,UACtB,OAAO,UAAU,YAAa,eAAqC,SAAS,KAAK,IAC5E,QACD;AAEN,IAAM,UAAU,CAAC,YAA2D;AAC1E,QAAM,QAAQ,QAAQ;AACtB,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG;AACrE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAwCO,IAAM,SAAS,CAAC,aAA6B;AAClD,QAAM,WAAW,SAAS,iBAAiB,CAAC;AAC5C,QAAM,UAAU,SAAS,gBAAgB,CAAC;AAC1C,QAAM,OAAO,SAAS,aAAa,SAAS;AAC5C,QAAM,aAAa,SAAS;AAE5B,SAAO;AAAA,IACL,IAAI,SAAS;AAAA,IACb,OAAO,SAAS;AAAA,IAChB,eAAe,CAAC,CAAC,SAAS;AAAA,IAC1B,WAAW,SAAS;AAAA,IACpB,WAAW,SAAS;AAAA,IACpB,UAAU,eAAe,QAAQ,QAAQ;AAAA,IACzC,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,IACxC,YAAY,OAAO,eAAe,WAAW,aAAa;AAAA,IAC1D,OAAO,QAAQ,OAAO;AAAA,IACtB,UAAU;AAAA,IACV,eAAe,EAAE,GAAG,SAAS;AAAA,EAC/B;AACF;AAMA,IAAM,eAAe,CAAC,WAA+B;AACnD,QAAM,UAAU,OAAO,gBAAgB,CAAC;AACxC,QAAM,WAAW,OAAO,iBAAiB,CAAC;AAC1C,QAAM,OAAO,SAAS,aAAa,SAAS;AAC5C,QAAM,aAAa,SAAS;AAE5B,SAAO;AAAA,IACL,IAAI,OAAO,OAAO;AAAA,IAClB,OAAO,OAAO;AAAA,IACd,UAAU,eAAe,QAAQ,QAAQ;AAAA,IACzC,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,IACxC,YAAY,OAAO,eAAe,WAAW,aAAa;AAAA,IAC1D,OAAO,QAAQ,OAAO;AAAA,IACtB,UAAU;AAAA,EACZ;AACF;AAGO,IAAM,mBAAmB,CAAC,UAAuC;AACtE,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,UAAM,UAAU,KAAK,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG,CAAC;AACnE,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,IAAM,gBAAgB,OAAO,aAAqB,QAAsC;AACtF,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,GAAG,WAAW,SAAS;AAAA,MAC7C,SAAS,EAAE,eAAe,UAAU,GAAG,GAAG;AAAA,IAC5C,CAAC;AACD,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,UAAM,WAAY,MAAM,IAAI,KAAK;AACjC,WAAO,OAAO,QAAQ;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,IAAM,qBAAqB,MAAqB;AAC9C,QAAM,kBAAkB,mBAAmB;AAC3C,MAAI,iBAAiB,IAAK,QAAO,gBAAgB;AAEjD,MAAI,WAAW,SAAS,SAAS,KAAK;AACpC,WAAO,IAAI,IAAI,eAAe,WAAW,QAAQ,QAAQ,GAAG,EAAE;AAAA,EAChE;AAEA,QAAM,UAAU,OAAO,YAAY,cAAc,QAAQ,KAAK,MAAM;AACpE,MAAI,SAAS;AACX,WAAO,IAAI,IAAI,eAAe,OAAO,EAAE;AAAA,EACzC;AAEA,SAAO;AACT;AAmBO,IAAM,UAAU,YAAkC;AACvD,MAAI,UAAU,GAAG;AACf,UAAM,SAAS,gBAAgB;AAC/B,UAAM,cAAc,QAAQ,YAAY,KAAK;AAE7C,QAAI,aAAa;AAGf,YAAMC,OAAM,UAAU,aAAa;AACnC,UAAI,CAACA,MAAK;AACR,YAAI;AACF,sBAAY,aAAa;AAAA,QAC3B,QAAQ;AAAA,QAER;AACA,eAAO;AAAA,MACT;AACA,aAAO,OAAO,WAAW;AAAA,IAC3B;AAGA,UAAM,MAAM,UAAU,aAAa;AACnC,QAAI,CAAC,IAAK,QAAO;AAGjB,UAAMC,UAAS,iBAAiB,GAAG;AACnC,QAAI,CAACA,QAAQ,QAAO;AAEpB,UAAM,WAAW,MAAM,eAAe;AACtC,QAAI,SAAU,QAAO;AAGrB,WAAO,aAAaA,OAAM;AAAA,EAC5B;AAGA,uBAAqB;AAGrB,QAAM,kBAAkB,WAAW;AACnC,QAAM,YAAY,iBAAiB,SAAS,gBAAgB,aAAa;AAGzE,MAAI,WAAW;AACb,UAAM,cAAc,mBAAmB;AACvC,QAAI,aAAa;AACf,YAAM,WAAW,MAAM,cAAc,aAAa,SAAS;AAC3D,UAAI,SAAU,QAAO;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,SAAS,iBAAiB,SAAS,YAAY,iBAAiB,SAAS,IAAI;AACnF,SAAO,SAAS,aAAa,MAAM,IAAI;AACzC;AAKO,IAAM,kBAAkB,YAA+B,MAAM,QAAQ,MAAO;;;AChO5E,IAAM,oBAAoB,MAA6B;AAC5D,MAAI,UAAU,GAAG;AACf,WAAO,EAAE,KAAK,GAAG,OAAO,SAAS,MAAM,GAAG,aAAa,GAAG;AAAA,EAC5D;AAEA,SAAO,mBAAmB;AAC5B;AAQO,IAAM,cAAc,YAA+B;AACxD,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,SAAS;AAClC,UAAM,WAAmD,IAAI,YAAY,CAAC;AAC1E,WAAO;AAAA,MACL,aAAa,IAAI;AAAA,MACjB,eAAe,IAAI;AAAA,MACnB,WAAW;AAAA,QACT,QAAQ,SAAS,UAAU;AAAA,QAC3B,QAAQ,SAAS,UAAU;AAAA,QAC3B,QAAQ,SAAS,UAAU;AAAA,QAC3B,WAAW,SAAS,aAAa;AAAA,QACjC,UAAU,SAAS,YAAY;AAAA,QAC/B,OAAO,SAAS,SAAS;AAAA,QACzB,MAAM,SAAS,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,IAAI,UAAU,eAAe,QAAQ,IAAI,UAAU,qCAAqC,KAAK,EAAE,OAAO,IAAI,CAAC;AAAA,EACnH;AACF;;;AChCA,IAAM,qBAAqB,YAAiC;AAC1D,QAAM,SAAS,UAAU;AAEzB,MAAI,cAAc,OAAO,YAAY;AACrC,MAAI,CAAC,eAAe,UAAU,GAAG;AAC/B,QAAI;AACF,YAAM,eAAe;AAAA,IACvB,QAAQ;AAAA,IAER;AACA,kBAAc,OAAO,YAAY;AAAA,EACnC;AACA,MAAI,CAAC,YAAa,OAAM,IAAI,UAAU,gCAAgC;AAEtE,SAAO;AACT;AAOO,IAAM,0BAA0B,OAAO,UAAiC;AAC7E,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,OAAO,wBAAwB,KAAK;AAAA,EAC5C,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAOO,IAAM,kBAAkB,OAAO,OAAe,gBAAuC;AAC1F,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,aAAa,MAAM,OAAO,QAAQ,OAAO,cAAc;AAC7D,UAAM,cAAc,MAAM,WAAW,OAAO,EAAE,UAAU,YAAY,CAAC;AACrE,UAAM,OAAO,OAAO,WAAW;AAE/B,kBAAc,YAAY,OAAO,IAAI;AACrC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAOO,IAAM,eAAe,OAAO,UAAiC;AAClE,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,aAAa,MAAM,OAAO,QAAQ,OAAO,cAAc;AAC7D,UAAM,OAAO,OAAO,UAAU;AAC9B,kBAAc,YAAY,OAAO,IAAI;AACrC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAOO,IAAM,eAAe,OAAO,OAAe,aAAoC;AACpF,QAAM,SAAS,UAAU;AAEzB,MAAI;AACF,UAAM,aAAa,MAAM,OAAO,aAAa,OAAO,UAAU,cAAc;AAC5E,UAAM,OAAO,OAAO,UAAU;AAC9B,kBAAc,YAAY,OAAO,IAAI;AACrC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAQO,IAAM,oBAAoB,OAAO,UAAiC;AACvE,MAAI,CAAC,UAAU,EAAG,OAAM,IAAI,UAAU,sDAAsD;AAE5F,QAAM,cAAc,MAAM,mBAAmB;AAE7C,MAAI;AACF,UAAM,MAAM,MAAM,YAAY,IAAI;AAClC,UAAM,cAAc,GAAG,OAAO,SAAS,MAAM,GAAG,aAAa;AAE7D,UAAM,MAAM,MAAM,MAAM,GAAG,WAAW,SAAS;AAAA,MAC7C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,GAAG;AAAA,MAC9B;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,oBAAoB,MAAM,CAAC;AAAA,IACpD,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,YAAa,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,UAAU,UAAU,OAAO,qCAAqC,IAAI,MAAM,KAAK,IAAI,MAAM;AAAA,IACrG;AAEA,UAAM,WAAY,MAAM,IAAI,KAAK;AACjC,UAAM,OAAO,OAAO,QAAQ;AAC5B,kBAAc,YAAY,cAAc,IAAI;AAC5C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;AAUO,IAAM,aAAa,OAAO,YAAwC;AACvE,QAAM,cAAc,MAAM,mBAAmB;AAE7C,MAAI;AACF,UAAM,cAAc,MAAM,YAAY,OAAO,OAAO;AACpD,UAAM,OAAO,OAAO,WAAW;AAC/B,kBAAc,YAAY,cAAc,IAAI;AAC5C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,KAAK,KAAK;AAAA,EAC5B;AACF;;;ACrJA,IAAM,eAAe,MAAsC;AACzD,QAAM,MAAM,mBAAmB;AAC/B,MAAI,CAAC,KAAK,KAAK;AACb,UAAM,IAAI,UAAU,6DAA6D;AAAA,EACnF;AACA,MAAI,CAAC,IAAI,OAAO;AACd,UAAM,IAAI,UAAU,kFAAkF;AAAA,EACxG;AACA,SAAO,EAAE,KAAK,IAAI,KAAK,OAAO,IAAI,MAAM;AAC1C;AAMA,IAAM,aAAa,OAAO,MAAc,UAAuB,CAAC,MAAyB;AACvF,QAAM,EAAE,KAAK,MAAM,IAAI,aAAa;AACpC,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI;AAAA,MACjC,GAAG;AAAA,MACH,SAAS;AAAA,QACP,GAAG,QAAQ;AAAA,QACX,eAAe,UAAU,KAAK;AAAA,QAC9B,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,UAAW,MAAgB,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3E;AACA,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,YAAY,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACnD,UAAM,IAAI,UAAW,UAA8B,OAAO,yBAAyB,IAAI,MAAM,KAAK,IAAI,MAAM;AAAA,EAC9G;AACA,SAAO;AACT;AAGA,IAAM,eAAe,MAAM;AACzB,QAAM,SAAS,UAAU;AACzB,QAAM,OAAO,OAAO,YAAY;AAChC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,UAAU,2DAA2D;AAAA,EACjF;AACA,SAAO;AACT;AAaA,IAAM,YAAY,OAAO,YAAgD;AACvE,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,SAAS,QAAQ,KAAM,QAAO,IAAI,QAAQ,OAAO,QAAQ,IAAI,CAAC;AAClE,QAAI,SAAS,WAAW,KAAM,QAAO,IAAI,YAAY,OAAO,QAAQ,OAAO,CAAC;AAC5E,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,OAAO,eAAe,QAAQ,IAAI,KAAK,KAAK,EAAE;AAEpD,UAAM,MAAM,MAAM,WAAW,IAAI;AACjC,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAO,KAAK,MAAM,IAAI,MAAM;AAAA,EAC9B;AAEA,MAAI;AACF,UAAM,OAAO,aAAa;AAC1B,UAAM,QAAQ,MAAM,KAAK,MAAM,UAAU,EAAE;AAC3C,WAAQ,MAAqB,IAAI,MAAM;AAAA,EACzC,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,IAAI,UAAW,MAAgB,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3E;AACF;AAaA,IAAMC,WAAU,OAAO,WAAkC;AACvD,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,MAAM,MAAM,WAAW,gBAAgB,MAAM,EAAE;AACrD,UAAM,WAAY,MAAM,IAAI,KAAK;AACjC,WAAO,OAAO,QAAQ;AAAA,EACxB;AAEA,MAAI;AACF,UAAM,OAAO,aAAa;AAC1B,UAAM,WAAW,MAAM,KAAK,MAAM,QAAQ,EAAE,IAAI,OAAO,CAAa;AACpE,WAAO,OAAO,QAAQ;AAAA,EACxB,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,IAAI,UAAW,MAAgB,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3E;AACF;AAkBA,IAAM,aAAa,OAAO,WAA4C;AACpE,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,MAAM,MAAM,WAAW,gBAAgB;AAAA,MAC3C,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,OAAO;AAAA,QACd,UAAU,OAAO;AAAA,QACjB,GAAG,OAAO;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AACD,UAAM,WAAY,MAAM,IAAI,KAAK;AACjC,WAAO,OAAO,QAAQ;AAAA,EACxB;AAEA,MAAI;AACF,UAAM,OAAO,aAAa;AAC1B,UAAM,WAAW,MAAM,KAAK,MAAM,WAAW,OAAO,OAAO,OAAO,UAAU;AAAA,MAC1E,GAAG,OAAO;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,WAAO,OAAO,QAAQ;AAAA,EACxB,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,IAAI,UAAW,MAAgB,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3E;AACF;AAaA,IAAMC,cAAa,OAAO,QAAgB,eAAgD;AACxF,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,MAAM,MAAM,WAAW,gBAAgB,MAAM,IAAI;AAAA,MACrD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,UAAU;AAAA,IACjC,CAAC;AACD,UAAM,WAAY,MAAM,IAAI,KAAK;AACjC,WAAO,OAAO,QAAQ;AAAA,EACxB;AAEA,MAAI;AACF,UAAM,OAAO,aAAa;AAC1B,UAAM,WAAW,MAAM,KAAK,MAAM,WAAW,EAAE,IAAI,OAAO,GAAe,UAAU;AACnF,WAAO,OAAO,QAAQ;AAAA,EACxB,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,IAAI,UAAW,MAAgB,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3E;AACF;AAaA,IAAM,aAAa,OAAO,WAAkC;AAC1D,MAAI,CAAC,UAAU,GAAG;AAChB,UAAM,WAAW,gBAAgB,MAAM,IAAI,EAAE,QAAQ,SAAS,CAAC;AAC/D;AAAA,EACF;AAEA,MAAI;AACF,UAAM,OAAO,aAAa;AAC1B,UAAM,KAAK,MAAM,WAAW,EAAE,IAAI,OAAO,CAAa;AAAA,EACxD,SAAS,OAAO;AACd,QAAI,iBAAiB,UAAW,OAAM;AACtC,UAAM,IAAI,UAAW,MAAgB,SAAS,QAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3E;AACF;AAiFO,IAAM,QAAe,EAAE,WAAW,SAAAD,UAAS,YAAY,YAAAC,aAAY,WAAW;","names":["GoTrue","jwt","claims","getUser","updateUser"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/environment.ts","../src/errors.ts","../src/cookies.ts","../src/nextjs.ts","../src/events.ts","../src/refresh.ts","../src/auth.ts","../src/user.ts","../src/config.ts","../src/account.ts","../src/admin.ts"],"sourcesContent":["export type { User } from './user.js'\nexport { getUser, isAuthenticated } from './user.js'\nexport { getIdentityConfig, getSettings } from './config.js'\nexport type { AuthCallback, AuthEvent } from './events.js'\nexport { AUTH_EVENTS, onAuthChange } from './events.js'\nexport type { CallbackResult } from './auth.js'\nexport { login, signup, logout, oauthLogin, handleAuthCallback, hydrateSession } from './auth.js'\nexport { refreshSession } from './refresh.js'\nexport { AuthError, MissingIdentityError } from './errors.js'\nexport type {\n AdminUserUpdates,\n AppMetadata,\n AuthProvider,\n CreateUserParams,\n IdentityConfig,\n ListUsersOptions,\n Settings,\n UserUpdates,\n SignupData,\n} from './types.js'\nexport type { Admin } from './admin.js'\nexport {\n requestPasswordRecovery,\n recoverPassword,\n confirmEmail,\n acceptInvite,\n verifyEmailChange,\n updateUser,\n} from './account.js'\nexport { admin } from './admin.js'\n","/** The supported OAuth and authentication providers. */\nexport const AUTH_PROVIDERS = ['google', 'github', 'gitlab', 'bitbucket', 'facebook', 'saml', 'email'] as const\n\n/** A supported authentication provider name (e.g., `'google'`, `'github'`, `'email'`). */\nexport type AuthProvider = (typeof AUTH_PROVIDERS)[number]\n\n/**\n * Provider and role metadata stored in a user's `app_metadata` field.\n * GoTrue sets `provider` automatically on signup; `roles` controls authorization.\n * Additional keys may be present depending on your Identity configuration.\n *\n * @example\n * ```ts\n * const meta: AppMetadata = {\n * provider: 'github',\n * roles: ['admin'],\n * custom_claim: 'value',\n * }\n * ```\n */\nexport interface AppMetadata {\n provider: AuthProvider\n roles?: string[]\n [key: string]: unknown\n}\n\n/**\n * Identity endpoint configuration for the current environment.\n * In the browser, `url` is derived from `window.location.origin`.\n * On the server, `token` is the operator token for admin operations.\n */\nexport interface IdentityConfig {\n /** The GoTrue API endpoint URL (e.g., `https://example.com/.netlify/identity`). */\n url: string\n /** Operator token for server-side admin requests. Only available in Netlify Functions. */\n token?: string\n}\n\n/**\n * Project-level Identity settings returned by {@link getSettings}.\n * Reflects the configuration in your Netlify dashboard.\n */\nexport interface Settings {\n /** Whether new signups are auto-confirmed (no confirmation email sent). */\n autoconfirm: boolean\n /** Whether new signups are disabled entirely. */\n disableSignup: boolean\n /** Map of provider names to whether they are enabled. */\n providers: Record<AuthProvider, boolean>\n}\n\n/**\n * Fields accepted by {@link updateUser}. All fields are optional.\n * Pass `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).\n *\n * @example\n * ```ts\n * await updateUser({ data: { full_name: 'Jane Doe' } })\n * await updateUser({ email: 'new@example.com' })\n * await updateUser({ password: 'new-password' })\n * ```\n */\nexport interface UserUpdates {\n email?: string\n password?: string\n data?: Record<string, unknown>\n [key: string]: unknown\n}\n\n/**\n * User metadata passed during signup (e.g., `{ full_name: 'Jane Doe' }`).\n * Stored in the user's `user_metadata` field.\n */\nexport type SignupData = Record<string, unknown>\n\n/** GoTrue OAuth2 token response from the /token endpoint. */\nexport interface TokenResponse {\n access_token: string\n token_type: string\n expires_in: number\n refresh_token?: string\n}\n\n/**\n * Fields accepted by {@link admin.updateUser}. All fields are optional.\n *\n * Unlike {@link UserUpdates} (used by the self-service `updateUser`), admin updates\n * can set `role`, force-confirm a user, and write to `app_metadata`.\n *\n * @example\n * ```ts\n * await admin.updateUser(userId, {\n * role: 'editor',\n * confirm: true,\n * app_metadata: { plan: 'pro' },\n * })\n * ```\n */\nexport interface AdminUserUpdates {\n email?: string\n password?: string\n /** The user's role (e.g., `'admin'`, `'editor'`). */\n role?: string\n /** Set to `true` to force-confirm the user's email without sending a confirmation email. */\n confirm?: boolean\n /** Server-managed metadata. Only writable via admin operations. */\n app_metadata?: Record<string, unknown>\n /** User-managed metadata (display name, avatar, preferences, etc.). */\n user_metadata?: Record<string, unknown>\n [key: string]: unknown\n}\n\n/** GoTrue error response body. */\nexport interface GoTrueErrorBody {\n msg?: string\n error_description?: string\n}\n\n/**\n * Options for {@link admin.listUsers}. Only used on the server;\n * pagination is ignored in the browser (gotrue-js limitation).\n */\nexport interface ListUsersOptions {\n /** 1-based page number. */\n page?: number\n /** Number of users per page. */\n perPage?: number\n}\n\n/**\n * Parameters for {@link admin.createUser}.\n *\n * The optional `data` fields are spread as top-level attributes in the GoTrue\n * request body (not nested under `user_metadata`). Use this to set `app_metadata`,\n * `user_metadata`, `role`, or other GoTrue user fields at creation time.\n *\n * @example\n * ```ts\n * await admin.createUser({\n * email: 'jane@example.com',\n * password: 'secret',\n * data: { role: 'editor', user_metadata: { full_name: 'Jane Doe' } },\n * })\n * ```\n */\nexport interface CreateUserParams {\n email: string\n password: string\n /** Additional GoTrue user fields spread into the request body. */\n data?: Record<string, unknown>\n}\n\n/**\n * Cookie interface provided by the Netlify Functions runtime.\n * Used internally for server-side auth cookie management.\n */\nexport interface NetlifyCookies {\n get(name: string): string | undefined\n set(options: {\n name: string\n value: string\n httpOnly: boolean\n secure: boolean\n path: string\n sameSite: 'Strict' | 'Lax' | 'None'\n }): void\n delete(name: string): void\n}\n","import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\nimport { MissingIdentityError } from './errors.js'\n\nexport const IDENTITY_PATH = '/.netlify/identity'\n\nlet goTrueClient: GoTrue | null = null\nlet cachedApiUrl: string | null | undefined\nlet warnedMissingUrl = false\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.location !== 'undefined'\n\n/**\n * Discovers and caches the GoTrue API URL.\n *\n * Browser: uses `window.location.origin` + IDENTITY_PATH.\n * Server: reads from `globalThis.netlifyIdentityContext`.\n */\nconst discoverApiUrl = (): string | null => {\n if (cachedApiUrl !== undefined) return cachedApiUrl\n\n if (isBrowser()) {\n cachedApiUrl = `${window.location.origin}${IDENTITY_PATH}`\n } else {\n const identityContext = getIdentityContext()\n if (identityContext?.url) {\n cachedApiUrl = identityContext.url\n } else if (globalThis.Netlify?.context?.url) {\n cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href\n } else if (typeof process !== 'undefined' && process.env?.URL) {\n cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href\n }\n }\n\n return cachedApiUrl ?? null\n}\n\n/**\n * Returns (and lazily creates) a singleton gotrue-js client.\n * Returns `null` and logs a warning if no identity URL can be discovered.\n */\nexport const getGoTrueClient = (): GoTrue | null => {\n if (goTrueClient) return goTrueClient\n\n const apiUrl = discoverApiUrl()\n if (!apiUrl) {\n if (!warnedMissingUrl) {\n console.warn(\n '@netlify/identity: Could not determine the Identity endpoint URL. ' +\n 'Make sure your site has Netlify Identity enabled, or run your app with `netlify dev`.',\n )\n warnedMissingUrl = true\n }\n return null\n }\n\n goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: false })\n return goTrueClient\n}\n\n/**\n * Returns the singleton gotrue-js client, or throws if Identity is not configured.\n */\nexport const getClient = (): GoTrue => {\n const client = getGoTrueClient()\n if (!client) throw new MissingIdentityError()\n return client\n}\n\n/**\n * Reads the server-side identity context set by the Netlify bootstrap.\n * Returns `null` outside the Netlify serverless environment.\n */\nexport const getIdentityContext = (): IdentityConfig | null => {\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url) {\n return {\n url: identityContext.url,\n token: identityContext.token,\n }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href }\n }\n\n // Fallback: Netlify sets the URL env var on all deployed sites\n const siteUrl = typeof process !== 'undefined' ? process.env?.URL : undefined\n if (siteUrl) {\n return { url: new URL(IDENTITY_PATH, siteUrl).href }\n }\n\n return null\n}\n\n/** Reset cached state for tests. */\nexport const resetTestGoTrueClient = (): void => {\n goTrueClient = null\n cachedApiUrl = undefined\n warnedMissingUrl = false\n}\n","/**\n * Thrown by auth operations when something goes wrong: invalid credentials,\n * network failures, missing runtime context, etc.\n *\n * The `status` field contains the HTTP status code from GoTrue when available\n * (e.g., 401 for bad credentials, 422 for validation errors).\n * The `cause` field preserves the original error for debugging.\n *\n * @example\n * ```ts\n * try {\n * await login(email, password)\n * } catch (error) {\n * if (error instanceof AuthError) {\n * console.error(error.message, error.status)\n * }\n * }\n * ```\n */\nexport class AuthError extends Error {\n override name = 'AuthError'\n /** HTTP status code from GoTrue, if the error originated from an API response. */\n status?: number\n declare cause?: unknown\n\n constructor(message: string, status?: number, options?: { cause?: unknown }) {\n super(message)\n this.status = status\n if (options && 'cause' in options) {\n this.cause = options.cause\n }\n }\n\n static from(error: unknown): AuthError {\n if (error instanceof AuthError) return error\n const message = error instanceof Error ? error.message : String(error)\n return new AuthError(message, undefined, { cause: error })\n }\n}\n\n/**\n * Thrown when a function requires a gotrue-js client but Netlify Identity\n * is not configured (no endpoint URL could be discovered).\n *\n * This typically means the site does not have Identity enabled, or the app\n * is not running via `netlify dev` / deployed on Netlify.\n */\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Netlify Identity is not available.') {\n super(message)\n }\n}\n","import type { NetlifyCookies } from './types.js'\n\nexport const NF_JWT_COOKIE = 'nf_jwt'\nexport const NF_REFRESH_COOKIE = 'nf_refresh'\n\n/** Reads a cookie value from `document.cookie` by name. Returns `null` if not found or not in a browser. */\nexport const getCookie = (name: string): string | null => {\n if (typeof document === 'undefined') return null\n const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}=([^;]*)`))\n if (!match) return null\n try {\n return decodeURIComponent(match[1])\n } catch {\n return match[1]\n }\n}\n\n/** Sets the `nf_jwt` and (optionally) `nf_refresh` auth cookies via the Netlify runtime. */\nexport const setAuthCookies = (cookies: NetlifyCookies, accessToken: string, refreshToken?: string): void => {\n cookies.set({\n name: NF_JWT_COOKIE,\n value: accessToken,\n httpOnly: false,\n secure: true,\n path: '/',\n sameSite: 'Lax',\n })\n\n if (refreshToken) {\n // httpOnly: false because browser-side hydration (backgroundHydrate, hydrateSession)\n // reads nf_refresh via document.cookie to bootstrap the gotrue-js session.\n cookies.set({\n name: NF_REFRESH_COOKIE,\n value: refreshToken,\n httpOnly: false,\n secure: true,\n path: '/',\n sameSite: 'Lax',\n })\n }\n}\n\n/** Deletes both auth cookies via the Netlify runtime. */\nexport const deleteAuthCookies = (cookies: NetlifyCookies): void => {\n cookies.delete(NF_JWT_COOKIE)\n cookies.delete(NF_REFRESH_COOKIE)\n}\n\n/** Sets auth cookies via document.cookie (browser-side). No-op on the server. */\nexport const setBrowserAuthCookies = (accessToken: string, refreshToken?: string): void => {\n if (typeof document === 'undefined') return\n document.cookie = `${NF_JWT_COOKIE}=${encodeURIComponent(accessToken)}; path=/; secure; samesite=lax`\n if (refreshToken) {\n document.cookie = `${NF_REFRESH_COOKIE}=${encodeURIComponent(refreshToken)}; path=/; secure; samesite=lax`\n }\n}\n\n/** Deletes auth cookies via document.cookie (browser-side). No-op on the server. */\nexport const deleteBrowserAuthCookies = (): void => {\n if (typeof document === 'undefined') return\n document.cookie = `${NF_JWT_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`\n document.cookie = `${NF_REFRESH_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`\n}\n\n/** Reads a cookie from the server-side Netlify runtime. Returns `null` if not available. */\nexport const getServerCookie = (name: string): string | null => {\n const cookies = globalThis.Netlify?.context?.cookies\n if (!cookies || typeof cookies.get !== 'function') return null\n return cookies.get(name) ?? null\n}\n","// Minimal declaration so we can use require() without @types/node\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ndeclare const require: ((id: string) => any) | undefined\n\n/**\n * Calls `headers()` from `next/headers` if available, to opt Next.js RSC\n * routes into dynamic rendering. Without this, Next.js may statically\n * optimize pages that call functions in this package, caching the build-time result.\n *\n * Re-throws DynamicServerError so Next.js can catch it and switch to\n * dynamic rendering. Silently ignores if not in a Next.js environment.\n */\nlet nextHeadersFn: (() => unknown) | null | undefined\nexport const triggerNextjsDynamic = (): void => {\n if (nextHeadersFn === null) return\n\n if (nextHeadersFn === undefined) {\n try {\n if (typeof require === 'undefined') {\n nextHeadersFn = null\n return\n }\n const mod = require('next/headers')\n nextHeadersFn = mod.headers\n } catch {\n nextHeadersFn = null\n return\n }\n }\n\n const fn = nextHeadersFn\n if (!fn) return\n\n try {\n fn()\n } catch (e: unknown) {\n // Re-throw DynamicServerError so Next.js can opt into dynamic rendering.\n // These errors have a `digest` property containing 'DYNAMIC_SERVER_USAGE'\n // or a message about bailing out of prerendering.\n if (e instanceof Error && ('digest' in e || /bail\\s*out.*prerende/i.test(e.message))) {\n throw e\n }\n }\n}\n\n/** Reset cached state and optionally inject a headers function. Test use only. */\nexport const resetNextjsState = (headersFn?: (() => unknown) | null): void => {\n nextHeadersFn = headersFn === null ? null : (headersFn ?? undefined)\n}\n","import { getGoTrueClient, isBrowser } from './environment.js'\nimport { toUser, type User } from './user.js'\n\n/**\n * Constants for the auth events emitted by the library.\n * Use these instead of string literals when comparing event types.\n *\n * @example\n * ```ts\n * onAuthChange((event, user) => {\n * if (event === AUTH_EVENTS.LOGIN) console.log('Logged in:', user)\n * if (event === AUTH_EVENTS.RECOVERY) redirect('/reset-password')\n * })\n * ```\n */\nexport const AUTH_EVENTS = {\n LOGIN: 'login',\n LOGOUT: 'logout',\n TOKEN_REFRESH: 'token_refresh',\n USER_UPDATED: 'user_updated',\n RECOVERY: 'recovery',\n} as const\n\n/**\n * Union of all auth event names: `'login' | 'logout' | 'token_refresh' | 'user_updated' | 'recovery'`.\n * Passed as the first argument to {@link AuthCallback} subscribers.\n */\nexport type AuthEvent = (typeof AUTH_EVENTS)[keyof typeof AUTH_EVENTS]\n\n/**\n * Callback function signature for {@link onAuthChange} subscribers.\n * `user` is `null` on logout events.\n */\nexport type AuthCallback = (event: AuthEvent, user: User | null) => void\n\nconst GOTRUE_STORAGE_KEY = 'gotrue.user'\n\nconst listeners = new Set<AuthCallback>()\n\nexport const emitAuthEvent = (event: AuthEvent, user: User | null): void => {\n for (const listener of listeners) {\n try {\n listener(event, user)\n } catch {\n // Prevent one subscriber from breaking others\n }\n }\n}\n\nlet storageListenerAttached = false\n\nconst attachStorageListener = (): void => {\n if (storageListenerAttached || !isBrowser()) return\n storageListenerAttached = true\n\n window.addEventListener('storage', (event: StorageEvent) => {\n if (event.key !== GOTRUE_STORAGE_KEY) return\n\n if (event.newValue) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser()\n emitAuthEvent(AUTH_EVENTS.LOGIN, currentUser ? toUser(currentUser) : null)\n } else {\n emitAuthEvent(AUTH_EVENTS.LOGOUT, null)\n }\n })\n}\n\n/**\n * Subscribes to auth state changes (login, logout, token refresh, user updates,\n * and recovery). Returns an unsubscribe function. No-op on the server.\n *\n * The `'recovery'` event fires when {@link handleAuthCallback} processes a\n * password recovery token. The user is logged in but has not yet set a new\n * password. Redirect them to a password reset form and call\n * `updateUser({ password })` to complete the flow.\n */\nexport const onAuthChange = (callback: AuthCallback): (() => void) => {\n if (!isBrowser()) {\n return () => {}\n }\n\n listeners.add(callback)\n attachStorageListener()\n\n return () => {\n listeners.delete(callback)\n }\n}\n","import { getGoTrueClient, isBrowser, getIdentityContext, IDENTITY_PATH } from './environment.js'\nimport {\n NF_JWT_COOKIE,\n NF_REFRESH_COOKIE,\n setBrowserAuthCookies,\n setAuthCookies,\n deleteAuthCookies,\n getServerCookie,\n} from './cookies.js'\nimport { decodeJwtPayload, toUser } from './user.js'\nimport { AUTH_EVENTS, emitAuthEvent } from './events.js'\nimport { AuthError } from './errors.js'\nimport type { NetlifyCookies, TokenResponse, GoTrueErrorBody } from './types.js'\n\n/** Seconds before expiry to trigger a refresh. */\nconst REFRESH_MARGIN_S = 60\n\nlet refreshTimer: ReturnType<typeof setTimeout> | null = null\n\n/**\n * Starts a browser-side timer that refreshes the access token before it expires\n * and syncs the new token back to the `nf_jwt` cookie. Automatically called by\n * any browser flow that establishes a session (`login`, `signup`,\n * `hydrateSession`, `handleAuthCallback`, `confirmEmail`, `recoverPassword`,\n * `acceptInvite`) and by `getUser` when it finds an existing session.\n * No-op on the server.\n *\n * Safe to call multiple times; restarts the timer with the current token's expiry.\n */\nexport const startTokenRefresh = (): void => {\n if (!isBrowser()) return\n stopTokenRefresh()\n\n const client = getGoTrueClient()\n const user = client?.currentUser()\n if (!user) return\n\n const token = user.tokenDetails()\n if (!token?.expires_at) return\n\n const nowS = Math.floor(Date.now() / 1000)\n const expiresAtS =\n typeof token.expires_at === 'number' && token.expires_at > 1e12\n ? Math.floor(token.expires_at / 1000) // gotrue-js stores expires_at in ms\n : token.expires_at\n const delayMs = Math.max(0, expiresAtS - nowS - REFRESH_MARGIN_S) * 1000\n\n refreshTimer = setTimeout(async () => {\n try {\n const freshJwt = await user.jwt(true)\n const freshDetails = user.tokenDetails()\n setBrowserAuthCookies(freshJwt, freshDetails?.refresh_token)\n emitAuthEvent(AUTH_EVENTS.TOKEN_REFRESH, toUser(user))\n // Schedule next refresh\n startTokenRefresh()\n } catch {\n // Refresh failed (e.g., refresh token revoked). Stop trying.\n stopTokenRefresh()\n }\n }, delayMs)\n}\n\n/**\n * Stops the browser-side auto-refresh timer. Automatically called by `logout`.\n */\nexport const stopTokenRefresh = (): void => {\n if (refreshTimer !== null) {\n clearTimeout(refreshTimer)\n refreshTimer = null\n }\n}\n\n/**\n * Refreshes the session's access token.\n *\n * **Browser:** Token refresh is handled automatically after any browser flow\n * that establishes a session (`login`, `signup`, `hydrateSession`,\n * `handleAuthCallback`, `confirmEmail`, `recoverPassword`, `acceptInvite`)\n * and by `getUser` when it finds an existing session. Calling\n * `refreshSession()` in the browser triggers an\n * immediate refresh if the token is near expiry. Returns the new JWT on\n * success, or `null` if no refresh is needed. Browser-side errors (e.g.,\n * revoked refresh token) do not throw; they return `null`.\n *\n * **Server:** Reads the `nf_jwt` and `nf_refresh` cookies, checks if the token\n * is expired or near expiry, and exchanges the refresh token for a new access\n * token via the Identity `/token` endpoint. Updates both cookies on the response.\n * Call this in framework middleware or at the start of server-side request\n * handlers to ensure subsequent requests carry a valid JWT.\n *\n * Returns the new access token on success, or `null` if no refresh is needed\n * or the refresh token is invalid/missing (400/401).\n *\n * @throws {AuthError} Server-side only: on network failure or when the Identity URL cannot be determined.\n *\n * @example\n * ```ts\n * // In server middleware (e.g., Astro, SvelteKit)\n * import { refreshSession } from '@netlify/identity'\n * await refreshSession()\n * ```\n */\nexport const refreshSession = async (): Promise<string | null> => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const user = client?.currentUser()\n if (!user) return null\n\n // Check if the token is near expiry before refreshing\n const details = user.tokenDetails()\n if (details?.expires_at) {\n const nowS = Math.floor(Date.now() / 1000)\n const expiresAtS =\n typeof details.expires_at === 'number' && details.expires_at > 1e12\n ? Math.floor(details.expires_at / 1000)\n : details.expires_at\n if (expiresAtS - nowS > REFRESH_MARGIN_S) {\n return null\n }\n }\n\n try {\n const jwt = await user.jwt(true)\n setBrowserAuthCookies(jwt, user.tokenDetails()?.refresh_token)\n emitAuthEvent(AUTH_EVENTS.TOKEN_REFRESH, toUser(user))\n startTokenRefresh()\n return jwt\n } catch {\n stopTokenRefresh()\n return null\n }\n }\n\n // Server-side: read cookies, check expiry, refresh if needed\n const accessToken = getServerCookie(NF_JWT_COOKIE)\n const refreshToken = getServerCookie(NF_REFRESH_COOKIE)\n\n if (!accessToken || !refreshToken) return null\n\n const decoded = decodeJwtPayload(accessToken)\n if (!decoded?.exp) return null\n\n const nowS = Math.floor(Date.now() / 1000)\n if (decoded.exp - nowS > REFRESH_MARGIN_S) {\n // Token is still valid, no refresh needed\n return null\n }\n\n // Token is expired or near expiry; exchange refresh token for new access token\n const ctx = getIdentityContext()\n const identityUrl =\n ctx?.url ?? (globalThis.Netlify?.context?.url ? new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href : null)\n\n if (!identityUrl) {\n throw new AuthError('Could not determine the Identity endpoint URL for token refresh')\n }\n\n let res: Response\n try {\n res = await fetch(`${identityUrl}/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token: refreshToken }).toString(),\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!res.ok) {\n // Refresh token is invalid/expired; cannot refresh\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n if (res.status === 401 || res.status === 400) {\n // Invalid refresh token; clear stale cookies so middleware stops retrying\n const cookies = globalThis.Netlify?.context?.cookies as NetlifyCookies | undefined\n if (cookies) {\n deleteAuthCookies(cookies)\n }\n return null\n }\n throw new AuthError(errorBody.msg || `Token refresh failed (${res.status})`, res.status)\n }\n\n const data = (await res.json()) as TokenResponse\n\n const cookies = globalThis.Netlify?.context?.cookies as NetlifyCookies | undefined\n if (cookies) {\n setAuthCookies(cookies, data.access_token, data.refresh_token)\n }\n\n return data.access_token\n}\n","import type GoTrue from 'gotrue-js'\nimport type { UserData } from 'gotrue-js'\nimport type { AuthProvider, NetlifyCookies, SignupData, TokenResponse, GoTrueErrorBody } from './types.js'\nimport { toUser, decodeJwtPayload } from './user.js'\n\nimport { getClient, getIdentityContext, isBrowser, IDENTITY_PATH } from './environment.js'\nimport {\n getCookie,\n setAuthCookies,\n deleteAuthCookies,\n setBrowserAuthCookies,\n deleteBrowserAuthCookies,\n NF_JWT_COOKIE,\n NF_REFRESH_COOKIE,\n} from './cookies.js'\nimport { AuthError } from './errors.js'\nimport { AUTH_EVENTS, emitAuthEvent } from './events.js'\nimport { startTokenRefresh, stopTokenRefresh } from './refresh.js'\n\nconst getCookies = (): NetlifyCookies => {\n const cookies = globalThis.Netlify?.context?.cookies\n if (!cookies) {\n throw new AuthError('Server-side auth requires Netlify Functions runtime')\n }\n return cookies\n}\n\nconst getServerIdentityUrl = (): string => {\n const ctx = getIdentityContext()\n if (!ctx?.url) {\n throw new AuthError('Could not determine the Identity endpoint URL on the server')\n }\n return ctx.url\n}\n\n/** Persist the session to localStorage so it survives page reloads. */\nexport const persistSession = true\n\n/**\n * Logs in with email and password. Works in both browser and server contexts.\n *\n * On success, sets `nf_jwt` and `nf_refresh` cookies and returns the authenticated {@link User}.\n * In the browser, also emits a `'login'` event via {@link onAuthChange}.\n *\n * @throws {AuthError} On invalid credentials, network failure, or missing Netlify runtime.\n *\n * @remarks\n * In Next.js server actions, call `redirect()` **after** `login()` returns, not inside a\n * try/catch. Next.js implements `redirect()` by throwing a special error; wrapping it in\n * try/catch will swallow the redirect.\n *\n * @example\n * ```ts\n * // Next.js server action\n * const user = await login(email, password)\n * redirect('/dashboard') // after login, not inside try/catch\n * ```\n */\nexport const login = async (email: string, password: string): Promise<import('./user.js').User> => {\n if (!isBrowser()) {\n const identityUrl = getServerIdentityUrl()\n const cookies = getCookies()\n\n const body = new URLSearchParams({\n grant_type: 'password',\n username: email,\n password,\n })\n\n let res: Response\n try {\n res = await fetch(`${identityUrl}/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!res.ok) {\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || errorBody.error_description || `Login failed (${res.status})`, res.status)\n }\n\n const data = (await res.json()) as TokenResponse\n const accessToken = data.access_token\n\n let userRes: Response\n try {\n userRes = await fetch(`${identityUrl}/user`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!userRes.ok) {\n const errorBody = (await userRes.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || `Failed to fetch user data (${userRes.status})`, userRes.status)\n }\n\n const userData = (await userRes.json()) as UserData\n const user = toUser(userData)\n\n setAuthCookies(cookies, accessToken, data.refresh_token)\n\n return user\n }\n\n const client = getClient()\n\n try {\n const gotrueUser = await client.login(email, password, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token)\n const user = toUser(gotrueUser)\n startTokenRefresh()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Creates a new account. Works in both browser and server contexts.\n *\n * If autoconfirm is enabled in your Identity settings, the user is logged in immediately:\n * cookies are set and a `'login'` event is emitted. If autoconfirm is **disabled** (the default),\n * the user receives a confirmation email and must click the link before they can log in.\n * In that case, no cookies are set and no auth event is emitted.\n *\n * @throws {AuthError} On duplicate email, validation failure, network error, or missing Netlify runtime.\n */\nexport const signup = async (email: string, password: string, data?: SignupData): Promise<import('./user.js').User> => {\n if (!isBrowser()) {\n const identityUrl = getServerIdentityUrl()\n const cookies = getCookies()\n\n let res: Response\n try {\n res = await fetch(`${identityUrl}/signup`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password, data }),\n })\n } catch (error) {\n throw AuthError.from(error)\n }\n\n if (!res.ok) {\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || `Signup failed (${res.status})`, res.status)\n }\n\n const responseData = (await res.json()) as UserData & Partial<TokenResponse>\n const user = toUser(responseData)\n\n if (responseData.confirmed_at) {\n const accessToken = responseData.access_token\n if (accessToken) {\n setAuthCookies(cookies, accessToken, responseData.refresh_token)\n }\n }\n\n return user\n }\n\n const client = getClient()\n\n try {\n const response = await client.signup(email, password, data)\n const user = toUser(response as UserData)\n if (response.confirmed_at) {\n const jwt = await (response as { jwt?: () => Promise<string> }).jwt?.()\n if (jwt) {\n const refreshToken = (response as { tokenDetails?: () => { refresh_token: string } | null }).tokenDetails?.()\n ?.refresh_token\n setBrowserAuthCookies(jwt, refreshToken)\n }\n startTokenRefresh()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n }\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Logs out the current user and clears the session. Works in both browser and server contexts.\n *\n * Always deletes `nf_jwt` and `nf_refresh` cookies, even if the server-side token\n * invalidation request fails. In the browser, emits a `'logout'` event via {@link onAuthChange}.\n *\n * @throws {AuthError} On missing Netlify runtime (server) or logout failure (browser).\n */\nexport const logout = async (): Promise<void> => {\n if (!isBrowser()) {\n const identityUrl = getServerIdentityUrl()\n const cookies = getCookies()\n\n const jwt = cookies.get(NF_JWT_COOKIE)\n if (jwt) {\n try {\n await fetch(`${identityUrl}/logout`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${jwt}` },\n })\n } catch {\n // Best-effort: token invalidation may fail, but we always clear cookies below\n }\n }\n\n deleteAuthCookies(cookies)\n return\n }\n\n const client = getClient()\n\n try {\n const currentUser = client.currentUser()\n if (currentUser) {\n await currentUser.logout()\n }\n deleteBrowserAuthCookies()\n stopTokenRefresh()\n emitAuthEvent(AUTH_EVENTS.LOGOUT, null)\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Initiates an OAuth login by redirecting to the given provider (e.g., `'google'`, `'github'`).\n * The page navigates away; this function never returns normally. Browser only.\n *\n * After the provider redirects back, call {@link handleAuthCallback} on page load\n * to complete the login and obtain the {@link User}.\n *\n * @throws {AuthError} If called on the server.\n */\nexport const oauthLogin = (provider: AuthProvider): never => {\n if (!isBrowser()) {\n throw new AuthError('oauthLogin() is only available in the browser')\n }\n const client = getClient()\n\n window.location.href = client.loginExternalUrl(provider)\n throw new AuthError('Redirecting to OAuth provider')\n}\n\n/**\n * Result returned by {@link handleAuthCallback} after processing a URL hash.\n *\n * - `'oauth'`: OAuth provider redirect completed. `user` is the authenticated user.\n * - `'confirmation'`: Email confirmed via token. `user` is the confirmed user.\n * - `'recovery'`: Password recovery token redeemed. `user` is logged in but must set a new password.\n * - `'invite'`: Invite token found. `user` is `null`; `token` contains the invite token for {@link acceptInvite}.\n * - `'email_change'`: Email change verified. `user` reflects the updated email.\n *\n * @example\n * ```ts\n * const result = await handleAuthCallback()\n * if (result?.type === 'recovery') {\n * redirect('/reset-password')\n * } else if (result?.type === 'invite') {\n * redirect(`/join?token=${result.token}`)\n * }\n * ```\n */\nexport interface CallbackResult {\n /** The type of auth callback that was processed. */\n type: 'oauth' | 'confirmation' | 'recovery' | 'invite' | 'email_change'\n /** The authenticated user, or `null` for invite callbacks. */\n user: import('./user.js').User | null\n /** The invite token, only present when `type` is `'invite'`. */\n token?: string\n}\n\n/**\n * Processes the URL hash after an OAuth redirect, email confirmation, password\n * recovery, invite acceptance, or email change. Call on page load. Browser only.\n * Returns `null` if the hash contains no auth parameters.\n *\n * Call this early in your app's initialization (e.g., in a layout component or\n * root loader), **not** inside a route that requires authentication, because\n * the callback URL must match the page where this function runs.\n *\n * For recovery callbacks (`result.type === 'recovery'`), the user is logged in\n * but has **not** set a new password yet. Your app must check the result type\n * and redirect to a password form that calls `updateUser({ password })`.\n * A `'recovery'` event (not `'login'`) is emitted via {@link onAuthChange}.\n *\n * @throws {AuthError} If the callback token is invalid or the verification request fails.\n */\nexport const handleAuthCallback = async (): Promise<CallbackResult | null> => {\n if (!isBrowser()) return null\n\n const hash = window.location.hash.substring(1)\n if (!hash) return null\n\n const client = getClient()\n const params = new URLSearchParams(hash)\n\n try {\n const accessToken = params.get('access_token')\n if (accessToken) return await handleOAuthCallback(client, params, accessToken)\n\n const confirmationToken = params.get('confirmation_token')\n if (confirmationToken) return await handleConfirmationCallback(client, confirmationToken)\n\n const recoveryToken = params.get('recovery_token')\n if (recoveryToken) return await handleRecoveryCallback(client, recoveryToken)\n\n const inviteToken = params.get('invite_token')\n if (inviteToken) return handleInviteCallback(inviteToken)\n\n const emailChangeToken = params.get('email_change_token')\n if (emailChangeToken) return await handleEmailChangeCallback(client, emailChangeToken)\n\n return null\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw AuthError.from(error)\n }\n}\n\nconst handleOAuthCallback = async (\n client: GoTrue,\n params: URLSearchParams,\n accessToken: string,\n): Promise<CallbackResult> => {\n const refreshToken = params.get('refresh_token') ?? ''\n const expiresIn = parseInt(params.get('expires_in') ?? '', 10)\n const expiresAt = parseInt(params.get('expires_at') ?? '', 10)\n const gotrueUser = await client.createUser(\n {\n access_token: accessToken,\n token_type: (params.get('token_type') as 'bearer') ?? 'bearer',\n expires_in: isFinite(expiresIn) ? expiresIn : 3600,\n expires_at: isFinite(expiresAt) ? expiresAt : Math.floor(Date.now() / 1000) + 3600,\n refresh_token: refreshToken,\n },\n persistSession,\n )\n setBrowserAuthCookies(accessToken, refreshToken || undefined)\n const user = toUser(gotrueUser)\n startTokenRefresh()\n clearHash()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return { type: 'oauth', user }\n}\n\nconst handleConfirmationCallback = async (client: GoTrue, token: string): Promise<CallbackResult> => {\n const gotrueUser = await client.confirm(token, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token)\n const user = toUser(gotrueUser)\n startTokenRefresh()\n clearHash()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return { type: 'confirmation', user }\n}\n\nconst handleRecoveryCallback = async (client: GoTrue, token: string): Promise<CallbackResult> => {\n const gotrueUser = await client.recover(token, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token)\n const user = toUser(gotrueUser)\n startTokenRefresh()\n clearHash()\n emitAuthEvent(AUTH_EVENTS.RECOVERY, user)\n return { type: 'recovery', user }\n}\n\nconst handleInviteCallback = (token: string): CallbackResult => {\n clearHash()\n return { type: 'invite', user: null, token }\n}\n\nconst handleEmailChangeCallback = async (client: GoTrue, emailChangeToken: string): Promise<CallbackResult> => {\n const currentUser = client.currentUser()\n if (!currentUser) {\n throw new AuthError('Email change verification requires an active browser session')\n }\n\n const jwt = await currentUser.jwt()\n const identityUrl = `${window.location.origin}${IDENTITY_PATH}`\n\n const emailChangeRes = await fetch(`${identityUrl}/user`, {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${jwt}`,\n },\n body: JSON.stringify({ email_change_token: emailChangeToken }),\n })\n\n if (!emailChangeRes.ok) {\n const errorBody = (await emailChangeRes.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(\n errorBody.msg || `Email change verification failed (${emailChangeRes.status})`,\n emailChangeRes.status,\n )\n }\n\n const emailChangeData = (await emailChangeRes.json()) as UserData\n const user = toUser(emailChangeData)\n clearHash()\n emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user)\n return { type: 'email_change', user }\n}\n\nconst clearHash = (): void => {\n history.replaceState(null, '', window.location.pathname + window.location.search)\n}\n\n/**\n * Hydrates the browser-side gotrue-js session from server-set auth cookies.\n * Call this on page load when using server-side login to enable browser\n * account operations (updateUser, verifyEmailChange, etc.).\n *\n * No-op if a browser session already exists or no auth cookies are present.\n * No-op on the server.\n */\nexport const hydrateSession = async (): Promise<import('./user.js').User | null> => {\n if (!isBrowser()) return null\n\n const client = getClient()\n const currentUser = client.currentUser()\n if (currentUser) {\n startTokenRefresh()\n return toUser(currentUser)\n }\n\n const accessToken = getCookie(NF_JWT_COOKIE)\n if (!accessToken) return null\n\n const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? ''\n\n const decoded = decodeJwtPayload(accessToken)\n const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1000) + 3600\n const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1000))\n\n let gotrueUser\n try {\n gotrueUser = await client.createUser(\n {\n access_token: accessToken,\n token_type: 'bearer',\n expires_in: expiresIn,\n expires_at: expiresAt,\n refresh_token: refreshToken,\n },\n persistSession,\n )\n } catch {\n deleteBrowserAuthCookies()\n return null\n }\n\n const user = toUser(gotrueUser)\n startTokenRefresh()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n}\n","import type { UserData } from 'gotrue-js'\nimport { AUTH_PROVIDERS, type AuthProvider } from './types.js'\nimport { getGoTrueClient, getIdentityContext, isBrowser, IDENTITY_PATH } from './environment.js'\nimport { getCookie, getServerCookie, NF_JWT_COOKIE } from './cookies.js'\nimport { triggerNextjsDynamic } from './nextjs.js'\nimport { hydrateSession } from './auth.js'\nimport { startTokenRefresh } from './refresh.js'\n\n/** Decoded JWT claims from the Identity token. Used internally to construct {@link User}. */\nexport interface IdentityUser {\n sub?: string\n email?: string\n exp?: number\n app_metadata?: Record<string, unknown>\n user_metadata?: Record<string, unknown>\n [key: string]: unknown\n}\n\nconst toAuthProvider = (value: unknown): AuthProvider | undefined =>\n typeof value === 'string' && (AUTH_PROVIDERS as readonly string[]).includes(value)\n ? (value as AuthProvider)\n : undefined\n\nconst toRoles = (appMeta: Record<string, unknown>): string[] | undefined => {\n const roles = appMeta.roles\n if (Array.isArray(roles) && roles.every((r) => typeof r === 'string')) {\n return roles as string[]\n }\n return undefined\n}\n\n/**\n * A normalized user object returned by all auth and admin functions.\n * Provides a consistent shape regardless of whether the user was loaded\n * from gotrue-js, a JWT cookie, or the server-side identity context.\n *\n * @example\n * ```ts\n * const user = await getUser()\n * if (user) {\n * console.log(user.email, user.name, user.roles)\n * }\n * ```\n */\nexport interface User {\n /** The user's unique identifier (GoTrue UUID). */\n id: string\n /** The user's email address. */\n email?: string\n /** `true` if the user's email has been confirmed. */\n emailVerified?: boolean\n /** ISO 8601 timestamp of when the account was created. */\n createdAt?: string\n /** ISO 8601 timestamp of the last account update. */\n updatedAt?: string\n /** The authentication provider used to create the account. */\n provider?: AuthProvider\n /** Display name from `user_metadata.full_name` or `user_metadata.name`. */\n name?: string\n /** Avatar URL from `user_metadata.avatar_url`. */\n pictureUrl?: string\n /** Roles from `app_metadata.roles`, set via the admin API or Netlify UI. */\n roles?: string[]\n /** The full `user_metadata` object. */\n metadata?: Record<string, unknown>\n /** The raw GoTrue user data, for accessing fields not mapped to this interface. */\n rawGoTrueData?: Record<string, unknown>\n}\n\nexport const toUser = (userData: UserData): User => {\n const userMeta = userData.user_metadata ?? {}\n const appMeta = userData.app_metadata ?? {}\n const name = userMeta.full_name || userMeta.name\n const pictureUrl = userMeta.avatar_url\n\n return {\n id: userData.id,\n email: userData.email,\n emailVerified: !!userData.confirmed_at,\n createdAt: userData.created_at,\n updatedAt: userData.updated_at,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n roles: toRoles(appMeta),\n metadata: userMeta,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts JWT claims into a User. Used as a fallback when the full GoTrue\n * user object is unavailable (e.g., GoTrue is unreachable on the server).\n */\nconst claimsToUser = (claims: IdentityUser): User => {\n const appMeta = claims.app_metadata ?? {}\n const userMeta = claims.user_metadata ?? {}\n const name = userMeta.full_name || userMeta.name\n const pictureUrl = userMeta.avatar_url\n\n return {\n id: claims.sub ?? '',\n email: claims.email,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n roles: toRoles(appMeta),\n metadata: userMeta,\n }\n}\n\n/** Decodes a JWT payload without verifying the signature. */\nexport const decodeJwtPayload = (token: string): IdentityUser | null => {\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return null\n const payload = atob(parts[1].replace(/-/g, '+').replace(/_/g, '/'))\n return JSON.parse(payload) as IdentityUser\n } catch {\n return null\n }\n}\n\n/**\n * Fetches the full user object from GoTrue using the JWT.\n * Returns null if the fetch fails (GoTrue unreachable, invalid token, etc.).\n */\nconst fetchFullUser = async (identityUrl: string, jwt: string): Promise<User | null> => {\n try {\n const res = await fetch(`${identityUrl}/user`, {\n headers: { Authorization: `Bearer ${jwt}` },\n })\n if (!res.ok) return null\n const userData = (await res.json()) as UserData\n return toUser(userData)\n } catch {\n return null\n }\n}\n\n/**\n * Resolves the Identity URL from available sources, or null if not discoverable.\n */\nconst resolveIdentityUrl = (): string | null => {\n const identityContext = getIdentityContext()\n if (identityContext?.url) return identityContext.url\n\n if (globalThis.Netlify?.context?.url) {\n return new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href\n }\n\n const siteUrl = typeof process !== 'undefined' ? process.env?.URL : undefined\n if (siteUrl) {\n return new URL(IDENTITY_PATH, siteUrl).href\n }\n\n return null\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n * Never throws; returns `null` on any failure.\n *\n * Always returns a full {@link User} object with all available fields\n * (email, roles, timestamps, metadata, etc.) regardless of whether the\n * call happens in the browser or on the server.\n *\n * In the browser, checks gotrue-js localStorage first. If no localStorage\n * session exists, hydrates from the `nf_jwt` cookie (set by server-side login).\n *\n * On the server, fetches the full user from GoTrue using the JWT from\n * the request. Falls back to JWT claims if GoTrue is unreachable.\n *\n * On the server in a Next.js App Router context, calls `headers()` from\n * `next/headers` to opt the route into dynamic rendering. Without this,\n * Next.js may statically cache the page at build time.\n */\nexport const getUser = async (): Promise<User | null> => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n\n if (currentUser) {\n // If gotrue-js has a localStorage session but the nf_jwt cookie is gone,\n // the server logged us out. Clear the stale localStorage session.\n const jwt = getCookie(NF_JWT_COOKIE)\n if (!jwt) {\n try {\n currentUser.clearSession()\n } catch {\n // best-effort cleanup\n }\n return null\n }\n startTokenRefresh()\n return toUser(currentUser)\n }\n\n // No gotrue-js session but cookie exists: hydrate to get the full user\n const jwt = getCookie(NF_JWT_COOKIE)\n if (!jwt) return null\n\n // Verify the cookie contains a decodable JWT before attempting hydration\n const claims = decodeJwtPayload(jwt)\n if (!claims) return null\n\n const hydrated = await hydrateSession()\n return hydrated ?? null\n }\n\n // Trigger Next.js dynamic rendering if in a Next.js RSC context\n triggerNextjsDynamic()\n\n // Get the JWT from the identity context header or cookie\n const identityContext = globalThis.netlifyIdentityContext\n const serverJwt = identityContext?.token || getServerCookie(NF_JWT_COOKIE)\n\n // Try to fetch the full user from GoTrue for a complete User object\n if (serverJwt) {\n const identityUrl = resolveIdentityUrl()\n if (identityUrl) {\n const fullUser = await fetchFullUser(identityUrl, serverJwt)\n if (fullUser) return fullUser\n }\n }\n\n // Fallback: only use server-validated identity context, never decode an unverified cookie\n const claims = identityContext?.user ?? null\n return claims ? claimsToUser(claims) : null\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n * Never throws; returns `false` on any failure.\n */\nexport const isAuthenticated = async (): Promise<boolean> => (await getUser()) !== null\n","import type { AuthProvider, IdentityConfig, Settings } from './types.js'\nimport { getClient, getIdentityContext, IDENTITY_PATH, isBrowser } from './environment.js'\nimport { AuthError } from './errors.js'\n\n/**\n * Returns the identity configuration for the current environment.\n * Browser: always returns `{ url }` derived from `window.location.origin`.\n * Server: returns `{ url, token }` from the identity context, or `null` if unavailable.\n * Never throws.\n */\nexport const getIdentityConfig = (): IdentityConfig | null => {\n if (isBrowser()) {\n return { url: `${window.location.origin}${IDENTITY_PATH}` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches your project's Identity settings (enabled providers, autoconfirm, signup disabled).\n *\n * @throws {MissingIdentityError} If Identity is not configured.\n * @throws {AuthError} If the endpoint is unreachable.\n */\nexport const getSettings = async (): Promise<Settings> => {\n const client = getClient()\n\n try {\n const raw = await client.settings()\n const external: Partial<Record<AuthProvider, boolean>> = raw.external ?? {}\n return {\n autoconfirm: raw.autoconfirm,\n disableSignup: raw.disable_signup,\n providers: {\n google: external.google ?? false,\n github: external.github ?? false,\n gitlab: external.gitlab ?? false,\n bitbucket: external.bitbucket ?? false,\n facebook: external.facebook ?? false,\n email: external.email ?? false,\n saml: external.saml ?? false,\n },\n }\n } catch (err) {\n throw new AuthError(err instanceof Error ? err.message : 'Failed to fetch identity settings', 502, { cause: err })\n }\n}\n","import type { UserData, User as GoTrueUser } from 'gotrue-js'\n\nimport type { UserUpdates, GoTrueErrorBody } from './types.js'\nimport type { User } from './user.js'\nimport { toUser } from './user.js'\nimport { getClient, isBrowser, IDENTITY_PATH } from './environment.js'\nimport { persistSession, hydrateSession } from './auth.js'\nimport { AUTH_EVENTS, emitAuthEvent } from './events.js'\nimport { AuthError } from './errors.js'\nimport { startTokenRefresh } from './refresh.js'\n\n/**\n * Returns the current gotrue-js user, attempting hydration from cookies if\n * no in-memory session exists. Throws if no user can be resolved.\n */\nconst resolveCurrentUser = async (): Promise<GoTrueUser> => {\n const client = getClient()\n\n let currentUser = client.currentUser()\n if (!currentUser && isBrowser()) {\n try {\n await hydrateSession()\n } catch {\n // hydration failed (e.g. expired cookie, network error) — fall through\n }\n currentUser = client.currentUser()\n }\n if (!currentUser) throw new AuthError('No user is currently logged in')\n\n return currentUser\n}\n\n/**\n * Sends a password recovery email to the given address.\n *\n * @throws {AuthError} On network failure or if the request is rejected.\n */\nexport const requestPasswordRecovery = async (email: string): Promise<void> => {\n const client = getClient()\n\n try {\n await client.requestPasswordRecovery(email)\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Redeems a recovery token and sets a new password. Logs the user in on success.\n *\n * @throws {AuthError} If the token is invalid, expired, or the update fails.\n */\nexport const recoverPassword = async (token: string, newPassword: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.recover(token, persistSession)\n const updatedUser = await gotrueUser.update({ password: newPassword })\n const user = toUser(updatedUser)\n startTokenRefresh()\n // Emits LOGIN because the recovery is fully complete\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Confirms an email address using the token from a confirmation email. Logs the user in on success.\n *\n * @throws {AuthError} If the token is invalid or expired.\n */\nexport const confirmEmail = async (token: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.confirm(token, persistSession)\n const user = toUser(gotrueUser)\n startTokenRefresh()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Accepts an invite token and sets a password for the new account. Logs the user in on success.\n *\n * @throws {AuthError} If the token is invalid or expired.\n */\nexport const acceptInvite = async (token: string, password: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.acceptInvite(token, password, persistSession)\n const user = toUser(gotrueUser)\n startTokenRefresh()\n emitAuthEvent(AUTH_EVENTS.LOGIN, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n\n/**\n * Verifies an email change using the token from a verification email.\n * Auto-hydrates from auth cookies if no browser session exists. Browser only.\n *\n * @throws {AuthError} If called on the server, no user is logged in, or the token is invalid.\n */\nexport const verifyEmailChange = async (token: string): Promise<User> => {\n if (!isBrowser()) throw new AuthError('verifyEmailChange() is only available in the browser')\n\n const currentUser = await resolveCurrentUser()\n\n try {\n const jwt = await currentUser.jwt()\n const identityUrl = `${window.location.origin}${IDENTITY_PATH}`\n\n const res = await fetch(`${identityUrl}/user`, {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${jwt}`,\n },\n body: JSON.stringify({ email_change_token: token }),\n })\n\n if (!res.ok) {\n const errorBody = (await res.json().catch(() => ({}))) as GoTrueErrorBody\n throw new AuthError(errorBody.msg || `Email change verification failed (${res.status})`, res.status)\n }\n\n const userData = (await res.json()) as UserData\n const user = toUser(userData)\n emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user)\n return user\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw AuthError.from(error)\n }\n}\n\n/**\n * Updates the current user's email, password, or user metadata.\n * Auto-hydrates from auth cookies if no browser session exists.\n *\n * @param updates - Fields to update. Pass `email` or `password` to change credentials,\n * or `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).\n * @throws {AuthError} If no user is logged in or the update fails.\n */\nexport const updateUser = async (updates: UserUpdates): Promise<User> => {\n const currentUser = await resolveCurrentUser()\n\n try {\n const updatedUser = await currentUser.update(updates)\n const user = toUser(updatedUser)\n emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user)\n return user\n } catch (error) {\n throw AuthError.from(error)\n }\n}\n","import type { UserData } from 'gotrue-js'\n\nimport { isBrowser, getClient, getIdentityContext } from './environment.js'\nimport { AuthError } from './errors.js'\nimport type { AdminUserUpdates, CreateUserParams, GoTrueErrorBody, ListUsersOptions } from './types.js'\nimport { toUser, type User } from './user.js'\n\n/**\n * Returns the operator token and Identity URL for server-side admin requests.\n * @throws {AuthError} If the Identity endpoint URL or operator token is unavailable.\n */\nconst getAdminAuth = (): { url: string; token: string } => {\n const ctx = getIdentityContext()\n if (!ctx?.url) {\n throw new AuthError('Could not determine the Identity endpoint URL on the server')\n }\n if (!ctx.token) {\n throw new AuthError('Admin operations require an operator token (only available in Netlify Functions)')\n }\n return { url: ctx.url, token: ctx.token }\n}\n\n/**\n * Makes an authenticated admin request to GoTrue on the server.\n * @throws {AuthError} If the request fails or GoTrue returns a non-OK status.\n */\nconst adminFetch = async (path: string, options: RequestInit = {}): Promise<Response> => {\n const { url, token } = getAdminAuth()\n let res: Response\n try {\n res = await fetch(`${url}${path}`, {\n ...options,\n headers: {\n ...options.headers,\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n })\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n if (!res.ok) {\n const errorBody = await res.json().catch(() => ({}))\n throw new AuthError((errorBody as GoTrueErrorBody).msg || `Admin request failed (${res.status})`, res.status)\n }\n return res\n}\n\n/** Returns the current user (browser only), throwing if not logged in. */\nconst getAdminUser = () => {\n const client = getClient()\n const user = client.currentUser()\n if (!user) {\n throw new AuthError('Admin operations require a logged-in user with admin role')\n }\n return user\n}\n\n/**\n * Lists all users. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users` with the operator token. Pagination\n * options (`page`, `perPage`) are forwarded as query parameters.\n *\n * **Browser:** calls gotrue-js `user.admin.listUsers()`. The logged-in user must\n * have an admin role. Pagination options are ignored (gotrue-js does not support them).\n *\n * @throws {AuthError} If the operator token is missing (server) or no admin user is logged in (browser).\n */\nconst listUsers = async (options?: ListUsersOptions): Promise<User[]> => {\n if (!isBrowser()) {\n const params = new URLSearchParams()\n if (options?.page != null) params.set('page', String(options.page))\n if (options?.perPage != null) params.set('per_page', String(options.perPage))\n const query = params.toString()\n const path = `/admin/users${query ? `?${query}` : ''}`\n\n const res = await adminFetch(path)\n const body = (await res.json()) as { users: UserData[] }\n return body.users.map(toUser)\n }\n\n try {\n const user = getAdminUser()\n const users = await user.admin.listUsers('')\n return (users as UserData[]).map(toUser)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Gets a single user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.getUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\nconst getUser = async (userId: string): Promise<User> => {\n if (!isBrowser()) {\n const res = await adminFetch(`/admin/users/${userId}`)\n const userData = (await res.json()) as UserData\n return toUser(userData)\n }\n\n try {\n const user = getAdminUser()\n const userData = await user.admin.getUser({ id: userId } as UserData)\n return toUser(userData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Creates a new user. The user is auto-confirmed (no confirmation email is sent).\n * Works in both server and browser contexts.\n *\n * The optional `data` fields are spread as **top-level attributes** in the GoTrue\n * request body (not nested under `user_metadata`). Use this to set `app_metadata`,\n * `user_metadata`, `role`, or any other GoTrue user field at creation time.\n *\n * **Server:** calls GoTrue `POST /admin/users` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.createUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the email already exists, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\nconst createUser = async (params: CreateUserParams): Promise<User> => {\n if (!isBrowser()) {\n const res = await adminFetch('/admin/users', {\n method: 'POST',\n body: JSON.stringify({\n email: params.email,\n password: params.password,\n ...params.data,\n confirm: true,\n }),\n })\n const userData = (await res.json()) as UserData\n return toUser(userData)\n }\n\n try {\n const user = getAdminUser()\n const userData = await user.admin.createUser(params.email, params.password, {\n ...params.data,\n confirm: true,\n })\n return toUser(userData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Updates an existing user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `PUT /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.updateUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the update fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\nconst updateUser = async (userId: string, attributes: AdminUserUpdates): Promise<User> => {\n if (!isBrowser()) {\n const res = await adminFetch(`/admin/users/${userId}`, {\n method: 'PUT',\n body: JSON.stringify(attributes),\n })\n const userData = (await res.json()) as UserData\n return toUser(userData)\n }\n\n try {\n const user = getAdminUser()\n const userData = await user.admin.updateUser({ id: userId } as UserData, attributes)\n return toUser(userData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * Deletes a user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `DELETE /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.deleteUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the deletion fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\nconst deleteUser = async (userId: string): Promise<void> => {\n if (!isBrowser()) {\n await adminFetch(`/admin/users/${userId}`, { method: 'DELETE' })\n return\n }\n\n try {\n const user = getAdminUser()\n await user.admin.deleteUser({ id: userId } as UserData)\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/**\n * The admin namespace for privileged user management operations.\n * All methods work in both server and browser contexts.\n *\n * **Server:** uses the operator token (automatically available in Netlify Functions).\n * **Browser:** requires a logged-in user with an admin role.\n */\nexport interface Admin {\n /**\n * Lists all users. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users` with the operator token. Pagination\n * options (`page`, `perPage`) are forwarded as query parameters.\n *\n * **Browser:** calls gotrue-js `user.admin.listUsers()`. The logged-in user must\n * have an admin role. Pagination options are ignored (gotrue-js does not support them).\n *\n * @throws {AuthError} If the operator token is missing (server) or no admin user is logged in (browser).\n */\n listUsers: (options?: ListUsersOptions) => Promise<User[]>\n\n /**\n * Gets a single user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `GET /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.getUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\n getUser: (userId: string) => Promise<User>\n\n /**\n * Creates a new user. The user is auto-confirmed (no confirmation email is sent).\n * Works in both server and browser contexts.\n *\n * The optional `data` fields are spread as **top-level attributes** in the GoTrue\n * request body (not nested under `user_metadata`). Use this to set `app_metadata`,\n * `user_metadata`, `role`, or any other GoTrue user field at creation time.\n *\n * **Server:** calls GoTrue `POST /admin/users` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.createUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the email already exists, the operator token is missing (server),\n * or no admin user is logged in (browser).\n */\n createUser: (params: CreateUserParams) => Promise<User>\n\n /**\n * Updates an existing user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `PUT /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.updateUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the update fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\n updateUser: (userId: string, attributes: AdminUserUpdates) => Promise<User>\n\n /**\n * Deletes a user by ID. Works in both server and browser contexts.\n *\n * **Server:** calls GoTrue `DELETE /admin/users/:id` with the operator token.\n *\n * **Browser:** calls gotrue-js `user.admin.deleteUser()`. The logged-in user must\n * have an admin role.\n *\n * @throws {AuthError} If the user is not found, the deletion fails, the operator token\n * is missing (server), or no admin user is logged in (browser).\n */\n deleteUser: (userId: string) => Promise<void>\n}\n\nexport const admin: Admin = { listUsers, getUser, createUser, updateUser, deleteUser }\n"],"mappings":"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","names":["GoTrue","nowS","cookies","jwt","claims","getUser","updateUser"]}
package/dist/index.d.cts CHANGED
@@ -166,6 +166,7 @@ interface User {
166
166
  }
167
167
  /**
168
168
  * Returns the currently authenticated user, or `null` if not logged in.
169
+ * Never throws; returns `null` on any failure.
169
170
  *
170
171
  * Always returns a full {@link User} object with all available fields
171
172
  * (email, roles, timestamps, metadata, etc.) regardless of whether the
@@ -184,6 +185,7 @@ interface User {
184
185
  declare const getUser: () => Promise<User | null>;
185
186
  /**
186
187
  * Returns `true` if a user is currently authenticated.
188
+ * Never throws; returns `false` on any failure.
187
189
  */
188
190
  declare const isAuthenticated: () => Promise<boolean>;
189
191
 
@@ -292,7 +294,7 @@ declare const logout: () => Promise<void>;
292
294
  *
293
295
  * @throws {AuthError} If called on the server.
294
296
  */
295
- declare const oauthLogin: (provider: string) => never;
297
+ declare const oauthLogin: (provider: AuthProvider) => never;
296
298
  /**
297
299
  * Result returned by {@link handleAuthCallback} after processing a URL hash.
298
300
  *
@@ -347,6 +349,38 @@ declare const handleAuthCallback: () => Promise<CallbackResult | null>;
347
349
  */
348
350
  declare const hydrateSession: () => Promise<User | null>;
349
351
 
352
+ /**
353
+ * Refreshes the session's access token.
354
+ *
355
+ * **Browser:** Token refresh is handled automatically after any browser flow
356
+ * that establishes a session (`login`, `signup`, `hydrateSession`,
357
+ * `handleAuthCallback`, `confirmEmail`, `recoverPassword`, `acceptInvite`)
358
+ * and by `getUser` when it finds an existing session. Calling
359
+ * `refreshSession()` in the browser triggers an
360
+ * immediate refresh if the token is near expiry. Returns the new JWT on
361
+ * success, or `null` if no refresh is needed. Browser-side errors (e.g.,
362
+ * revoked refresh token) do not throw; they return `null`.
363
+ *
364
+ * **Server:** Reads the `nf_jwt` and `nf_refresh` cookies, checks if the token
365
+ * is expired or near expiry, and exchanges the refresh token for a new access
366
+ * token via the Identity `/token` endpoint. Updates both cookies on the response.
367
+ * Call this in framework middleware or at the start of server-side request
368
+ * handlers to ensure subsequent requests carry a valid JWT.
369
+ *
370
+ * Returns the new access token on success, or `null` if no refresh is needed
371
+ * or the refresh token is invalid/missing (400/401).
372
+ *
373
+ * @throws {AuthError} Server-side only: on network failure or when the Identity URL cannot be determined.
374
+ *
375
+ * @example
376
+ * ```ts
377
+ * // In server middleware (e.g., Astro, SvelteKit)
378
+ * import { refreshSession } from '@netlify/identity'
379
+ * await refreshSession()
380
+ * ```
381
+ */
382
+ declare const refreshSession: () => Promise<string | null>;
383
+
350
384
  /**
351
385
  * Thrown by auth operations when something goes wrong: invalid credentials,
352
386
  * network failures, missing runtime context, etc.
@@ -505,4 +539,4 @@ declare const verifyEmailChange: (token: string) => Promise<User>;
505
539
  */
506
540
  declare const updateUser: (updates: UserUpdates) => Promise<User>;
507
541
 
508
- export { AUTH_EVENTS, type Admin, type AdminUserUpdates, type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type CreateUserParams, type IdentityConfig, type ListUsersOptions, MissingIdentityError, type Settings, type SignupData, type User, type UserUpdates, acceptInvite, admin, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, hydrateSession, isAuthenticated, login, logout, oauthLogin, onAuthChange, recoverPassword, requestPasswordRecovery, signup, updateUser, verifyEmailChange };
542
+ export { AUTH_EVENTS, type Admin, type AdminUserUpdates, type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type CreateUserParams, type IdentityConfig, type ListUsersOptions, MissingIdentityError, type Settings, type SignupData, type User, type UserUpdates, acceptInvite, admin, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, hydrateSession, isAuthenticated, login, logout, oauthLogin, onAuthChange, recoverPassword, refreshSession, requestPasswordRecovery, signup, updateUser, verifyEmailChange };
package/dist/index.d.ts CHANGED
@@ -166,6 +166,7 @@ interface User {
166
166
  }
167
167
  /**
168
168
  * Returns the currently authenticated user, or `null` if not logged in.
169
+ * Never throws; returns `null` on any failure.
169
170
  *
170
171
  * Always returns a full {@link User} object with all available fields
171
172
  * (email, roles, timestamps, metadata, etc.) regardless of whether the
@@ -184,6 +185,7 @@ interface User {
184
185
  declare const getUser: () => Promise<User | null>;
185
186
  /**
186
187
  * Returns `true` if a user is currently authenticated.
188
+ * Never throws; returns `false` on any failure.
187
189
  */
188
190
  declare const isAuthenticated: () => Promise<boolean>;
189
191
 
@@ -292,7 +294,7 @@ declare const logout: () => Promise<void>;
292
294
  *
293
295
  * @throws {AuthError} If called on the server.
294
296
  */
295
- declare const oauthLogin: (provider: string) => never;
297
+ declare const oauthLogin: (provider: AuthProvider) => never;
296
298
  /**
297
299
  * Result returned by {@link handleAuthCallback} after processing a URL hash.
298
300
  *
@@ -347,6 +349,38 @@ declare const handleAuthCallback: () => Promise<CallbackResult | null>;
347
349
  */
348
350
  declare const hydrateSession: () => Promise<User | null>;
349
351
 
352
+ /**
353
+ * Refreshes the session's access token.
354
+ *
355
+ * **Browser:** Token refresh is handled automatically after any browser flow
356
+ * that establishes a session (`login`, `signup`, `hydrateSession`,
357
+ * `handleAuthCallback`, `confirmEmail`, `recoverPassword`, `acceptInvite`)
358
+ * and by `getUser` when it finds an existing session. Calling
359
+ * `refreshSession()` in the browser triggers an
360
+ * immediate refresh if the token is near expiry. Returns the new JWT on
361
+ * success, or `null` if no refresh is needed. Browser-side errors (e.g.,
362
+ * revoked refresh token) do not throw; they return `null`.
363
+ *
364
+ * **Server:** Reads the `nf_jwt` and `nf_refresh` cookies, checks if the token
365
+ * is expired or near expiry, and exchanges the refresh token for a new access
366
+ * token via the Identity `/token` endpoint. Updates both cookies on the response.
367
+ * Call this in framework middleware or at the start of server-side request
368
+ * handlers to ensure subsequent requests carry a valid JWT.
369
+ *
370
+ * Returns the new access token on success, or `null` if no refresh is needed
371
+ * or the refresh token is invalid/missing (400/401).
372
+ *
373
+ * @throws {AuthError} Server-side only: on network failure or when the Identity URL cannot be determined.
374
+ *
375
+ * @example
376
+ * ```ts
377
+ * // In server middleware (e.g., Astro, SvelteKit)
378
+ * import { refreshSession } from '@netlify/identity'
379
+ * await refreshSession()
380
+ * ```
381
+ */
382
+ declare const refreshSession: () => Promise<string | null>;
383
+
350
384
  /**
351
385
  * Thrown by auth operations when something goes wrong: invalid credentials,
352
386
  * network failures, missing runtime context, etc.
@@ -505,4 +539,4 @@ declare const verifyEmailChange: (token: string) => Promise<User>;
505
539
  */
506
540
  declare const updateUser: (updates: UserUpdates) => Promise<User>;
507
541
 
508
- export { AUTH_EVENTS, type Admin, type AdminUserUpdates, type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type CreateUserParams, type IdentityConfig, type ListUsersOptions, MissingIdentityError, type Settings, type SignupData, type User, type UserUpdates, acceptInvite, admin, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, hydrateSession, isAuthenticated, login, logout, oauthLogin, onAuthChange, recoverPassword, requestPasswordRecovery, signup, updateUser, verifyEmailChange };
542
+ export { AUTH_EVENTS, type Admin, type AdminUserUpdates, type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type CreateUserParams, type IdentityConfig, type ListUsersOptions, MissingIdentityError, type Settings, type SignupData, type User, type UserUpdates, acceptInvite, admin, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, hydrateSession, isAuthenticated, login, logout, oauthLogin, onAuthChange, recoverPassword, refreshSession, requestPasswordRecovery, signup, updateUser, verifyEmailChange };