first commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# `error-codes`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Stable, OpenSpec-tracked error-code registry for `@suaveplan/api-auth-better-auth`.
|
||||
Every fault path inside the adapter — session resolution, database access,
|
||||
OAuth handshake, principal mapping, route-prefix collision detection — terminates
|
||||
in a {@link BetterAuthError} carrying one of the ten codes defined here. Codes
|
||||
are namespaced under `AUTH_BA.*` via the package's `defineCodes` helper so the
|
||||
full literal value never collides with sibling adapters and consumers can branch
|
||||
on a single discriminated value.
|
||||
|
||||
## Features
|
||||
|
||||
- 10 namespaced codes covering session, database, OAuth, mapping and mount-time
|
||||
failure surfaces.
|
||||
- `BetterAuthErrorCode` literal-union derived from the code bag — narrows
|
||||
exhaustively in `switch`.
|
||||
- `BetterAuthError` class extending `SuaveplanError` so `instanceof` and
|
||||
structural matching (`err.betterAuthCode`) both work.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
AUTH_BA_CODES,
|
||||
BetterAuthError,
|
||||
} from "@suaveplan/api-auth-better-auth/error-codes";
|
||||
|
||||
if (!session) {
|
||||
throw new BetterAuthError(
|
||||
AUTH_BA_CODES.INVALID_SESSION,
|
||||
"session resolver returned no principal"
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
AUTH_BA_CODES,
|
||||
BetterAuthError,
|
||||
type BetterAuthErrorCode,
|
||||
} from "@suaveplan/api-auth-better-auth/error-codes";
|
||||
|
||||
function describe(code: BetterAuthErrorCode): string {
|
||||
switch (code) {
|
||||
case AUTH_BA_CODES.OAUTH_STATE_MISMATCH:
|
||||
return "Tampered or stale state parameter — restart the flow";
|
||||
case AUTH_BA_CODES.OAUTH_PROVIDER_REJECTED:
|
||||
return "The upstream IdP rejected our token request";
|
||||
default:
|
||||
return "Unhandled Better-Auth adapter failure";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await router.handle(request);
|
||||
} catch (err) {
|
||||
if (err instanceof BetterAuthError) {
|
||||
logger.warn(describe(err.betterAuthCode), { code: err.code, cause: err.cause });
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
| Export | Shape | Purpose |
|
||||
| ------ | ----- | ------- |
|
||||
| `AUTH_BA_CODES` | `Readonly<Record<Name, "AUTH_BA.${Name}">>` | Frozen bag of every documented code |
|
||||
| `BetterAuthErrorCode` | string-literal union | The exact set of values `code` may take |
|
||||
| `BetterAuthError` | class extending `SuaveplanError` | Throwable carrying a `BetterAuthErrorCode` |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`defineCodes("AUTH_BA", [...])` from `@suaveplan/error` is the only way to mint
|
||||
codes — it freezes the bag and produces the string-literal type. Adding a new
|
||||
code requires (1) an OpenSpec change against the `api-auth-better-auth`
|
||||
capability so the spec delta lists the new code, (2) editing the tuple here,
|
||||
and (3) editing every consumer `switch` block. The redundant
|
||||
`betterAuthCode` field mirrors `code` so transport boundaries that drop the
|
||||
prototype chain (worker, IPC) can still match structurally.
|
||||
Reference in New Issue
Block a user