Files
WRNexusJS/packages/auth/src/runtime.ts
T
2026-07-30 13:36:29 +05:30

104 lines
2.9 KiB
TypeScript

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<Response>;
onSignedOut?: (ctx: Context) => Response | Promise<Response>;
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<PropertyKey, unknown>;
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);
}