@alchemy.run/better-auth (中文(简体) )
更好的认证 页:1 炼金术 ——一个效果-内在包装器外加每个平台可插接的数据库层.
跟着 六段教学 用于构建浏览器的签名, Effect HTTP API 中间软件,以及 GitHub 认证. 见 登录提供者 财务报告和审定财务报表 数据库指南 其他整合.
import { BetterAuth } from "@alchemy.run/better-auth";
import { CloudflareD1 } from "@alchemy.run/better-auth/CloudflareD1";
import * as Cloudflare from "@alchemy.run/cloudflare";
export const AuthDb = Cloudflare.D1.Database("AuthDb");
export default class Api extends Cloudflare.Worker<Api>()(
"Api",
{ main: import.meta.url, compatibility: { flags: ["nodejs_compat"] } },
Effect.gen(function* () {
const auth = yield* BetterAuth({
basePath: "/auth",
emailAndPassword: { enabled: true },
});
return {
fetch: Effect.gen(function* () {
const request = yield* HttpServerRequest;
if (request.url.startsWith("/auth")) {
return yield* auth.fetch; // the Better Auth HTTP surface
}
const session = yield* auth.getSession(); // null when anonymous
return yield* HttpServerResponse.json({ user: session?.user ?? null });
}),
};
}).pipe(Effect.provide(CloudflareD1(AuthDb))),
) {}
你得到的东西是:
yield* BetterAuth(options)——满Auth<Options>类型推论: 通过的插件auth.api, (中文(简体) ),Session类型来自选项。 没有标签,没有铸币.auth.api.*– 每一个更好的 Auth 端点作为效果键入BetterAuthApiError失败( e)status, (中文(简体) ),statusCode, (中文(简体) ),body.code,以及headers包括 页:1set-cookie标题更好调用隐藏在符号上。 无APIError抛掷是缺陷.auth.fetch- 炼金术HttpEffect为更好的Auth线路服务;在Cloudflare Workers和AWS Lambda的工程不变.auth.getSession()- 从环境请求中输入会话查询(或明确Headers页:1null为匿名.auth.auth- 原始执行Auth成为逃生舱.- 部署时自动迁移计划 - 内部炼金术(包括插件)
alchemy deploy,仅在计划或目标数据库发生变化时重新运行。 选择退出migrate: false。 。 。 . - 管理机密 —— 说
secret默认为稳定的自动设置Alchemy.Random值绑入主机环境.
数据库是您提供的关于周围杂效的图层 。 选择您环境的最佳层 ~ 数据库配对 — HTTP/ 无服务器驱动程序, TCP驱动程序作为倒置:
| 运行时间 | 数据库 | 层 | 运输 |
|---|---|---|---|
| 云花岗工人 | D1级 | CloudflareD1 | 本地绑定 |
| Cloudflare 工人/ AWS Lambda | 霓虹 | Neon | 无服务器驱动程序( WebSocket) |
| AWS 兰布达 | 奥罗拉 | AuroraDataApi | RDS 数据 API (HTTPS, IAM) |
| 云花岗工人 | 任何 TCP 邮递/ MySQL | CloudflareHyperdrive | 通过超驱动程序集合 TCP |
| 任何带有套接字的地方 | 任何邮资 | Postgres | pg TCP 常规程序 |
| 任何带有套接字的地方 | 任何 MySQL(例如: 星球标本) | MySQL | mysql2 TCP 常规程序 |
| 圆包( dev/ tests) | 本地文件 | SQLite | bun:sqlite |
| 测试 | 记忆 | Memory | —— 说 |
| 带上你的 | 你的"滴滴" db | Drizzle | |
每层路由通过炼金术的捆绑系统运行时间访问——本土捆绑(D1,Hyperdrive,RDS Data API IAM grants)或主机-环境输出捆绑(连接字符串)——从不使用手接管活字 vars.
云纹 D1
本地 D1 在运行时绑定; 迁移在部署时运行于 D1 HTTP API 上( 并针对本地模拟器) alchemy dev) (中文(简体) ).
import { CloudflareD1 } from "@alchemy.run/better-auth/CloudflareD1";
import * as Cloudflare from "@alchemy.run/cloudflare";
export const AuthDb = Cloudflare.D1.Database("AuthDb");
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(Effect.provide(CloudflareD1(AuthDb)));
霓虹
Neon的无服务器驱动程序从边缘说 WebSocket —— 无超驱动程序, 无 pg没有 TCP 套接字。 工人和Lambda的最佳配对@neondatabase/serverless 是一个可选的对等点).
import { Neon as NeonDatabase } from "@alchemy.run/better-auth/Neon";
import * as Neon from "@alchemy.run/neon";
export const AuthDb = Neon.Project("AuthDb");
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(
Effect.provide(
Layer.unwrap(Effect.map(AuthDb, (db) => NeonDatabase(db.connectionUri))),
),
);
奥罗拉 (RDS Data API)
以 IAM auth 为主的 SQL over HTTPS – 没有为 Lambda 所附加的 VPC , 没有驱动器, 没有池. 运行时间访问流经 AWS.RDSData.* 约束(授予) rds-data:* + 键 secretsmanager:GetSecretValue 在主机上); 部署时间迁移使用与堆栈证书相同的数据 API. kysely 财务报告和审定财务报表 @distilled.cloud/aws 是可选的同龄人.
import { AuroraDataApi } from "@alchemy.run/better-auth/AuroraDataApi";
import * as AWS from "@alchemy.run/aws";
export const Db = AWS.RDS.Aurora("AuthDb", {
subnetIds: network.privateSubnetIds,
securityGroupIds: [securityGroup.groupId],
// the Data API is enabled by default
});
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(Effect.provide(AuroraDataApi(Db, { database: "postgres" })));
云浮超驱动
通过Hyperdrive连接来集合 Postgres(或 MySQL). Hyperdrive 的连接字符串只存在于工作间,所以通过 来源 用于部署时间迁移的 URL( 或省略) migrate 跳过它们.
import { CloudflareHyperdrive } from "@alchemy.run/better-auth/CloudflareHyperdrive";
const branch = yield* Neon.Branch("auth-db", { project });
const hyperdrive = yield* Cloudflare.Hyperdrive.Connection("auth-hd", {
origin: branch.origin,
});
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(
Effect.provide(
CloudflareHyperdrive(hyperdrive, { migrate: branch.connectionUri }),
),
);
Postgres( 基因TCP)
您拥有连接字符串的 Postgres 的倒置: Planet Scale Postgres ()role.connectionUrl(原始内容存档于2013-10-12). Prisma Postgres (英语)connection.databaseUrl),VPC内部的RDS,或字面URL. 一个 pg 每次执行的池,活动结束后关闭. pg 是一个可选的同伴依赖。 (预选 Neon编号 :AuroraDataApi编号 :CloudflareHyperdrive 当他们符合你的对。 )
import { Postgres } from "@alchemy.run/better-auth/Postgres";
const project = yield* Neon.Project("AuthDb");
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(Effect.provide(Postgres(project.connectionUri)));
资源产出在运行时部署并读取时被绑入主机环境;同一源驱动部署-时间迁移(覆盖 migrate:禁用 migrate: false) (中文(简体) ).
MySQL( 通用 TCP )
与 Postgres 的形状相同 mysql2 (可选对等点): Planet Scale MySQL, Hyperdrive MySQL 起源, RDS MySQL. Planet Scale 需要 TLS —— 在 URL 中通过它 ssl 查询参数.
import { MySQL } from "@alchemy.run/better-auth/MySQL";
const password = yield* Planetscale.MySQLPassword("auth-db", { database, role: "admin" });
const url = `mysql://${password.username}:...@${password.host}/${database.name}?ssl=${encodeURIComponent('{"rejectUnauthorized":true}')}`;
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(Effect.provide(MySQL(url)));
AWS 兰布达
不需要专用主机层—— auth.fetch 是可携带的主机。 从 Lambda 函数 URL 中提供与您目标匹配的数据库层: AuroraDataApi 为奥罗拉, Neon 或通用的 Postgres编号 :MySQL (蓝巴达的TCP司机需要) build: { install: ["pg"] } 所以有npm布局的动态进口驾驶船.
import * as Lambda from "@alchemy.run/aws/Lambda";
import { Neon as NeonDatabase } from "@alchemy.run/better-auth/Neon";
export const AuthDb = Neon.Project("AuthDb");
export class AuthFunction extends Lambda.Function<Lambda.Function>()("AuthFunction") {}
export default AuthFunction.make(
// scrypt password hashing needs headroom over the 128 MB default
{ main, url: true, memorySize: 512, timeout: Duration.seconds(30) },
Effect.gen(function* () {
const auth = yield* BetterAuth({
basePath: "/auth",
emailAndPassword: { enabled: true },
});
return { fetch: /* route /auth/* to auth.fetch */ };
}).pipe(
Effect.provide(
Layer.unwrap(Effect.map(AuthDb, (db) => NeonDatabase(db.connectionUri))),
),
),
);
SQLite(地方发展)
bun:sqlite- 在包跑时进行开发和测试.
import { SQLite } from "@alchemy.run/better-auth/SQLite";
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(Effect.provide(SQLite(".alchemy/auth.sqlite")));
内存( 测试)
记忆适配器;没有什么持续,不需要移民.
import { Memory } from "@alchemy.run/better-auth";
Effect.gen(function* () {
const auth = yield* BetterAuth({
emailAndPassword: { enabled: true },
secret: "test-secret",
});
// ...
}).pipe(Effect.provide(Memory()));
滴水龙头
通过 Better Auth 关系 v2 带回自己的 Drizzle 数据库 drizzleAdapter (可选对等者) drizzle-orm 财务报告和审定财务报表 @better-auth/drizzle-adapter) (中文(简体) ). Schema是你的——这个层没有自动迁移。 配置 CLI 认证实例 @better-auth/drizzle-adapter/relations-v2运行 npx [email protected] generate --config ./auth.cli.ts。通过 --adapter drizzle 选择遗留生成器,而不是配置的适配器.
import { Drizzle } from "@alchemy.run/better-auth/Drizzle";
import { drizzle } from "drizzle-orm/node-postgres";
import * as schema from "./auth-schema.ts";
import { relations } from "./app-schema.ts";
const db = drizzle({
client: pool,
relations: { ...relations, ...schema.authRelations },
});
Effect.gen(function* () {
const auth = yield* BetterAuth({ emailAndPassword: { enabled: true } });
// ...
}).pipe(Effect.provide(Drizzle(db, { provider: "pg", schema })));
处理错误
const result = yield* auth.api
.signInEmail({ body: { email, password } })
.pipe(
Effect.catchTag("BetterAuthApiError", (error) =>
error.statusCode === 401
? Effect.succeed(null) // wrong credentials
: Effect.fail(error),
),
);
error.toResponse() 使故障与更好的Auth完全相同(状态+JSON正体+合并头, set-cookie 包括),供通过处理器使用.
移徙
带有迁移支持的 SQL 层 应用方案变化 alchemy deploy 通过内部炼金术:
- 运行 仅在适用时 (从来没有在计划,从来没有在部署的运行时间—— 迁移代码从捆绑中去除),
- 仅在认证计划(插件、额外字段、索引)或目标数据库发生变化时重新运行,
- 应用缺失的表格、列和索引,通过 Better Auth 的映射器; 不安全的计划改变表面为
BetterAuthMigrationError。 。 。 .
一个直接的 1.6 → 1.7.5+ 升级,核心账户计划不变:无 issuer 列或身份回填。 保持相同的认证秘密,并一起升级更好的Auth同步软件包. 微软标识器、遗留的OIDC/MCP客户端、SCIM以及设备代码可能需要人工制备; Alchemy不重写身份或转换插件数据. 见 升级指南 在部署现有数据库之前.
选择退出 migrate: false 并管理自己的计划npx [email protected] generate) (中文(简体) ). 多个 BetterAuth 实例以一叠表示: 给每个不同的 id 将秘密+移民资源分解.