import type { Context } from "@wrnexus/core"; import type { AuthEngine } from "./engine.ts"; import type { AuthPasskeyHttpOptions } from "./http/index.ts"; import type { AuthSessionVerificationHandler } from "./types.ts"; import { resolveAuthSchemas, type AuthSchemaOverrides, type AuthSchemaSet } from "./validation.ts"; export interface DefaultAuthRouteOptions { baseUrl?: string; csrf?: boolean; passkey?: AuthPasskeyHttpOptions; onSignedIn?: (ctx: Context, returnTo?: string) => Response | Promise; onSignedOut?: (ctx: Context) => Response | Promise; sessionCookieName?: string; onSessionVerification?: AuthSessionVerificationHandler; } interface AuthRuntimeState { engine?: AuthEngine; schemas: AuthSchemaSet; routeOptions: DefaultAuthRouteOptions; } /** * A Symbol.for registry is used instead of module-local variables. * * The dev server may import the auth plugin and route modules using * different module URLs during HMR. Those modules still execute inside * the same JavaScript global realm, so Symbol.for keeps the runtime * configuration shared between them. */ const AUTH_RUNTIME_STATE_KEY = Symbol.for("@wrnexus/auth:runtime-state:v1"); function runtimeState(): AuthRuntimeState { const registry = globalThis as unknown as Record; const existing = registry[AUTH_RUNTIME_STATE_KEY] as AuthRuntimeState | undefined; if (existing) { return existing; } const created: AuthRuntimeState = { schemas: resolveAuthSchemas(), routeOptions: {}, }; registry[AUTH_RUNTIME_STATE_KEY] = created; return created; } export function setDefaultAuthEngine(engine: AuthEngine): void { runtimeState().engine = engine; } /** * Clear auth state when an application removes config.auth.engine * during development or when another application starts in the * same process. */ export function clearDefaultAuthEngine(): void { delete runtimeState().engine; } export function setDefaultAuthSchemas(schemas: AuthSchemaOverrides | AuthSchemaSet = {}): void { runtimeState().schemas = resolveAuthSchemas(schemas); } export function setDefaultAuthRouteOptions(options: DefaultAuthRouteOptions = {}): void { runtimeState().routeOptions = { ...options, }; } export function tryGetDefaultAuthEngine(): AuthEngine | undefined { return runtimeState().engine; } export function getDefaultAuthEngine(): AuthEngine { const engine = runtimeState().engine; if (!engine) { throw new Error( "WRN-AUTH-NOT-CONFIGURED: configure auth.engine or call setDefaultAuthEngine(createAuthEngine(...)) at startup", ); } return engine; } export function getDefaultAuthSchemas(): AuthSchemaSet { return runtimeState().schemas; } export function getDefaultAuthRouteOptions(): DefaultAuthRouteOptions { return runtimeState().routeOptions; } export function hasDefaultAuthEngine(): boolean { return Boolean(runtimeState().engine); }