first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# error-codes
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the stable error-code registry and typed error class for
|
||||
`@suaveplan/api-openapi`. Every public failure path in the package raises
|
||||
an `OpenAPIError` carrying one of the three `OPENAPI.*` codes, allowing
|
||||
downstream consumers to branch on `error.code` for recovery, telemetry,
|
||||
or user-facing message rendering. The registry is frozen at module load
|
||||
so codes cannot be added or mutated at runtime, which keeps the wire
|
||||
contract stable across versions.
|
||||
|
||||
The package intentionally exposes a small, deliberate code surface —
|
||||
this is an OpenAPI document builder, not a request validator, so most
|
||||
failure modes are caller-error rather than runtime-error. Three codes
|
||||
cover the entire surface.
|
||||
|
||||
## Features
|
||||
|
||||
- Frozen `OPENAPI_CODES` const map produced by `defineCodes("OPENAPI", …)`.
|
||||
- `OpenAPIErrorCode` discriminated string-literal union.
|
||||
- `OpenAPIError` subclass of `SuaveplanError` with public constructor,
|
||||
redundant `openapiCode` field for symmetric narrowing, and full
|
||||
`cause` / `context` / `requestId` propagation.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { OPENAPI_CODES, OpenAPIError } from "@suaveplan/api-openapi/error-codes";
|
||||
|
||||
throw new OpenAPIError(
|
||||
OPENAPI_CODES.SCHEMA_NOT_FOUND,
|
||||
`schema "${name}" is not registered`
|
||||
);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { OPENAPI_CODES, OpenAPIError } from "@suaveplan/api-openapi/error-codes";
|
||||
|
||||
try {
|
||||
registry.extend("User", "UserPublic", { exposedAt: z.string() });
|
||||
} catch (e) {
|
||||
if (e instanceof OpenAPIError && e.code === OPENAPI_CODES.INVALID_BASE_SCHEMA) {
|
||||
// The base name resolved to a non-ZodObject. Re-throw with
|
||||
// a richer context so the caller knows which schema failed.
|
||||
throw new OpenAPIError(e.code, e.message, {
|
||||
cause: e,
|
||||
context: { baseName: "User", attemptedExtension: "UserPublic" },
|
||||
});
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `OPENAPI_CODES` — frozen `{ INVALID_INPUT, SCHEMA_NOT_FOUND, INVALID_BASE_SCHEMA }` mapping local keys to `"OPENAPI.*"` wire codes.
|
||||
- `type OpenAPIErrorCode` — union of the three wire codes.
|
||||
- `class OpenAPIError extends SuaveplanError<OpenAPIErrorCode>` — public constructor `(code, message, options?)`, mirrors code in `.openapiCode`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The registry deliberately defines exactly three codes — adding new ones
|
||||
without bumping a major and updating consumers risks silent gaps in
|
||||
downstream error branches. New failure modes should either map onto one
|
||||
of the existing codes or be added in a coordinated change covered by an
|
||||
OpenSpec delta.
|
||||
|
||||
`OPENAPI.INVALID_BASE_SCHEMA` is the one behavioural divergence from
|
||||
upstream `@suaveplan/api`'s schema-registry — upstream silently returned
|
||||
`undefined` from `extend`/`partial`/`pick`/`omit` when the base was not
|
||||
a `ZodObject`. We raise so the caller learns why the derivation failed,
|
||||
which removes a class of "schema mysteriously missing" bugs that were
|
||||
near-impossible to diagnose in upstream.
|
||||
|
||||
The class is side-effect-imported by the package root barrel
|
||||
(`src/index.ts`) so consumers picking up `@suaveplan/api-openapi`
|
||||
surface the code registry without depending on a sub-export path.
|
||||
Reference in New Issue
Block a user