first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# `error-codes`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines `LIFECYCLE_CODES` — the frozen, namespaced registry of the four error
|
||||
codes raised by the `@suaveplan/api-lifecycle` package — and `LifecycleError`,
|
||||
the typed `SuaveplanError` subclass that carries them. Every failure path in
|
||||
the lifecycle package (illegal transition, mutex contention, retry-budget
|
||||
exhaustion, manifest version downgrade) constructs a `LifecycleError` so
|
||||
callers can branch on either `instanceof LifecycleError` or the stable
|
||||
`error.code` string.
|
||||
|
||||
## Features
|
||||
|
||||
- Four-code registry built via `@suaveplan/error`'s `defineCodes` helper, so
|
||||
the produced map is type-narrowed to `{ readonly K: "LIFECYCLE.K" }`.
|
||||
- `LifecycleError` extends `SuaveplanError<LifecycleCode>` — `instanceof`
|
||||
works, and the name is set to `"LifecycleError"` for self-describing
|
||||
stack traces.
|
||||
- Frozen at module load (`Object.freeze`), so accidental mutation throws in
|
||||
strict mode rather than silently corrupting the registry.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { LIFECYCLE_CODES, LifecycleError } from "@suaveplan/api-lifecycle/error-codes";
|
||||
|
||||
throw new LifecycleError(
|
||||
LIFECYCLE_CODES.ILLEGAL_TRANSITION,
|
||||
"Cannot transition from installed → stopped without going through stopping",
|
||||
);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Discriminating in a generic error handler:
|
||||
|
||||
```ts
|
||||
import { LifecycleError, LIFECYCLE_CODES } from "@suaveplan/api-lifecycle/error-codes";
|
||||
|
||||
function handle(err: unknown): "retry" | "park" | "abort" {
|
||||
if (!(err instanceof LifecycleError)) return "abort";
|
||||
switch (err.code) {
|
||||
case LIFECYCLE_CODES.RETRY_BUDGET_EXHAUSTED:
|
||||
return "park";
|
||||
case LIFECYCLE_CODES.MUTEX_HELD:
|
||||
return "retry";
|
||||
default:
|
||||
return "abort";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `code` is a template-literal type so exhaustiveness checks in `switch`
|
||||
statements catch missing branches at compile time.
|
||||
|
||||
## API Reference
|
||||
|
||||
- `LIFECYCLE_CODES` — frozen record. Keys: `ILLEGAL_TRANSITION`, `MUTEX_HELD`,
|
||||
`RETRY_BUDGET_EXHAUSTED`, `REINSTALL_REQUIRED_VERSION_DOWNGRADE`.
|
||||
- `type LifecycleCode` — the union of every code's fully-qualified string.
|
||||
- `class LifecycleError` — constructor `(code, message, options?)` mirroring
|
||||
the `SuaveplanError` shape.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
This file is the single source of truth for the namespace string `LIFECYCLE`.
|
||||
Adding a new code requires appending the bare reason to the tuple passed to
|
||||
`defineCodes` — the type is inferred from that tuple, so no other code change
|
||||
is needed. The error class itself is `protected constructor` upstream; this
|
||||
package narrows the namespace and adds `name = "LifecycleError"`.
|
||||
Reference in New Issue
Block a user