first commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# adapter
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The package's flagship export. `createBetterAuthSurrealAdapter(options)`
|
||||
returns a Better-Auth `Adapter` whose 8 contract methods plus
|
||||
`consumeOne` and `id` are wired against a SurrealDB v3 connection. The
|
||||
adapter validates options through Zod at the boundary, dispatches every
|
||||
CRUD method through OTel-instrumented spans, applies link-field
|
||||
prefix/strip on writes/reads, and compiles `Where[]` filters into
|
||||
parameterised SurrealQL — no string interpolation, no mocks, no
|
||||
`vi.mock`.
|
||||
|
||||
## Features
|
||||
|
||||
- Stable `id` constant `"@suaveplan/better-auth-surrealdb"`.
|
||||
- All 8 Better-Auth methods: `create`, `findOne`, `findMany`, `count`,
|
||||
`update`, `updateMany`, `delete`, `deleteMany`, plus the `consumeOne`
|
||||
primitive Better-Auth v1.6+ adds atop the older 8 methods.
|
||||
- Link-field-aware writes and reads — `userId: "u1"` becomes
|
||||
`userId: "user:u1"` at rest for `record<user>` columns.
|
||||
- Three id-strategies (`record-id` default, `plain`, `ulid`).
|
||||
- OTel counter + histogram via `instrument()`.
|
||||
- Zod-validated options at the boundary; failures raise
|
||||
`BetterAuthSurrealError(INVALID_INPUT)` with the `ZodError` as `cause`.
|
||||
- Connection-readiness check: every method validates `client.isConnected`
|
||||
and raises `CONNECTION_NOT_READY` when the underlying SurrealAdapter
|
||||
has not connected.
|
||||
- Underlying `SurrealError` failures wrap in `QUERY_FAILED` preserving the
|
||||
`cause` chain.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { SurrealAdapter } from "@suaveplan/surrealdb";
|
||||
import { applyBetterAuthSchema } from "@suaveplan/better-auth-surrealdb/schema";
|
||||
import { createBetterAuthSurrealAdapter } from "@suaveplan/better-auth-surrealdb/adapter";
|
||||
|
||||
const client = new SurrealAdapter({ url: "ws://localhost:8000" });
|
||||
await client.connect();
|
||||
await applyBetterAuthSchema(client);
|
||||
|
||||
const adapter = createBetterAuthSurrealAdapter({ client });
|
||||
|
||||
await adapter.create({
|
||||
model: "session",
|
||||
data: { id: "s1", userId: "u1", token: "t" },
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { createBetterAuthSurrealAdapter } from "@suaveplan/better-auth-surrealdb/adapter";
|
||||
|
||||
const adapter = createBetterAuthSurrealAdapter({
|
||||
client: surrealAdapter,
|
||||
idStrategy: "ulid",
|
||||
modelToTable: (m) => `bauth_${m}`,
|
||||
linkFields: {
|
||||
// override default — match a flat-string schema:
|
||||
session: {},
|
||||
member: { organizationId: "organization" },
|
||||
},
|
||||
});
|
||||
|
||||
const user = await adapter.findOne({
|
||||
model: "user",
|
||||
where: [{ field: "email", value: "x@y" }],
|
||||
select: ["id", "email"],
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `createBetterAuthSurrealAdapter(options): BetterAuthSurrealAdapter`
|
||||
- `BETTER_AUTH_SURREAL_ADAPTER_ID = "@suaveplan/better-auth-surrealdb"`
|
||||
- `BetterAuthSurrealAdapter` — structural type satisfying Better-Auth's
|
||||
`DBAdapter` minus `transaction` / `createSchema` (the host's own
|
||||
transaction primitive remains reachable via `SurrealAdapter.transaction`).
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The adapter's `client.query()` calls pass the binding record as
|
||||
`[vars]` so both `SurrealAdapter` (which flattens a trailing record) and
|
||||
hand-rolled `SurrealClientView` implementations receive the same shape.
|
||||
`update` is implemented atop `updateMany`'s `RETURN AFTER` row stream and
|
||||
returns the first row — `count() FROM <table> WHERE … GROUP ALL` returns
|
||||
a `{ c: <num> }` row by aliasing; bare `count()` returns the count
|
||||
unnamed which trips SurrealDB v3's stricter row shape. `consumeOne`
|
||||
fetches the row first, then deletes by the same predicate; this is the
|
||||
fallback path Better-Auth's factory installs when an adapter does not
|
||||
expose a native consume primitive, and gives the same race semantics
|
||||
under SurrealDB's read-then-delete pipeline.
|
||||
Reference in New Issue
Block a user