first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# error-codes
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Stable error-code registry and `SseError` class for `@suaveplan/api-plugin-sse`. Every failure path in the plugin raises an `SseError` carrying one of eight `SSE_*` codes so consumers can branch deterministically on the string value rather than parsing error messages. Codes are declared via `defineCodes("SSE", [...] as const)` so the type system narrows `error.code` to a literal-string union — handlers cannot accidentally branch on an unregistered code.
## Features
- 8 stable codes covering authentication, capacity, lifecycle, validation, and backpressure failures.
- `SseError extends SuaveplanError<SseErrorCode>` so `instanceof SseError` narrows the `code` field.
- Public constructor for direct instantiation from callers.
- `cause` chain preserved for upstream `ZodError` and runtime failures.
- `context` carries diagnostic payload (`channel`, `principalId`, `max`, `statusCode`).
## Usage: Basic
```ts
import { SSE_CODES, SseError } from "@suaveplan/api-plugin-sse/error-codes/error-codes";
try {
service.subscribe({ channel: "" });
} catch (err) {
if (err instanceof SseError && err.code === SSE_CODES.CHANNEL_REQUIRED) {
return Response.json({ error: "channel required" }, { status: 400 });
}
throw err;
}
```
## Usage: Advanced
```ts
import { SSE_CODES, SseError } from "@suaveplan/api-plugin-sse/error-codes/error-codes";
// Map every SSE_* code to an HTTP status for a unified handler.
const STATUS_BY_CODE: Record<string, number> = {
[SSE_CODES.UNAUTHENTICATED]: 401,
[SSE_CODES.PER_PRINCIPAL_LIMIT_EXCEEDED]: 429,
[SSE_CODES.TOO_MANY_CONNECTIONS]: 429,
[SSE_CODES.CHANNEL_REQUIRED]: 400,
[SSE_CODES.INVALID_INPUT]: 400,
[SSE_CODES.SERVICE_NOT_AVAILABLE]: 500,
[SSE_CODES.CLOSED]: 503,
[SSE_CODES.QUEUE_OVERFLOW]: 503,
};
app.onError((err, c) => {
if (err instanceof SseError) {
return c.json(
{ code: err.code, message: err.message, context: err.context },
STATUS_BY_CODE[err.code] ?? 500
);
}
return c.text("internal", 500);
});
```
## API Reference
- `SSE_CODES` — frozen record produced by `defineCodes("SSE", [...] as const)`. Keys: `UNAUTHENTICATED`, `TOO_MANY_CONNECTIONS`, `PER_PRINCIPAL_LIMIT_EXCEEDED`, `CHANNEL_REQUIRED`, `SERVICE_NOT_AVAILABLE`, `INVALID_INPUT`, `QUEUE_OVERFLOW`, `CLOSED`. Values are `SSE.<KEY>` strings.
- `type SseErrorCode` — union of every value in `SSE_CODES`.
- `class SseError extends SuaveplanError<SseErrorCode>` — public constructor `(code, message, options?)`. `options` accepts `{ cause?, context? }` per `SuaveplanErrorOptions`.
## Implementation Notes
- `QUEUE_OVERFLOW` is not thrown — it is attached to the `sse.queue_overflow_total` OTel counter as the `code` attribute so dashboards can correlate drops with the registry entry without inventing a parallel taxonomy.
- `UNAUTHENTICATED` is thrown only when the handler is configured with `requirePrincipal: true` AND `resolvePrincipalId` returned `undefined`. Anonymous routes never raise it.
- `SERVICE_NOT_AVAILABLE` carries `context.missing: string[]` so the orchestrator can list every missing slot in one failure message.
- All codes are stable across versions — adding new codes is additive; removing a code is a breaking change.