first commit
This commit is contained in:
177
docs/identity/auth/better-auth-surrealdb/README.md
Normal file
177
docs/identity/auth/better-auth-surrealdb/README.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# @suaveplan/better-auth-surrealdb - Better-Auth Adapter for SurrealDB v3 — bundles the canonical 17-table SurrealQL schema, compiles Better-Auth Where[] filters to parameterised SurrealQL, auto-prefixes record-link fields on write, strips prefixes on read, supports record-id/plain/ulid id strategies, and ships an OTel-instrumented conformance harness for cross-package consumption.
|
||||
|
||||
Better-Auth Adapter for SurrealDB v3 — bundles the canonical 17-table
|
||||
SurrealQL schema, compiles Better-Auth `Where[]` filters to parameterised
|
||||
SurrealQL, auto-prefixes record-link fields on write, strips prefixes on
|
||||
read, supports `record-id` / `plain` / `ulid` id strategies, and ships an
|
||||
OTel-instrumented conformance harness for cross-package reuse.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [adapter](./src/adapter/adapter.md) — The package's flagship export. `createBetterAuthSurrealAdapter(options)` returns a Better-Auth `Adapter` whose 8 contra…
|
||||
- [adapter](./src/adapter/adapter.md) — The package's flagship export. `createBetterAuthSurrealAdapter(options)` returns a Better-Auth `Adapter` whose 8 contra…
|
||||
- [internals](./src/adapter/internals.md) — Shared internal helpers consumed by the adapter shell (`adapter.ts`) and the per-method operation runners (`operations.…
|
||||
- [model-to-table](./src/adapter/model-to-table.md) — Memoising mapper from Better-Auth model name to SurrealDB table name. The mapper function is invoked once per distinct…
|
||||
- [operations](./src/adapter/operations.md) — Hosts the five primitive runners (`runCreate`, `runFindMany`, `runUpdateMany`, `runDeleteMany`, `runCount`) that transl…
|
||||
- [v1.6](./src/adapter/v1.6.md) — `betterAuthSurrealAdapter(options)` is the Better-Auth **v1.6** integration surface for `@suaveplan/better-auth-surreal…
|
||||
- [compile-select](./src/compile/compile-select.md) — Compiles a Better-Auth `select?: string[]` projection into a SurrealQL column list. Used inside the adapter's `SELECT`…
|
||||
- [compile-sort](./src/compile/compile-sort.md) — Compiles a Better-Auth `sortBy?: { field; direction }` argument into a SurrealQL `ORDER BY` fragment, validating the fi…
|
||||
- [compile-where](./src/compile/compile-where.md) — Translates Better-Auth's `Where[]` filter union into a parameterised SurrealQL `WHERE` fragment plus a binding record.…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — Defines the closed registry of error codes raised from every public path of `@suaveplan/better-auth-surrealdb`. Stable…
|
||||
- [error-codes](./src/error-codes/error-codes.md) — Defines the closed registry of error codes raised from every public path of `@suaveplan/better-auth-surrealdb`. Stable…
|
||||
- [id-strategy](./src/id-strategy/id-strategy.md) — Encapsulates the three Better-Auth record-id strategies the adapter supports. SurrealDB's native record-id format is `<…
|
||||
- [id-strategy](./src/id-strategy/id-strategy.md) — Encapsulates the three Better-Auth record-id strategies the adapter supports. SurrealDB's native record-id format is `<…
|
||||
- [link-fields](./src/link-fields/link-fields.md) — Encapsulates the central design decision of this package: SurrealDB stores record references as typed `record<target>`…
|
||||
- [link-fields](./src/link-fields/link-fields.md) — Encapsulates the central design decision of this package: SurrealDB stores record references as typed `record<target>`…
|
||||
- [otel](./src/otel/instruments.md) — Wires the package's OpenTelemetry metrics surface and exposes a thin `instrument(op)` helper the adapter wraps around e…
|
||||
- [instruments](./src/otel/instruments.md) — Wires the package's OpenTelemetry metrics surface and exposes a thin `instrument(op)` helper the adapter wraps around e…
|
||||
- [schema](./src/schema/schema.md) — Bundles the canonical 17-table Better-Auth SurrealQL schema as a frozen string constant `BETTER_AUTH_SURREAL_SCHEMA` an…
|
||||
- [schema](./src/schema/schema.md) — Bundles the canonical 17-table Better-Auth SurrealQL schema as a frozen string constant `BETTER_AUTH_SURREAL_SCHEMA` an…
|
||||
- [link-fields](./src/schemas/link-fields.md) — Zod boundary schema asserting the structural shape of a `LinkFieldMap`. Used to validate the optional `linkFields` argu…
|
||||
- [options](./src/schemas/options.md) — Zod boundary schema for `BetterAuthSurrealAdapterOptions`. Drives the runtime validation step inside `createBetterAuthS…
|
||||
- [testing](./src/testing/run-adapter-conformance.md) — Exposes `runAdapterConformance(factory)` — the reusable suite that pins every Better-Auth Adapter scenario this package…
|
||||
- [run-adapter-conformance](./src/testing/run-adapter-conformance.md) — Exposes `runAdapterConformance(factory)` — the reusable suite that pins every Better-Auth Adapter scenario this package…
|
||||
- [types](./src/types/adapter.md) — Type-only foundation for the entire package. Defines the public option shape (`BetterAuthSurrealAdapterOptions`), the r…
|
||||
- [adapter](./src/types/adapter.md) — Type-only foundation for the entire package. Defines the public option shape (`BetterAuthSurrealAdapterOptions`), the r…
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { SurrealAdapter } from "@suaveplan/surrealdb";
|
||||
import { applyBetterAuthSchema } from "@suaveplan/better-auth-surrealdb/schema";
|
||||
import { betterAuthSurrealAdapter } from "@suaveplan/better-auth-surrealdb/adapter/v1.6";
|
||||
import { betterAuth } from "better-auth";
|
||||
|
||||
const client = new SurrealAdapter({
|
||||
url: "ws://localhost:8000",
|
||||
namespace: "auth",
|
||||
database: "auth",
|
||||
username: "root",
|
||||
password: process.env.SURREAL_PASSWORD,
|
||||
});
|
||||
await client.connect();
|
||||
await applyBetterAuthSchema(client);
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: betterAuthSurrealAdapter({ client }),
|
||||
secret: process.env.BETTER_AUTH_SECRET,
|
||||
baseURL: "http://localhost:3000",
|
||||
emailAndPassword: { enabled: true },
|
||||
});
|
||||
```
|
||||
|
||||
### Advanced — direct conformance harness usage
|
||||
|
||||
The v1.4-shape `createBetterAuthSurrealAdapter` returns the 10-method
|
||||
adapter directly (without the `createAdapterFactory` wrapper). This is the
|
||||
surface the `./testing` conformance harness consumes and the right
|
||||
choice when you want to bypass Better-Auth's field-transformation layer:
|
||||
|
||||
```ts
|
||||
import { createBetterAuthSurrealAdapter } from "@suaveplan/better-auth-surrealdb/adapter";
|
||||
|
||||
const adapter = createBetterAuthSurrealAdapter({ client });
|
||||
await adapter.create({ model: "user", data: { id: "u1", email: "a@b" } });
|
||||
```
|
||||
|
||||
## Bundled schema — 17 Better-Auth tables
|
||||
|
||||
Mirrored byte-for-byte from
|
||||
`/mnt/f/surrealdb/surql/features/02-auth/02-better-auth.surql`. Schema
|
||||
version moves in lockstep with this package version. Upstream changes to
|
||||
the canonical schema require a coordinated package version bump.
|
||||
|
||||
| Table | `userId` shape | Notes |
|
||||
|-----------------------|-------------------------|--------------------------------------------------------|
|
||||
| `user` (extended) | n/a | Extends host's user table with `emailVerified`/`name`/`image` |
|
||||
| `session` | `record<user>` | Has default `linkFields.session.userId = "user"` |
|
||||
| `account` | `string` | Flat-string userId — NOT in `DEFAULT_BETTER_AUTH_LINK_FIELDS` |
|
||||
| `verification` | n/a | Single-use token storage |
|
||||
| `passkey` | `record<user>` | WebAuthn credentials |
|
||||
| `jwks` | n/a | Server JWK pairs |
|
||||
| `sso_provider` | `option<record<user>>` | Optional record-link |
|
||||
| `oauth_application` | `string` (option) | Flat-string userId |
|
||||
| `oauth_access_token` | `string` (option) | Flat-string userId |
|
||||
| `oauth_consent` | `string` (option) | Flat-string userId |
|
||||
| `organization` | n/a | Slug-unique tenant root |
|
||||
| `member` | record × 2 | `userId`+`organizationId` both record-links |
|
||||
| `invitation` | record × 3 | `inviterId`/`organizationId`/`teamId` record-links |
|
||||
| `team` | `record<organization>` | Belongs to org |
|
||||
| `team_member` | record × 2 | `userId`+`teamId` |
|
||||
| `two_factor` | `record<user>` | TOTP secret + backup codes |
|
||||
| `api_key` | `record<user>` | Long-lived API keys with rate-limit fields |
|
||||
|
||||
Plus 13 indexes (account provider, verification identifier, SSO provider
|
||||
id, oauth client/access/refresh tokens, organization slug, passkey
|
||||
credential, user phone, api_key prefix/user, member/team uniqueness,
|
||||
invitation email/org).
|
||||
|
||||
## `linkFields` — overriding the default record-link map
|
||||
|
||||
`DEFAULT_BETTER_AUTH_LINK_FIELDS` covers every `record<...>` column in
|
||||
the bundled schema. Pass your own `linkFields` when your schema differs:
|
||||
|
||||
```ts
|
||||
import { createBetterAuthSurrealAdapter } from "@suaveplan/better-auth-surrealdb/adapter";
|
||||
|
||||
// Flat-string schema everywhere — disable prefix manipulation:
|
||||
createBetterAuthSurrealAdapter({ client, linkFields: {} });
|
||||
|
||||
// Mixed override:
|
||||
createBetterAuthSurrealAdapter({
|
||||
client,
|
||||
linkFields: {
|
||||
session: { userId: "user" }, // keep default
|
||||
member: { userId: "user", organizationId: "tenant" }, // rename target
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## `idStrategy` — record-id format
|
||||
|
||||
| Strategy | Behaviour |
|
||||
|-------------|--------------------------------------------------------------------------------------------|
|
||||
| `record-id` (default) | `data.id` becomes the SurrealDB record component (`<table>:<id>`). Rejects `id` containing `:`. Returned `id` is bare. |
|
||||
| `plain` | `id` stored as a normal field; SurrealDB auto-generates the storage id. |
|
||||
| `ulid` | When `data.id` missing, generates a 26-char Crockford-base32 ULID and applies `record-id`. |
|
||||
|
||||
## Conformance harness
|
||||
|
||||
```ts
|
||||
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
|
||||
import { runAdapterConformance } from "@suaveplan/better-auth-surrealdb/testing";
|
||||
|
||||
const fixture = new SurrealDBFixture();
|
||||
let adapter: ReturnType<typeof createBetterAuthSurrealAdapter>;
|
||||
let client: SurrealAdapter;
|
||||
|
||||
beforeAll(async () => {
|
||||
const cfg = await fixture.start();
|
||||
client = new SurrealAdapter(cfg);
|
||||
await client.connect();
|
||||
await applyBetterAuthSchema(client);
|
||||
adapter = createBetterAuthSurrealAdapter({ client });
|
||||
}, 120_000);
|
||||
|
||||
afterAll(async () => {
|
||||
await client.disconnect();
|
||||
await fixture.stop();
|
||||
});
|
||||
|
||||
runAdapterConformance(() => ({ client, adapter }));
|
||||
```
|
||||
|
||||
## Peer deps
|
||||
|
||||
- `better-auth` ^1.4.0 — supplied by the consuming app. Type-only at this
|
||||
package's boundary; never imported at runtime so the adapter ships
|
||||
cleanly to apps using any 1.4+ minor.
|
||||
|
||||
## Subpath exports
|
||||
|
||||
`.`, `./adapter`, `./adapter/v1.6`, `./compile`, `./id-strategy`,
|
||||
`./link-fields`, `./schema`, `./schemas/options`, `./schemas/link-fields`,
|
||||
`./testing`, `./error-codes`, `./otel`, `./types`.
|
||||
|
||||
Reference in New Issue
Block a user