UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

155 lines 4.42 kB
/** * Error thrown by auth helpers when a route or workflow requires a user but no * authenticated user is available. */ export class AuthUnauthorizedError extends Error { code = "UNAUTHORIZED"; /** HTTP status used when the server maps this framework error. */ status = 401; constructor(message = "Unauthorized") { super(message); this.name = "AuthUnauthorizedError"; } } /** * Error thrown by tenant helpers when a workflow requires a tenant scope but * the current context has none. * * The server maps this to a framework-owned 403 response, mirroring how * `AuthUnauthorizedError` maps to a framework-owned 401. */ export class TenantRequiredError extends Error { code = "TENANT_REQUIRED"; status = 403; constructor(message = "A tenant is required for this action.") { super(message); this.name = "TenantRequiredError"; } } function throwRequired(options, fallback) { throw options?.error ? options.error() : fallback(); } /** * Return the authenticated session from `ctx.auth` or throw. * * Throws `AuthUnauthorizedError` (a framework-owned 401) by default. Pass * `options.error` to throw an app-owned error instead. * * @example * ```ts * const session = requireSession(ctx); * ``` */ export function requireSession(ctx, options) { if (!ctx.auth) { throwRequired(options, () => new AuthUnauthorizedError()); } return ctx.auth; } /** * Return the authenticated user from `ctx.auth` or throw. * * The user type is inferred from the app's `ctx.auth` session. Throws * `AuthUnauthorizedError` (a framework-owned 401) by default. * * @example * ```ts * const user = requireUser(ctx); * ``` */ export function requireUser(ctx, options) { return requireSession(ctx, options).user; } /** * Return the authenticated user's ID from `ctx.auth` or throw. * * Throws `AuthUnauthorizedError` (a framework-owned 401) by default. * * @example * ```ts * const userId = requireUserId(ctx); * ``` */ export function requireUserId(ctx, options) { return requireUser(ctx, options).id; } /** * Return the tenant scope from `ctx.tenant` or throw. * * Throws `TenantRequiredError` (a framework-owned 403) by default. Pass * `options.error` to throw an app-owned error instead. * * @example * ```ts * const tenant = requireTenant(ctx); * ``` */ export function requireTenant(ctx, options) { if (!ctx.tenant) { throwRequired(options, () => new TenantRequiredError()); } return ctx.tenant; } /** * Return the tenant ID from `ctx.tenant` or throw. * * Throws `TenantRequiredError` (a framework-owned 403) by default. * * @example * ```ts * const tenantId = requireTenantId(ctx); * ``` */ export function requireTenantId(ctx, options) { return requireTenant(ctx, options).id; } /** * Create an auth port from a fixed session or request-aware session factory. * * This is useful for tests, examples, and simple apps. Production apps usually * use a provider-backed auth port that verifies cookies, tokens, or sessions. * * @example * ```ts * const auth = createStaticAuth({ * user: { id: "user_1", name: "Ada" }, * }); * ``` * * @param session - Fixed session, `null`, or a function that resolves a session * from the request. * @returns An `AuthPort` implementation backed by the provided session source. */ export function createStaticAuth(session) { async function resolveSession(req) { return typeof session === "function" ? session(req) : session; } return { async getSession(req) { return resolveSession(req); }, async getUser(req) { return (await resolveSession(req))?.user ?? null; }, async requireUser(req) { const user = (await resolveSession(req))?.user ?? null; if (!user) { throw new AuthUnauthorizedError(); } return user; }, }; } /** * Create an auth port that always treats requests as unauthenticated. * * Use this in tests or examples where auth is intentionally absent. It is not a * security boundary; it simply returns `null` from `getSession`/`getUser` and * throws from `requireUser`. * * @returns An `AuthPort` with no active session. */ export function createAnonymousAuth() { return createStaticAuth(null); } //# sourceMappingURL=auth.js.map