import type { RuntimeContext } from "alchemy"; import type { HttpEffect } from "alchemy/Http"; import { type Auth, type BetterAuthOptions } from "better-auth"; import * as Effect from "effect/Effect"; import * as Redacted from "effect/Redacted"; import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"; import { type BetterAuthApi } from "./ApiProxy.ts"; import { Database } from "./Database.ts"; import type { BetterAuthApiError } from "./Errors.ts"; /** * Better Auth options, minus the fields alchemy owns: * * - `database` comes from the {@link Database} platform layer * (`Cloudflare.D1`, `Postgres`, `Memory`, ...) * - `secondaryStorage` comes from the optional {@link SecondaryStorage} * layer (`Cloudflare.KV`) * - `secret` is widened to accept `Redacted` values and Effects (resource * outputs), and defaults to an auto-provisioned stable random secret * * plus alchemy extensions (`id`, `migrate`). */ export interface BetterAuthProps extends Omit { /** * Distinguishes multiple BetterAuth instances in one namespace — suffixes * the auto-provisioned secret resource and the migration action logical * ids. * * @default "BetterAuth" */ readonly id?: string; /** * Deploy-time automatic schema migration. Runs as an internal alchemy * Action during `alchemy deploy` (never at plan, never inside the * deployed runtime) and re-runs only when the auth schema (plugins, * additional fields) or the target database changes. * * `false` opts out. `true` on a Database layer without migration support * (Memory, Drizzle) fails the deploy with a descriptive error. * * @default true when the Database layer supports migration */ readonly migrate?: boolean; /** * The Better Auth signing secret. Accepts a literal string, a `Redacted` * value, or an Effect resolving to one (e.g. another resource's output * accessor). * * @default an auto-provisioned `Alchemy.Random` secret (`${id}Secret`), * generated once and stable across deploys */ readonly secret?: string | Redacted.Redacted | Effect.Effect, never, RuntimeContext>; } /** * The Better Auth options type seen by `Auth` — the user's literal * options with the alchemy extension fields stripped, so plugin/session/user * type inference flows through untouched. */ export type AuthOptions = Omit extends infer T extends BetterAuthOptions ? T : BetterAuthOptions; /** The inferred `{ session, user }` shape for a given options type. */ export type Session = Auth>["$Infer"]["Session"]; export interface BetterAuthInstance { /** * The per-execution Better Auth instance (memoized on the execution * scope). Escape hatch for anything the effectified surface doesn't * cover (`$context`, `asResponse`/`returnHeaders` call forms, ...). */ readonly auth: Effect.Effect>, never, RuntimeContext>; /** * Every `auth.api.*` endpoint mirrored as an Effect with a typed * {@link BetterAuthApiError} failure. */ readonly api: BetterAuthApi>["api"]>; /** * HTTP handler for the Better Auth routes — mount it under your * `basePath` (default `/api/auth`): * * ```typescript * fetch: Effect.gen(function* () { * const request = yield* HttpServerRequest; * if (request.url.startsWith("/api/auth")) { * return yield* auth.fetch; * } * // ... * }) * ``` */ readonly fetch: HttpEffect; /** * Look up the session for the ambient request (or explicit `Headers`). * Resolves `null` for anonymous requests — failures are real errors, not * missing sessions. */ readonly getSession: { (): Effect.Effect | null, BetterAuthApiError, RuntimeContext | HttpServerRequest.HttpServerRequest>; (headers: Headers): Effect.Effect | null, BetterAuthApiError, RuntimeContext>; }; /** Type-level mirror of `auth.$Infer` (phantom — no runtime value). */ readonly Infer: Auth>["$Infer"]; } /** * Create a Better Auth instance wired to alchemy. * * The database comes from a {@link Database} platform layer provided on * the surrounding Worker/Function impl effect; the signing secret defaults * to a stable auto-provisioned random secret; schema migrations run * automatically at deploy time. * * ```typescript * Effect.gen(function* () { * const auth = yield* BetterAuth({ * basePath: "/api/auth", * emailAndPassword: { enabled: true }, * }); * return { fetch: ... }; * }).pipe(Effect.provide(CloudflareD1(Db))) * ``` */ export declare const BetterAuth: (options: O) => Effect.Effect, never, Database>; //# sourceMappingURL=BetterAuth.d.ts.map