Files
suaveplan/packages/api-stack/api/api-plugin-auth/src/services/auth-service.ts
2026-05-27 23:29:53 +01:00

77 lines
2.5 KiB
TypeScript

import type { Auth } from "better-auth";
import type { Context } from "hono";
import type { Principal } from "../principal/principal.js";
/**
* Loose-typed Better-Auth session shape returned by `auth.api.getSession`.
* Kept loose so plugin-extended sessions (passkeys, organisations,
* twoFactor) flow through without forcing this package to track every
* Better-Auth plugin's type extensions.
*/
export type BetterAuthSessionResult = {
readonly user: Record<string, unknown>;
readonly session: Record<string, unknown>;
} | null;
/**
* Service slot registered by `createAuthPlugin` in the host's
* `ServiceRegistry`. Downstream plugins (api-plugin-user,
* api-plugin-vault) call `ctx.getService("authService")` to read the
* current principal, the Better-Auth instance, or to manually resolve
* a session from arbitrary headers.
*/
export interface AuthService {
/**
* Returns the typed `Principal` attached to the current request
* context, or `null` for anonymous requests. The session middleware
* is responsible for populating `c.get("user")`.
*/
getCurrentPrincipal(c: Context): Principal | null;
/**
* Returns the underlying Better-Auth instance — useful for plugins
* that need to call Better-Auth API endpoints directly (e.g.
* organisation membership listings).
*/
getBetterAuthInstance(): Auth;
/**
* Resolves a session from arbitrary request headers. Plugins
* authenticating a stand-alone request (cron-triggered work, raw
* WebSocket upgrades) use this to get the same session shape the
* middleware would have produced.
*/
getSession(headers: Headers): Promise<BetterAuthSessionResult>;
}
/**
* Inputs required to build the `AuthService` impl. Kept explicit so
* the factory is testable without the full plugin lifecycle.
*/
export interface CreateAuthServiceOptions {
readonly auth: Auth;
}
/**
* Construct the canonical `AuthService` implementation backed by the
* supplied Better-Auth instance.
*/
export function createAuthService(
options: CreateAuthServiceOptions
): AuthService {
const { auth } = options;
return {
getCurrentPrincipal(c) {
const value = c.get("user");
return value ?? null;
},
getBetterAuthInstance() {
return auth;
},
async getSession(headers) {
const result = (await auth.api.getSession({
headers,
})) as BetterAuthSessionResult;
return result;
},
};
}