90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
import type { Context } from "@wrnexus/core";
|
|
import type { AuthEngine } from "./engine.ts";
|
|
import type { AuthSession, AuthUser } from "./types.ts";
|
|
|
|
export type AuthRouteName =
|
|
| "signIn"
|
|
| "signUp"
|
|
| "signOut"
|
|
| "forgotPassword"
|
|
| "resetPassword"
|
|
| "verifyEmail"
|
|
| "verifyPhone"
|
|
| "twoFactor"
|
|
| "sessions"
|
|
| "passkeys";
|
|
|
|
const DEFAULT_AUTH_ROUTES: Record<AuthRouteName, string> = {
|
|
signIn: "/sign-in",
|
|
signUp: "/sign-up",
|
|
signOut: "/api/auth/logout",
|
|
forgotPassword: "/forgot-password",
|
|
resetPassword: "/reset-password",
|
|
verifyEmail: "/verify-email",
|
|
verifyPhone: "/verify-phone",
|
|
twoFactor: "/two-factor",
|
|
sessions: "/account/sessions",
|
|
passkeys: "/account/passkeys",
|
|
};
|
|
|
|
export function authRoute(
|
|
name: AuthRouteName,
|
|
options: { basePath?: string; overrides?: Partial<Record<AuthRouteName, string>> } = {},
|
|
): string {
|
|
const route = options.overrides?.[name] ?? DEFAULT_AUTH_ROUTES[name];
|
|
if (!options.basePath || route.startsWith("http://") || route.startsWith("https://"))
|
|
return route;
|
|
return `${options.basePath.replace(/\/$/, "")}/${route.replace(/^\//, "")}`;
|
|
}
|
|
|
|
export function authSuccess<T extends Record<string, unknown>>(
|
|
data: T,
|
|
init: ResponseInit = {},
|
|
): Response {
|
|
return Response.json({ ok: true, ...data }, { status: init.status ?? 200, ...init });
|
|
}
|
|
|
|
export function authFailure(
|
|
code: string,
|
|
message: string,
|
|
status = 400,
|
|
details?: Record<string, unknown>,
|
|
): Response {
|
|
return Response.json(
|
|
{ ok: false, error: { code, message, ...(details ? { details } : {}) } },
|
|
{ status },
|
|
);
|
|
}
|
|
|
|
export function requireAuthUser(ctx: Context): AuthUser {
|
|
if (!ctx.user || typeof ctx.user !== "object") {
|
|
throw new Response("Unauthorized", { status: 401 });
|
|
}
|
|
return ctx.user as AuthUser;
|
|
}
|
|
|
|
export function optionalAuthUser(ctx: Context): AuthUser | null {
|
|
return ctx.user && typeof ctx.user === "object" ? (ctx.user as AuthUser) : null;
|
|
}
|
|
|
|
export async function currentAuthSession(
|
|
engine: AuthEngine,
|
|
sessionId: string | undefined,
|
|
): Promise<AuthSession | null> {
|
|
if (!sessionId) return null;
|
|
const session = await engine.store.findSession(sessionId);
|
|
return session ?? null;
|
|
}
|
|
|
|
export function authComponentProps(
|
|
input: Record<string, unknown>,
|
|
defaults: { color?: string; size?: string; class?: string } = {},
|
|
): Record<string, unknown> {
|
|
return {
|
|
color: defaults.color ?? "primary",
|
|
size: defaults.size ?? "md",
|
|
class: defaults.class ?? "",
|
|
...input,
|
|
};
|
|
}
|