UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

187 lines 6.27 kB
import type { ActivityTenant } from "./audit.js"; /** * Minimal request shape consumed by Beignet auth ports. * * Framework adapters can pass richer request objects, but auth providers should * only rely on headers and the optional raw platform request unless they * declare a more specific `RequestLike` type. */ export interface AuthRequestLike { /** * Request headers used for cookies, bearer tokens, API keys, or provider * specific auth data. */ headers: Headers; /** * Raw platform request, when the runtime has one available. */ raw?: Request; } /** * Normalized authenticated session returned by an `AuthPort`. * * `user` is the app/provider user object. `session` can carry provider-specific * session state such as cookie session metadata or token claims. */ export interface AuthSession<User = unknown, Session = unknown> { user: User; session?: Session; } /** * Error thrown by auth helpers when a route or workflow requires a user but no * authenticated user is available. */ export declare class AuthUnauthorizedError extends Error { readonly code = "UNAUTHORIZED"; /** HTTP status used when the server maps this framework error. */ readonly status = 401; constructor(message?: string); } /** * 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 declare class TenantRequiredError extends Error { readonly code = "TENANT_REQUIRED"; readonly status = 403; constructor(message?: string); } /** * Options accepted by the `requireX(ctx)` context helpers. */ export interface RequireOptions { /** * Create the error to throw instead of the framework default. */ error?: () => unknown; } /** * 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 declare function requireSession<Session extends AuthSession>(ctx: { auth?: Session | null; }, options?: RequireOptions): Session; /** * 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 declare function requireUser<User>(ctx: { auth?: AuthSession<User> | null; }, options?: RequireOptions): 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 declare function requireUserId(ctx: { auth?: AuthSession<{ id: string; }> | null; }, options?: RequireOptions): string; /** * 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 declare function requireTenant(ctx: { tenant?: ActivityTenant | null; }, options?: RequireOptions): ActivityTenant; /** * Return the tenant ID from `ctx.tenant` or throw. * * Throws `TenantRequiredError` (a framework-owned 403) by default. * * @example * ```ts * const tenantId = requireTenantId(ctx); * ``` */ export declare function requireTenantId(ctx: { tenant?: ActivityTenant | null; }, options?: RequireOptions): string; /** * App-facing authentication port. * * Implement this with a provider adapter such as Better Auth, a custom session * lookup, or a test fake. The port identifies the current user; it does not * decide whether that user may perform a business action. Keep authorization in * policies or use cases. */ export interface AuthPort<User = unknown, Session = unknown, RequestLike extends AuthRequestLike = AuthRequestLike> { /** * Return the current session, or `null` when the request is unauthenticated. */ getSession(req: RequestLike): Promise<AuthSession<User, Session> | null>; /** * Return the current user, or `null` when unauthenticated. */ getUser(req: RequestLike): Promise<User | null>; /** * Return the current user or throw `AuthUnauthorizedError`. */ requireUser(req: RequestLike): Promise<User>; } type MaybePromise<T> = T | Promise<T>; /** * Request-aware factory for a static auth session. */ export type StaticAuthSessionFactory<User, Session, RequestLike extends AuthRequestLike> = (req: RequestLike) => MaybePromise<AuthSession<User, Session> | null>; /** * 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 declare function createStaticAuth<User, Session = unknown, RequestLike extends AuthRequestLike = AuthRequestLike>(session: AuthSession<User, Session> | null | StaticAuthSessionFactory<User, Session, RequestLike>): AuthPort<User, Session, RequestLike>; /** * 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 declare function createAnonymousAuth<User = unknown, Session = unknown, RequestLike extends AuthRequestLike = AuthRequestLike>(): AuthPort<User, Session, RequestLike>; export {}; //# sourceMappingURL=auth.d.ts.map