@netlify/identity 0.1.1-alpha.2 → 0.1.1-alpha.21

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/user.ts","../src/config.ts","../src/auth.ts","../src/account.ts"],"sourcesContent":["export type { User } from './user.js'\nexport { getUser, isAuthenticated } from './user.js'\nexport { getIdentityConfig, getSettings } from './config.js'\nexport type { AuthCallback, AuthEvent, CallbackResult } from './auth.js'\nexport { login, signup, logout, oauthLogin, onAuthChange, handleAuthCallback } from './auth.js'\nexport { AuthError, MissingIdentityError } from './errors.js'\nexport type { AppMetadata, AuthProvider, IdentityConfig, Settings } from './types.js'\nexport { requestPasswordRecovery, confirmEmail, acceptInvite, verifyEmailChange, updateUser } from './account.js'\n","export const AUTH_PROVIDERS = ['google', 'github', 'gitlab', 'bitbucket', 'facebook', 'saml', 'email'] as const\nexport type AuthProvider = (typeof AUTH_PROVIDERS)[number]\n\nexport interface AppMetadata {\n provider: AuthProvider\n roles?: string[]\n [key: string]: unknown\n}\n\nexport interface IdentityConfig {\n url: string\n token?: string // this is an operator token, only available on the server\n}\n\nexport interface Settings {\n autoconfirm: boolean\n disableSignup: boolean\n providers: Record<AuthProvider, boolean>\n}\n","import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\nimport { MissingIdentityError } from './errors.js'\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` + `/.netlify/identity`.\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}/.netlify/identity`\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('/.netlify/identity', globalThis.Netlify.context.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: isBrowser() })\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 // TODO(kh): After Stargate deploys EX-1764, netlifyIdentityContext will have\n // typed `url` and `token` fields. Remove the typeof guards and use direct access.\n // https://linear.app/netlify/issue/EX-1764/identity-stargate-needs-to-set-identity-url-and-providertoken\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url && typeof identityContext.url === 'string') {\n return {\n url: identityContext.url,\n token: typeof identityContext.token === 'string' ? identityContext.token : undefined,\n }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL('/.netlify/identity', globalThis.Netlify.context.url).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","export class AuthError extends Error {\n override name = 'AuthError'\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\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Identity is not available in this environment') {\n super(message)\n }\n}\n","import type { UserData } from 'gotrue-js'\nimport { AUTH_PROVIDERS, type AuthProvider } from './types.js'\nimport { getGoTrueClient, isBrowser } from './environment.js'\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\nexport interface User {\n id: string\n email?: string\n emailVerified?: boolean\n createdAt?: string\n updatedAt?: string\n provider?: AuthProvider\n name?: string\n pictureUrl?: string\n metadata?: Record<string, unknown>\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 metadata: userMeta,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts raw JWT claims from the identity header into a User.\n * JWT claims use a different shape than the gotrue-js UserData class.\n */\nconst claimsToUser = (claims: Record<string, unknown>): User => {\n const appMeta = (claims.app_metadata ?? {}) as Record<string, unknown>\n const userMeta = (claims.user_metadata ?? {}) as Record<string, unknown>\n const name = userMeta.full_name || userMeta.name\n\n return {\n id: typeof claims.sub === 'string' ? claims.sub : '',\n email: typeof claims.email === 'string' ? claims.email : undefined,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n metadata: userMeta,\n }\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n * Synchronous. Never throws.\n */\nexport const getUser = (): User | null => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n if (!currentUser) return null\n return toUser(currentUser)\n }\n\n const identityContext = globalThis.netlifyIdentityContext\n if (!identityContext) return null\n\n const claims = identityContext.user ?? (identityContext.sub ? identityContext : null)\n if (!claims) return null\n return claimsToUser(claims as Record<string, unknown>)\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = (): boolean => getUser() !== null\n","import type { AuthProvider, IdentityConfig, Settings } from './types.js'\nimport { AuthError } from './errors.js'\nimport { getClient, getIdentityContext, isBrowser } from './environment.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}/.netlify/identity` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches the GoTrue `/settings` endpoint.\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 } from 'gotrue-js'\n\nimport type { AppMetadata } from './types.js'\n\nexport type AuthEvent = 'login' | 'logout' | 'token_refresh' | 'user_updated'\nimport type { User } from './user.js'\nimport { toUser } from './user.js'\nimport { getGoTrueClient, getClient, isBrowser } from './environment.js'\nimport { AuthError } from './errors.js'\n\nexport interface JWTClaims {\n sub: string // UUID\n email: string\n exp: number\n iat: number\n aud: string\n app_metadata: AppMetadata\n user_metadata: Record<string, unknown>\n}\n\nexport type AuthCallback = (event: AuthEvent, user: User | null) => void\n\n/** Persist the session to localStorage so it survives page reloads. */\nexport const persistSession = true\n\nconst listeners = new Set<AuthCallback>()\n\nexport const emitAuthEvent = (event: AuthEvent, user: User | null): void => {\n for (const listener of listeners) {\n listener(event, user)\n }\n}\n\nlet storageListenerAttached = false\n\nconst attachStorageListener = (): void => {\n if (storageListenerAttached) return\n storageListenerAttached = true\n\n window.addEventListener('storage', (event: StorageEvent) => {\n if (event.key !== 'gotrue.user') return\n\n if (event.newValue) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser()\n emitAuthEvent('login', currentUser ? toUser(currentUser) : null)\n } else {\n emitAuthEvent('logout', null)\n }\n })\n}\n\n/**\n * Subscribes to auth state changes (login, logout, token refresh, user updates).\n * Returns an unsubscribe function. No-op on the server.\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\n/** Logs in with email and password. Browser only. */\nexport const login = async (email: string, password: string): Promise<User> => {\n const client = getClient()\n\n try {\n const gotrueUser = await client.login(email, password, persistSession)\n const user = toUser(gotrueUser)\n emitAuthEvent('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Creates a new account. Emits 'login' if autoconfirm is enabled. Browser only. */\nexport const signup = async (email: string, password: string, data?: Record<string, unknown>): Promise<User> => {\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 emitAuthEvent('login', user)\n }\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Logs out the current user and clears the session. Browser only. */\nexport const logout = async (): Promise<void> => {\n const client = getClient()\n\n try {\n const currentUser = client.currentUser()\n if (currentUser) {\n await currentUser.logout()\n }\n emitAuthEvent('logout', null)\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Redirects to an OAuth provider. Always throws (the page navigates away). Browser only. */\nexport const oauthLogin = (provider: string): never => {\n if (!isBrowser()) {\n throw new Error('oauthLogin() is only available in the browser')\n }\n const client = getClient()\n\n window.location.href = client.loginExternalUrl(provider)\n throw new Error('Redirecting to OAuth provider')\n}\n\nexport interface CallbackResult {\n type: 'oauth' | 'confirmation' | 'recovery' | 'invite' | 'email_change'\n user: User | null\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 */\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\n try {\n const params = new URLSearchParams(hash)\n\n const accessToken = params.get('access_token')\n if (accessToken) {\n const gotrueUser = await client.createUser(\n {\n access_token: accessToken,\n token_type: (params.get('token_type') as 'bearer') ?? 'bearer',\n expires_in: Number(params.get('expires_in')),\n expires_at: Number(params.get('expires_at')),\n refresh_token: params.get('refresh_token') ?? '',\n },\n persistSession,\n )\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('login', user)\n return { type: 'oauth', user }\n }\n\n const confirmationToken = params.get('confirmation_token')\n if (confirmationToken) {\n const gotrueUser = await client.confirm(confirmationToken, persistSession)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('login', user)\n return { type: 'confirmation', user }\n }\n\n const recoveryToken = params.get('recovery_token')\n if (recoveryToken) {\n const gotrueUser = await client.recover(recoveryToken, persistSession)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('login', user)\n return { type: 'recovery', user }\n }\n\n const inviteToken = params.get('invite_token')\n if (inviteToken) {\n clearHash()\n return { type: 'invite', user: null, token: inviteToken }\n }\n\n const emailChangeToken = params.get('email_change_token')\n if (emailChangeToken) {\n const currentUser = client.currentUser()\n if (!currentUser) {\n clearHash()\n return { type: 'email_change', user: null, token: emailChangeToken }\n }\n const gotrueUser = await currentUser.update({ email_change_token: emailChangeToken })\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('user_updated', user)\n return { type: 'email_change', user }\n }\n\n return null\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\nconst clearHash = (): void => {\n history.replaceState(null, '', window.location.pathname + window.location.search)\n}\n","import type { User } from './user.js'\nimport { toUser } from './user.js'\nimport { getClient } from './environment.js'\nimport { emitAuthEvent, persistSession } from './auth.js'\nimport { AuthError } from './errors.js'\n\n/** Sends a password recovery email to the given address. */\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 new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Confirms an email address using the token from a confirmation email. Logs the user in on success. */\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('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Accepts an invite token and sets a password for the new account. Logs the user in on success. */\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('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Verifies an email change using the token from a verification email. Requires an active session. */\nexport const verifyEmailChange = async (token: string): Promise<User> => {\n const client = getClient()\n\n const currentUser = client.currentUser()\n if (!currentUser) throw new AuthError('No user is currently logged in')\n\n try {\n const gotrueUser = await currentUser.update({ email_change_token: token })\n const user = toUser(gotrueUser)\n emitAuthEvent('user_updated', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n\n/** Updates the current user's metadata or credentials. Requires an active session. */\nexport const updateUser = async (updates: Record<string, unknown>): Promise<User> => {\n const client = getClient()\n\n const currentUser = client.currentUser()\n if (!currentUser) throw new AuthError('No user is currently logged in')\n\n try {\n const updatedUser = await currentUser.update(updates)\n const user = toUser(updatedUser)\n emitAuthEvent('user_updated', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n"],"mappings":"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","names":["GoTrue"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/environment.ts","../src/errors.ts","../src/cookies.ts","../src/nextjs.ts","../src/user.ts","../src/config.ts","../src/auth.ts","../src/account.ts"],"sourcesContent":["export type { User } from './user.js'\nexport { getUser, isAuthenticated } from './user.js'\nexport { getIdentityConfig, getSettings } from './config.js'\nexport type { AuthCallback, AuthEvent, CallbackResult } from './auth.js'\nexport { login, signup, logout, oauthLogin, onAuthChange, handleAuthCallback, hydrateSession } from './auth.js'\nexport { AuthError, MissingIdentityError } from './errors.js'\nexport type { AppMetadata, AuthProvider, IdentityConfig, Settings, UserUpdates, SignupData } from './types.js'\nexport {\n requestPasswordRecovery,\n recoverPassword,\n confirmEmail,\n acceptInvite,\n verifyEmailChange,\n updateUser,\n} from './account.js'\n","export const AUTH_PROVIDERS = ['google', 'github', 'gitlab', 'bitbucket', 'facebook', 'saml', 'email'] as const\nexport type AuthProvider = (typeof AUTH_PROVIDERS)[number]\n\nexport interface AppMetadata {\n provider: AuthProvider\n roles?: string[]\n [key: string]: unknown\n}\n\nexport interface IdentityConfig {\n url: string\n token?: string // this is an operator token, only available on the server\n}\n\nexport interface Settings {\n autoconfirm: boolean\n disableSignup: boolean\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 */\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\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: string\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 (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 = process.env.URL\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","export class AuthError extends Error {\n override name = 'AuthError'\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\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(\n message = 'Netlify Identity is not available. Enable Identity in your site dashboard and use `netlify dev` for local development.',\n ) {\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. */\nexport const getCookie = (name: string): string | null => {\n const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}=([^;]*)`))\n return match ? decodeURIComponent(match[1]) : null\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 // A BFF-style server refresh endpoint would allow httpOnly here.\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). */\nexport const setBrowserAuthCookies = (accessToken: string, refreshToken?: string): void => {\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). */\nexport const deleteBrowserAuthCookies = (): void => {\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 type { UserData } from 'gotrue-js'\nimport { AUTH_PROVIDERS, type AuthProvider } from './types.js'\nimport { getGoTrueClient, getClient, isBrowser } from './environment.js'\nimport { getCookie, getServerCookie, NF_JWT_COOKIE, NF_REFRESH_COOKIE } from './cookies.js'\nimport { triggerNextjsDynamic } from './nextjs.js'\n\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\nexport interface User {\n id: string\n email?: string\n emailVerified?: boolean\n createdAt?: string\n updatedAt?: string\n provider?: AuthProvider\n name?: string\n pictureUrl?: string\n metadata?: Record<string, unknown>\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 metadata: userMeta,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts server-side JWT claims into User\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\n return {\n id: claims.sub ?? '',\n email: claims.email,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n metadata: userMeta,\n }\n}\n\nlet hydrating = false\n\n/**\n * Creates a gotrue-js session from the nf_jwt cookie so that browser-side\n * operations (updateUser, logout, etc.) work after a server-side login.\n * Fire-and-forget: getUser() returns synchronously from the JWT while this\n * runs in the background.\n */\nconst backgroundHydrate = (accessToken: string): void => {\n if (hydrating) return\n hydrating = true\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 // Defer to the next tick so the synchronous getUser() call completes first,\n // and gotrue-js's internal currentUser isn't set until after the caller\n // has received the JWT-decoded result.\n setTimeout(() => {\n try {\n const client = getClient()\n client\n .createUser(\n {\n access_token: accessToken,\n token_type: 'bearer',\n expires_in: expiresIn,\n expires_at: expiresAt,\n refresh_token: refreshToken,\n },\n true,\n )\n .catch(() => {\n // best-effort: if hydration fails, getUser() still works via cookie decode\n })\n .finally(() => {\n hydrating = false\n })\n } catch {\n hydrating = false\n }\n }, 0)\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 * Returns the currently authenticated user, or `null` if not logged in.\n * Synchronous.\n *\n * In the browser, checks gotrue-js localStorage first. If no localStorage\n * session exists, falls back to decoding the `nf_jwt` cookie (set by\n * server-side login) and kicks off background hydration of the gotrue-js\n * session so that subsequent operations (updateUser, logout, etc.) work.\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 = (): 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 const jwt = getCookie(NF_JWT_COOKIE)\n if (!jwt) return null\n\n const claims = decodeJwtPayload(jwt)\n if (!claims) return null\n\n // Hydrate gotrue-js in the background so browser-side operations\n // (updateUser, logout, etc.) work after a server-side login.\n backgroundHydrate(jwt)\n\n return claimsToUser(claims)\n }\n\n // Trigger Next.js dynamic rendering if in a Next.js RSC context\n triggerNextjsDynamic()\n\n // Primary path: identity context populated from the X-Nf-Identity-Info request header\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.user) {\n return claimsToUser(identityContext.user)\n }\n\n // Fallback: read the nf_jwt cookie directly from the Netlify runtime.\n const serverJwt = getServerCookie(NF_JWT_COOKIE)\n if (serverJwt) {\n const claims = decodeJwtPayload(serverJwt)\n if (claims) return claimsToUser(claims)\n }\n\n return null\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = (): boolean => 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 } from 'gotrue-js'\n\nimport type { NetlifyCookies, SignupData } from './types.js'\nimport type { User } from './user.js'\nimport { toUser, decodeJwtPayload } from './user.js'\n\nimport { getGoTrueClient, 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'\n\nexport type AuthEvent = 'login' | 'logout' | 'token_refresh' | 'user_updated'\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\nexport type AuthCallback = (event: AuthEvent, user: User | null) => void\n\n/** Persist the session to localStorage so it survives page reloads. */\nexport const persistSession = true\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\nconst GOTRUE_STORAGE_KEY = 'gotrue.user'\n\nlet storageListenerAttached = false\n\nconst attachStorageListener = (): void => {\n if (storageListenerAttached) 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('login', currentUser ? toUser(currentUser) : null)\n } else {\n emitAuthEvent('logout', null)\n }\n })\n}\n\n/**\n * Subscribes to auth state changes (login, logout, token refresh, user updates).\n * Returns an unsubscribe function. No-op on the server.\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\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<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 new AuthError((error as Error).message, undefined, { cause: error })\n }\n\n if (!res.ok) {\n const errorBody = await res.json().catch(() => ({}))\n throw new AuthError(\n (errorBody as Record<string, string>).msg ||\n (errorBody as Record<string, string>).error_description ||\n `Login failed (${res.status})`,\n res.status,\n )\n }\n\n const data = (await res.json()) as Record<string, unknown>\n const accessToken = data.access_token as string\n\n let userRes: Response\n try {\n userRes = await fetch(`${identityUrl}/user`, {\n headers: { Authorization: `Bearer ${accessToken}` },\n })\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n\n if (!userRes.ok) {\n const errorBody = await userRes.json().catch(() => ({}))\n throw new AuthError(\n (errorBody as Record<string, string>).msg || `Failed to fetch user data (${userRes.status})`,\n userRes.status,\n )\n }\n\n const userData = (await userRes.json()) as UserData\n const user = toUser(userData)\n\n setAuthCookies(cookies, accessToken, data.refresh_token as string | undefined)\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)\n const user = toUser(gotrueUser)\n emitAuthEvent('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: 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<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 new AuthError((error as Error).message, undefined, { cause: error })\n }\n\n if (!res.ok) {\n const errorBody = await res.json().catch(() => ({}))\n throw new AuthError((errorBody as Record<string, string>).msg || `Signup failed (${res.status})`, res.status)\n }\n\n const responseData = (await res.json()) as UserData\n const user = toUser(responseData)\n\n if (responseData.confirmed_at) {\n const responseRecord = responseData as unknown as Record<string, unknown>\n const accessToken = responseRecord.access_token as string | undefined\n if (accessToken) {\n setAuthCookies(cookies, accessToken, responseRecord.refresh_token as string | undefined)\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 setBrowserAuthCookies(jwt)\n }\n emitAuthEvent('login', user)\n }\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: 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('logout', null)\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: 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\nexport interface CallbackResult {\n type: 'oauth' | 'confirmation' | 'recovery' | 'invite' | 'email_change'\n user: User | null\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 * @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\n try {\n const params = new URLSearchParams(hash)\n\n const accessToken = params.get('access_token')\n if (accessToken) {\n const refreshToken = params.get('refresh_token') ?? ''\n const gotrueUser = await client.createUser(\n {\n access_token: accessToken,\n token_type: (params.get('token_type') as 'bearer') ?? 'bearer',\n expires_in: Number(params.get('expires_in')),\n expires_at: Number(params.get('expires_at')),\n refresh_token: refreshToken,\n },\n persistSession,\n )\n setBrowserAuthCookies(accessToken, refreshToken || undefined)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('login', user)\n return { type: 'oauth', user }\n }\n\n const confirmationToken = params.get('confirmation_token')\n if (confirmationToken) {\n const gotrueUser = await client.confirm(confirmationToken, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('login', user)\n return { type: 'confirmation', user }\n }\n\n const recoveryToken = params.get('recovery_token')\n if (recoveryToken) {\n const gotrueUser = await client.recover(recoveryToken, persistSession)\n const jwt = await gotrueUser.jwt()\n setBrowserAuthCookies(jwt)\n const user = toUser(gotrueUser)\n clearHash()\n emitAuthEvent('login', user)\n return { type: 'recovery', user }\n }\n\n const inviteToken = params.get('invite_token')\n if (inviteToken) {\n clearHash()\n return { type: 'invite', user: null, token: inviteToken }\n }\n\n const emailChangeToken = params.get('email_change_token')\n if (emailChangeToken) {\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(() => ({}))\n throw new AuthError(\n (errorBody as Record<string, string>).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('user_updated', user)\n return { type: 'email_change', user }\n }\n\n return null\n } catch (error) {\n if (error instanceof AuthError) throw error\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\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<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 const 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\n const user = toUser(gotrueUser)\n emitAuthEvent('login', user)\n return user\n}\n","import type { UserData, User as GoTrueUser } from 'gotrue-js'\n\nimport type { UserUpdates } from './types.js'\nimport type { User } from './user.js'\nimport { toUser } from './user.js'\nimport { getClient, isBrowser, IDENTITY_PATH } from './environment.js'\nimport { emitAuthEvent, persistSession, hydrateSession } from './auth.js'\nimport { AuthError } from './errors.js'\n\n/**\n * Returns the current gotrue-js user, auto-hydrating from cookies if needed.\n * Throws AuthError if no user can be resolved.\n */\nconst ensureCurrentUser = 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 new AuthError((error as Error).message, undefined, { cause: 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 emitAuthEvent('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: 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('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: 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('login', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: 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 ensureCurrentUser()\n\n const jwt = await currentUser.jwt()\n const identityUrl = `${window.location.origin}${IDENTITY_PATH}`\n\n try {\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(() => ({}))\n throw new AuthError(\n (errorBody as Record<string, string>).msg || `Email change verification failed (${res.status})`,\n res.status,\n )\n }\n\n const userData = (await res.json()) as UserData\n const user = toUser(userData)\n emitAuthEvent('user_updated', user)\n return user\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 the current user's metadata or credentials.\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 ensureCurrentUser()\n\n try {\n const updatedUser = await currentUser.update(updates)\n const user = toUser(updatedUser)\n emitAuthEvent('user_updated', user)\n return user\n } catch (error) {\n throw new AuthError((error as Error).message, undefined, { cause: error })\n }\n}\n"],"mappings":"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","names":["GoTrue","jwt"]}
package/dist/index.d.cts CHANGED
@@ -14,6 +14,21 @@ interface Settings {
14
14
  disableSignup: boolean;
15
15
  providers: Record<AuthProvider, boolean>;
16
16
  }
17
+ /**
18
+ * Fields accepted by {@link updateUser}. All fields are optional.
19
+ * Pass `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).
20
+ */
21
+ interface UserUpdates {
22
+ email?: string;
23
+ password?: string;
24
+ data?: Record<string, unknown>;
25
+ [key: string]: unknown;
26
+ }
27
+ /**
28
+ * User metadata passed during signup (e.g., `{ full_name: 'Jane Doe' }`).
29
+ * Stored in the user's `user_metadata` field.
30
+ */
31
+ type SignupData = Record<string, unknown>;
17
32
 
18
33
  interface User {
19
34
  id: string;
@@ -29,7 +44,16 @@ interface User {
29
44
  }
30
45
  /**
31
46
  * Returns the currently authenticated user, or `null` if not logged in.
32
- * Synchronous. Never throws.
47
+ * Synchronous.
48
+ *
49
+ * In the browser, checks gotrue-js localStorage first. If no localStorage
50
+ * session exists, falls back to decoding the `nf_jwt` cookie (set by
51
+ * server-side login) and kicks off background hydration of the gotrue-js
52
+ * session so that subsequent operations (updateUser, logout, etc.) work.
53
+ *
54
+ * On the server in a Next.js App Router context, calls `headers()` from
55
+ * `next/headers` to opt the route into dynamic rendering. Without this,
56
+ * Next.js may statically cache the page at build time.
33
57
  */
34
58
  declare const getUser: () => User | null;
35
59
  /**
@@ -45,27 +69,70 @@ declare const isAuthenticated: () => boolean;
45
69
  */
46
70
  declare const getIdentityConfig: () => IdentityConfig | null;
47
71
  /**
48
- * Fetches the GoTrue `/settings` endpoint.
49
- * Throws `MissingIdentityError` if Identity is not configured.
50
- * Throws `AuthError` if the endpoint is unreachable.
72
+ * Fetches your project's Identity settings (enabled providers, autoconfirm, signup disabled).
73
+ *
74
+ * @throws {MissingIdentityError} If Identity is not configured.
75
+ * @throws {AuthError} If the endpoint is unreachable.
51
76
  */
52
77
  declare const getSettings: () => Promise<Settings>;
53
78
 
54
79
  type AuthEvent = 'login' | 'logout' | 'token_refresh' | 'user_updated';
55
-
56
80
  type AuthCallback = (event: AuthEvent, user: User | null) => void;
57
81
  /**
58
82
  * Subscribes to auth state changes (login, logout, token refresh, user updates).
59
83
  * Returns an unsubscribe function. No-op on the server.
60
84
  */
61
85
  declare const onAuthChange: (callback: AuthCallback) => (() => void);
62
- /** Logs in with email and password. Browser only. */
86
+ /**
87
+ * Logs in with email and password. Works in both browser and server contexts.
88
+ *
89
+ * On success, sets `nf_jwt` and `nf_refresh` cookies and returns the authenticated {@link User}.
90
+ * In the browser, also emits a `'login'` event via {@link onAuthChange}.
91
+ *
92
+ * @throws {AuthError} On invalid credentials, network failure, or missing Netlify runtime.
93
+ *
94
+ * @remarks
95
+ * In Next.js server actions, call `redirect()` **after** `login()` returns, not inside a
96
+ * try/catch. Next.js implements `redirect()` by throwing a special error; wrapping it in
97
+ * try/catch will swallow the redirect.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * // Next.js server action
102
+ * const user = await login(email, password)
103
+ * redirect('/dashboard') // after login, not inside try/catch
104
+ * ```
105
+ */
63
106
  declare const login: (email: string, password: string) => Promise<User>;
64
- /** Creates a new account. Emits 'login' if autoconfirm is enabled. Browser only. */
65
- declare const signup: (email: string, password: string, data?: Record<string, unknown>) => Promise<User>;
66
- /** Logs out the current user and clears the session. Browser only. */
107
+ /**
108
+ * Creates a new account. Works in both browser and server contexts.
109
+ *
110
+ * If autoconfirm is enabled in your Identity settings, the user is logged in immediately:
111
+ * cookies are set and a `'login'` event is emitted. If autoconfirm is **disabled** (the default),
112
+ * the user receives a confirmation email and must click the link before they can log in.
113
+ * In that case, no cookies are set and no auth event is emitted.
114
+ *
115
+ * @throws {AuthError} On duplicate email, validation failure, network error, or missing Netlify runtime.
116
+ */
117
+ declare const signup: (email: string, password: string, data?: SignupData) => Promise<User>;
118
+ /**
119
+ * Logs out the current user and clears the session. Works in both browser and server contexts.
120
+ *
121
+ * Always deletes `nf_jwt` and `nf_refresh` cookies, even if the server-side token
122
+ * invalidation request fails. In the browser, emits a `'logout'` event via {@link onAuthChange}.
123
+ *
124
+ * @throws {AuthError} On missing Netlify runtime (server) or logout failure (browser).
125
+ */
67
126
  declare const logout: () => Promise<void>;
68
- /** Redirects to an OAuth provider. Always throws (the page navigates away). Browser only. */
127
+ /**
128
+ * Initiates an OAuth login by redirecting to the given provider (e.g., `'google'`, `'github'`).
129
+ * The page navigates away; this function never returns normally. Browser only.
130
+ *
131
+ * After the provider redirects back, call {@link handleAuthCallback} on page load
132
+ * to complete the login and obtain the {@link User}.
133
+ *
134
+ * @throws {AuthError} If called on the server.
135
+ */
69
136
  declare const oauthLogin: (provider: string) => never;
70
137
  interface CallbackResult {
71
138
  type: 'oauth' | 'confirmation' | 'recovery' | 'invite' | 'email_change';
@@ -76,8 +143,23 @@ interface CallbackResult {
76
143
  * Processes the URL hash after an OAuth redirect, email confirmation, password
77
144
  * recovery, invite acceptance, or email change. Call on page load. Browser only.
78
145
  * Returns `null` if the hash contains no auth parameters.
146
+ *
147
+ * Call this early in your app's initialization (e.g., in a layout component or
148
+ * root loader), **not** inside a route that requires authentication, because
149
+ * the callback URL must match the page where this function runs.
150
+ *
151
+ * @throws {AuthError} If the callback token is invalid or the verification request fails.
79
152
  */
80
153
  declare const handleAuthCallback: () => Promise<CallbackResult | null>;
154
+ /**
155
+ * Hydrates the browser-side gotrue-js session from server-set auth cookies.
156
+ * Call this on page load when using server-side login to enable browser
157
+ * account operations (updateUser, verifyEmailChange, etc.).
158
+ *
159
+ * No-op if a browser session already exists or no auth cookies are present.
160
+ * No-op on the server.
161
+ */
162
+ declare const hydrateSession: () => Promise<User | null>;
81
163
 
82
164
  declare class AuthError extends Error {
83
165
  name: string;
@@ -92,15 +174,45 @@ declare class MissingIdentityError extends Error {
92
174
  constructor(message?: string);
93
175
  }
94
176
 
95
- /** Sends a password recovery email to the given address. */
177
+ /**
178
+ * Sends a password recovery email to the given address.
179
+ *
180
+ * @throws {AuthError} On network failure or if the request is rejected.
181
+ */
96
182
  declare const requestPasswordRecovery: (email: string) => Promise<void>;
97
- /** Confirms an email address using the token from a confirmation email. Logs the user in on success. */
183
+ /**
184
+ * Redeems a recovery token and sets a new password. Logs the user in on success.
185
+ *
186
+ * @throws {AuthError} If the token is invalid, expired, or the update fails.
187
+ */
188
+ declare const recoverPassword: (token: string, newPassword: string) => Promise<User>;
189
+ /**
190
+ * Confirms an email address using the token from a confirmation email. Logs the user in on success.
191
+ *
192
+ * @throws {AuthError} If the token is invalid or expired.
193
+ */
98
194
  declare const confirmEmail: (token: string) => Promise<User>;
99
- /** Accepts an invite token and sets a password for the new account. Logs the user in on success. */
195
+ /**
196
+ * Accepts an invite token and sets a password for the new account. Logs the user in on success.
197
+ *
198
+ * @throws {AuthError} If the token is invalid or expired.
199
+ */
100
200
  declare const acceptInvite: (token: string, password: string) => Promise<User>;
101
- /** Verifies an email change using the token from a verification email. Requires an active session. */
201
+ /**
202
+ * Verifies an email change using the token from a verification email.
203
+ * Auto-hydrates from auth cookies if no browser session exists. Browser only.
204
+ *
205
+ * @throws {AuthError} If called on the server, no user is logged in, or the token is invalid.
206
+ */
102
207
  declare const verifyEmailChange: (token: string) => Promise<User>;
103
- /** Updates the current user's metadata or credentials. Requires an active session. */
104
- declare const updateUser: (updates: Record<string, unknown>) => Promise<User>;
208
+ /**
209
+ * Updates the current user's metadata or credentials.
210
+ * Auto-hydrates from auth cookies if no browser session exists.
211
+ *
212
+ * @param updates - Fields to update. Pass `email` or `password` to change credentials,
213
+ * or `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).
214
+ * @throws {AuthError} If no user is logged in or the update fails.
215
+ */
216
+ declare const updateUser: (updates: UserUpdates) => Promise<User>;
105
217
 
106
- export { type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type IdentityConfig, MissingIdentityError, type Settings, type User, acceptInvite, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, isAuthenticated, login, logout, oauthLogin, onAuthChange, requestPasswordRecovery, signup, updateUser, verifyEmailChange };
218
+ export { type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type IdentityConfig, MissingIdentityError, type Settings, type SignupData, type User, type UserUpdates, acceptInvite, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, hydrateSession, isAuthenticated, login, logout, oauthLogin, onAuthChange, recoverPassword, requestPasswordRecovery, signup, updateUser, verifyEmailChange };
package/dist/index.d.ts CHANGED
@@ -14,6 +14,21 @@ interface Settings {
14
14
  disableSignup: boolean;
15
15
  providers: Record<AuthProvider, boolean>;
16
16
  }
17
+ /**
18
+ * Fields accepted by {@link updateUser}. All fields are optional.
19
+ * Pass `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).
20
+ */
21
+ interface UserUpdates {
22
+ email?: string;
23
+ password?: string;
24
+ data?: Record<string, unknown>;
25
+ [key: string]: unknown;
26
+ }
27
+ /**
28
+ * User metadata passed during signup (e.g., `{ full_name: 'Jane Doe' }`).
29
+ * Stored in the user's `user_metadata` field.
30
+ */
31
+ type SignupData = Record<string, unknown>;
17
32
 
18
33
  interface User {
19
34
  id: string;
@@ -29,7 +44,16 @@ interface User {
29
44
  }
30
45
  /**
31
46
  * Returns the currently authenticated user, or `null` if not logged in.
32
- * Synchronous. Never throws.
47
+ * Synchronous.
48
+ *
49
+ * In the browser, checks gotrue-js localStorage first. If no localStorage
50
+ * session exists, falls back to decoding the `nf_jwt` cookie (set by
51
+ * server-side login) and kicks off background hydration of the gotrue-js
52
+ * session so that subsequent operations (updateUser, logout, etc.) work.
53
+ *
54
+ * On the server in a Next.js App Router context, calls `headers()` from
55
+ * `next/headers` to opt the route into dynamic rendering. Without this,
56
+ * Next.js may statically cache the page at build time.
33
57
  */
34
58
  declare const getUser: () => User | null;
35
59
  /**
@@ -45,27 +69,70 @@ declare const isAuthenticated: () => boolean;
45
69
  */
46
70
  declare const getIdentityConfig: () => IdentityConfig | null;
47
71
  /**
48
- * Fetches the GoTrue `/settings` endpoint.
49
- * Throws `MissingIdentityError` if Identity is not configured.
50
- * Throws `AuthError` if the endpoint is unreachable.
72
+ * Fetches your project's Identity settings (enabled providers, autoconfirm, signup disabled).
73
+ *
74
+ * @throws {MissingIdentityError} If Identity is not configured.
75
+ * @throws {AuthError} If the endpoint is unreachable.
51
76
  */
52
77
  declare const getSettings: () => Promise<Settings>;
53
78
 
54
79
  type AuthEvent = 'login' | 'logout' | 'token_refresh' | 'user_updated';
55
-
56
80
  type AuthCallback = (event: AuthEvent, user: User | null) => void;
57
81
  /**
58
82
  * Subscribes to auth state changes (login, logout, token refresh, user updates).
59
83
  * Returns an unsubscribe function. No-op on the server.
60
84
  */
61
85
  declare const onAuthChange: (callback: AuthCallback) => (() => void);
62
- /** Logs in with email and password. Browser only. */
86
+ /**
87
+ * Logs in with email and password. Works in both browser and server contexts.
88
+ *
89
+ * On success, sets `nf_jwt` and `nf_refresh` cookies and returns the authenticated {@link User}.
90
+ * In the browser, also emits a `'login'` event via {@link onAuthChange}.
91
+ *
92
+ * @throws {AuthError} On invalid credentials, network failure, or missing Netlify runtime.
93
+ *
94
+ * @remarks
95
+ * In Next.js server actions, call `redirect()` **after** `login()` returns, not inside a
96
+ * try/catch. Next.js implements `redirect()` by throwing a special error; wrapping it in
97
+ * try/catch will swallow the redirect.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * // Next.js server action
102
+ * const user = await login(email, password)
103
+ * redirect('/dashboard') // after login, not inside try/catch
104
+ * ```
105
+ */
63
106
  declare const login: (email: string, password: string) => Promise<User>;
64
- /** Creates a new account. Emits 'login' if autoconfirm is enabled. Browser only. */
65
- declare const signup: (email: string, password: string, data?: Record<string, unknown>) => Promise<User>;
66
- /** Logs out the current user and clears the session. Browser only. */
107
+ /**
108
+ * Creates a new account. Works in both browser and server contexts.
109
+ *
110
+ * If autoconfirm is enabled in your Identity settings, the user is logged in immediately:
111
+ * cookies are set and a `'login'` event is emitted. If autoconfirm is **disabled** (the default),
112
+ * the user receives a confirmation email and must click the link before they can log in.
113
+ * In that case, no cookies are set and no auth event is emitted.
114
+ *
115
+ * @throws {AuthError} On duplicate email, validation failure, network error, or missing Netlify runtime.
116
+ */
117
+ declare const signup: (email: string, password: string, data?: SignupData) => Promise<User>;
118
+ /**
119
+ * Logs out the current user and clears the session. Works in both browser and server contexts.
120
+ *
121
+ * Always deletes `nf_jwt` and `nf_refresh` cookies, even if the server-side token
122
+ * invalidation request fails. In the browser, emits a `'logout'` event via {@link onAuthChange}.
123
+ *
124
+ * @throws {AuthError} On missing Netlify runtime (server) or logout failure (browser).
125
+ */
67
126
  declare const logout: () => Promise<void>;
68
- /** Redirects to an OAuth provider. Always throws (the page navigates away). Browser only. */
127
+ /**
128
+ * Initiates an OAuth login by redirecting to the given provider (e.g., `'google'`, `'github'`).
129
+ * The page navigates away; this function never returns normally. Browser only.
130
+ *
131
+ * After the provider redirects back, call {@link handleAuthCallback} on page load
132
+ * to complete the login and obtain the {@link User}.
133
+ *
134
+ * @throws {AuthError} If called on the server.
135
+ */
69
136
  declare const oauthLogin: (provider: string) => never;
70
137
  interface CallbackResult {
71
138
  type: 'oauth' | 'confirmation' | 'recovery' | 'invite' | 'email_change';
@@ -76,8 +143,23 @@ interface CallbackResult {
76
143
  * Processes the URL hash after an OAuth redirect, email confirmation, password
77
144
  * recovery, invite acceptance, or email change. Call on page load. Browser only.
78
145
  * Returns `null` if the hash contains no auth parameters.
146
+ *
147
+ * Call this early in your app's initialization (e.g., in a layout component or
148
+ * root loader), **not** inside a route that requires authentication, because
149
+ * the callback URL must match the page where this function runs.
150
+ *
151
+ * @throws {AuthError} If the callback token is invalid or the verification request fails.
79
152
  */
80
153
  declare const handleAuthCallback: () => Promise<CallbackResult | null>;
154
+ /**
155
+ * Hydrates the browser-side gotrue-js session from server-set auth cookies.
156
+ * Call this on page load when using server-side login to enable browser
157
+ * account operations (updateUser, verifyEmailChange, etc.).
158
+ *
159
+ * No-op if a browser session already exists or no auth cookies are present.
160
+ * No-op on the server.
161
+ */
162
+ declare const hydrateSession: () => Promise<User | null>;
81
163
 
82
164
  declare class AuthError extends Error {
83
165
  name: string;
@@ -92,15 +174,45 @@ declare class MissingIdentityError extends Error {
92
174
  constructor(message?: string);
93
175
  }
94
176
 
95
- /** Sends a password recovery email to the given address. */
177
+ /**
178
+ * Sends a password recovery email to the given address.
179
+ *
180
+ * @throws {AuthError} On network failure or if the request is rejected.
181
+ */
96
182
  declare const requestPasswordRecovery: (email: string) => Promise<void>;
97
- /** Confirms an email address using the token from a confirmation email. Logs the user in on success. */
183
+ /**
184
+ * Redeems a recovery token and sets a new password. Logs the user in on success.
185
+ *
186
+ * @throws {AuthError} If the token is invalid, expired, or the update fails.
187
+ */
188
+ declare const recoverPassword: (token: string, newPassword: string) => Promise<User>;
189
+ /**
190
+ * Confirms an email address using the token from a confirmation email. Logs the user in on success.
191
+ *
192
+ * @throws {AuthError} If the token is invalid or expired.
193
+ */
98
194
  declare const confirmEmail: (token: string) => Promise<User>;
99
- /** Accepts an invite token and sets a password for the new account. Logs the user in on success. */
195
+ /**
196
+ * Accepts an invite token and sets a password for the new account. Logs the user in on success.
197
+ *
198
+ * @throws {AuthError} If the token is invalid or expired.
199
+ */
100
200
  declare const acceptInvite: (token: string, password: string) => Promise<User>;
101
- /** Verifies an email change using the token from a verification email. Requires an active session. */
201
+ /**
202
+ * Verifies an email change using the token from a verification email.
203
+ * Auto-hydrates from auth cookies if no browser session exists. Browser only.
204
+ *
205
+ * @throws {AuthError} If called on the server, no user is logged in, or the token is invalid.
206
+ */
102
207
  declare const verifyEmailChange: (token: string) => Promise<User>;
103
- /** Updates the current user's metadata or credentials. Requires an active session. */
104
- declare const updateUser: (updates: Record<string, unknown>) => Promise<User>;
208
+ /**
209
+ * Updates the current user's metadata or credentials.
210
+ * Auto-hydrates from auth cookies if no browser session exists.
211
+ *
212
+ * @param updates - Fields to update. Pass `email` or `password` to change credentials,
213
+ * or `data` to update user metadata (e.g., `{ data: { full_name: 'New Name' } }`).
214
+ * @throws {AuthError} If no user is logged in or the update fails.
215
+ */
216
+ declare const updateUser: (updates: UserUpdates) => Promise<User>;
105
217
 
106
- export { type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type IdentityConfig, MissingIdentityError, type Settings, type User, acceptInvite, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, isAuthenticated, login, logout, oauthLogin, onAuthChange, requestPasswordRecovery, signup, updateUser, verifyEmailChange };
218
+ export { type AppMetadata, type AuthCallback, AuthError, type AuthEvent, type AuthProvider, type CallbackResult, type IdentityConfig, MissingIdentityError, type Settings, type SignupData, type User, type UserUpdates, acceptInvite, confirmEmail, getIdentityConfig, getSettings, getUser, handleAuthCallback, hydrateSession, isAuthenticated, login, logout, oauthLogin, onAuthChange, recoverPassword, requestPasswordRecovery, signup, updateUser, verifyEmailChange };