first commit
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# `error-codes`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the stable `DATABASE_*` error-code registry consumed by every other module in the `@suaveplan/api-plugin-database` package and by downstream observers that branch on `error.code`. The codes are registered through `defineCodes` from `@suaveplan/error` so they participate in the cross-package code namespace and inherit the canonical `SuaveplanError` wire-format, redaction, and OTel span-event integration.
|
||||
|
||||
The companion `DatabaseError` class extends `SuaveplanError<DatabaseErrorCode>` so `instanceof DatabaseError` narrows `error.code` to the literal union at every catch site. Consumers can write `if (error instanceof DatabaseError && error.code === DATABASE_CODES.POOL_EXHAUSTED)` and get exhaustive type checking from TypeScript.
|
||||
|
||||
## Features
|
||||
|
||||
- Eight stable codes spanning connection, pool, query, migration, lock, tenant, and configuration concerns.
|
||||
- Literal-typed code values (`"DATABASE.POOL_EXHAUSTED"`, etc.) computed by `defineCodes`.
|
||||
- `DatabaseError` carries `cause`, `context`, `timestamp`, and i18n message-key support inherited from `SuaveplanError`.
|
||||
- Frozen registry object — runtime mutation throws.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
DATABASE_CODES,
|
||||
DatabaseError,
|
||||
} from "@suaveplan/api-plugin-database/error-codes/error-codes";
|
||||
|
||||
throw new DatabaseError(
|
||||
DATABASE_CODES.POOL_EXHAUSTED,
|
||||
"no free connections available after 5s"
|
||||
);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
DATABASE_CODES,
|
||||
DatabaseError,
|
||||
type DatabaseErrorCode,
|
||||
} from "@suaveplan/api-plugin-database";
|
||||
|
||||
function isTransient(code: DatabaseErrorCode): boolean {
|
||||
return (
|
||||
code === DATABASE_CODES.POOL_EXHAUSTED ||
|
||||
code === DATABASE_CODES.CONNECTION_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await db.query("SELECT * FROM users");
|
||||
} catch (err) {
|
||||
if (err instanceof DatabaseError && isTransient(err.code)) {
|
||||
// exponential backoff retry path
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `DATABASE_CODES`
|
||||
|
||||
Frozen object mapping reason → fully-qualified code string. Exact keys: `CONNECTION_FAILED`, `POOL_EXHAUSTED`, `POOL_CLOSED`, `QUERY_FAILED`, `MIGRATION_FAILED`, `LOCK_CONTENDED`, `TENANT_INVALID`, `INVALID_CONFIG`.
|
||||
|
||||
### `DatabaseErrorCode`
|
||||
|
||||
Literal union of the eight code strings (e.g. `"DATABASE.POOL_EXHAUSTED"`).
|
||||
|
||||
### `class DatabaseError extends SuaveplanError<DatabaseErrorCode>`
|
||||
|
||||
- `new DatabaseError(code, message, options?)` — constructs an error carrying the supplied code. Options accept `cause`, `context`, and `clock` per the parent class.
|
||||
- `databaseCode` — convenience alias of `code` typed at the literal union.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The registry intentionally avoids redundant `INTERNAL` / `UNKNOWN` slots. Every wrapper in this package uses one of the eight codes; anything truly unexpected propagates as the underlying `Error`.
|
||||
- Adding a code is a breaking change for the API surface (the literal union widens) — bump the package version and add a `## MODIFIED Requirements` entry in the spec delta.
|
||||
- `defineCodes` freezes the returned object; tests verify the surface against the registered list rather than the implementation.
|
||||
Reference in New Issue
Block a user