first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# `error-codes` — `PLUGIN.EXAMPLE.*` registry + status map
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The reference plugin owns a small set of stable error codes that the
|
||||
integration suite asserts are surfaced through the host's error
|
||||
boundary with the manifest-declared HTTP statuses. The registry lives
|
||||
in a single file so the runtime, the manifest, and the integration
|
||||
tests share one source of truth.
|
||||
|
||||
The plugin throws an {@link ExamplePluginError} carrying a
|
||||
{@link ExamplePluginCode}. The host error boundary consults
|
||||
{@link EXAMPLE_STATUS_MAP} to compute the response status. The map is
|
||||
mirrored verbatim in `plugin.json` under `errors.statusMap` so a code
|
||||
appearing on one side and missing on the other fails the
|
||||
`validate-error-status-map-shape` manifest validator.
|
||||
|
||||
## Features
|
||||
|
||||
- Discriminated `ExamplePluginCode` union — every code one literal.
|
||||
- Frozen `EXAMPLE_CODES` constant for index-by-name access.
|
||||
- `EXAMPLE_STATUS_MAP` aligned with `plugin.json`.
|
||||
- Plain `Error` subclass — no heavyweight `SuaveplanError` import.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
EXAMPLE_CODES,
|
||||
ExamplePluginError,
|
||||
} from "@suaveplan/api-plugin-example/error-codes/error-codes";
|
||||
|
||||
if (invoice === null) {
|
||||
throw new ExamplePluginError(
|
||||
EXAMPLE_CODES.INVOICE_NOT_FOUND,
|
||||
`invoice ${id} not found`
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
The integration test reads the registry directly to assert every code
|
||||
is raised by at least one production path:
|
||||
|
||||
```ts
|
||||
import {
|
||||
EXAMPLE_CODES,
|
||||
EXAMPLE_STATUS_MAP,
|
||||
} from "@suaveplan/api-plugin-example/error-codes/error-codes";
|
||||
|
||||
for (const code of Object.values(EXAMPLE_CODES)) {
|
||||
expect(EXAMPLE_STATUS_MAP[code]).toBeDefined();
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `EXAMPLE_CODES` — Frozen `Record<string, ExamplePluginCode>`.
|
||||
- `EXAMPLE_STATUS_MAP` — Frozen `Record<ExamplePluginCode, number>`.
|
||||
- `ExamplePluginError(code, message)` — Plain `Error` subclass with
|
||||
`code` field.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`ExamplePluginCode` is a string-literal union, not a `enum`, so the
|
||||
runtime cost is zero and the values appear unchanged in stack traces.
|
||||
The registry is `Object.freeze`d to prevent silent drift between the
|
||||
manifest and runtime. The Suaveplan convention is to reuse `Error`
|
||||
rather than `SuaveplanError` for leaf plugins — the host's boundary
|
||||
only reads `code`, so any subclass works.
|
||||
Reference in New Issue
Block a user