UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

59 lines (58 loc) 2.79 kB
import { isDynamicBaseURLConfig, isRequestLike } from "../utils/url.mjs"; import { pickSource, resolveDynamicTrustedProxyHeaders, resolveRequestContext } from "../context/helpers.mjs"; import { dispatchAuthEndpoint, getOperationId } from "./dispatch.mjs"; import { hasRequestState, runWithRequestState } from "@better-auth/core/context"; import { APIError, BetterAuthError } from "@better-auth/core/error"; //#region src/api/to-auth-endpoints.ts /** * Resolves the per-call `AuthContext` for endpoints with a dynamic `baseURL`. * * - `rawCtx.baseURL` already set: HTTP handler rehydrated upstream; return as-is. * - Direct `auth.api` call with a source or a configured `fallback`: resolve here. * - Neither: throw `APIError` with a helpful message. Leaving `baseURL = ""` * would let plugins build `new URL("")` and crash cryptically downstream. */ async function resolveDynamicContext(rawCtx, input) { if (rawCtx.baseURL) return rawCtx; const source = pickSource(input); const config = rawCtx.options.baseURL; const hasFallback = isDynamicBaseURLConfig(config) && Boolean(config.fallback); if (source === void 0 && !hasFallback) throw new APIError("INTERNAL_SERVER_ERROR", { message: "Dynamic baseURL could not be resolved for this direct auth.api call. Pass `headers: request.headers` (or `request`) to the call, or add `fallback` to your baseURL config." }); try { return await resolveRequestContext(rawCtx, source, resolveDynamicTrustedProxyHeaders(rawCtx.options)); } catch (err) { if (err instanceof BetterAuthError) throw new APIError("INTERNAL_SERVER_ERROR", { message: err.message }); throw err; } } /** * Wraps each raw endpoint so a router or `auth.api.*` call runs it through the * configured hook pipeline. Per-call work that is specific to this entry point * (dynamic `baseURL` resolution, request-state initialization) happens here; * the hook pipeline itself lives in {@link dispatchAuthEndpoint}. */ function toAuthEndpoints(endpoints, ctx) { const api = {}; for (const [key, endpoint] of Object.entries(endpoints)) { api[key] = async (context) => { const operationId = getOperationId(endpoint, key); const run = async () => { const rawContext = await ctx; const authContext = isDynamicBaseURLConfig(rawContext.options.baseURL) ? await resolveDynamicContext(rawContext, context) : rawContext; return dispatchAuthEndpoint(endpoint, { ...context, context: authContext, operationId, asResponse: context?.asResponse ?? isRequestLike(context?.request) }); }; if (await hasRequestState()) return run(); return runWithRequestState(/* @__PURE__ */ new WeakMap(), run); }; api[key].path = endpoint.path; api[key].options = endpoint.options; } return api; } //#endregion export { toAuthEndpoints };