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,107 @@
# error-codes — stable CONTACTS_API.* registry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Single source of truth for every failure path inside
`@suaveplan/api-plugin-contacts`. Built on the suaveplan
`@suaveplan/error` foundation (`defineCodes` + `SuaveplanError`) so
codes are typed as a string-literal union and the registry is wire-
stable across versions. Consumers (UI translation layers, response
encoders, log shippers) branch on `error.code` without sniffing the
message text.
The 12 codes split cleanly into three groups: lifecycle errors
(`INVALID_INPUT`, `SERVICE_NOT_AVAILABLE`, `SCHEMA_APPLY_FAILED`,
`ROUTE_PREFIX_COLLISION`), boundary errors visible to HTTP callers
(`NOT_FOUND`, `UNAUTHORIZED`, `IMPORT_TOO_LARGE`), and operation
errors raised by the SurrealDB repositories (`CREATE_FAILED`,
`UPDATE_FAILED`, `DELETE_FAILED`, `GROUP_DEPTH_EXCEEDED`,
`MEMBERSHIP_EXISTS`).
## Features
- Stable code strings prefixed with `CONTACTS_API.` (built via
`defineCodes`) — safe to log or send to clients.
- `ContactsApiError` subclass of `SuaveplanError` preserves the
underlying `cause`, optional structured `context`, and a redactable
message.
- Codes are exhaustive: every `throw` in the production tree uses
exactly one of the 12; the spec-conformance test pins this.
## Usage: Basic
```ts
import {
CONTACTS_API_CODES,
ContactsApiError,
} from "@suaveplan/api-plugin-contacts";
throw new ContactsApiError(
CONTACTS_API_CODES.NOT_FOUND,
"contact not found",
{ context: { statusCode: 404 } }
);
```
## Usage: Advanced
```ts
import {
CONTACTS_API_CODES,
type ContactsApiErrorCode,
ContactsApiError,
} from "@suaveplan/api-plugin-contacts";
function toHttpStatus(code: ContactsApiErrorCode): number {
switch (code) {
case CONTACTS_API_CODES.NOT_FOUND:
return 404;
case CONTACTS_API_CODES.UNAUTHORIZED:
return 401;
case CONTACTS_API_CODES.IMPORT_TOO_LARGE:
case CONTACTS_API_CODES.GROUP_DEPTH_EXCEEDED:
case CONTACTS_API_CODES.INVALID_INPUT:
return 400;
case CONTACTS_API_CODES.MEMBERSHIP_EXISTS:
return 409;
default:
return 500;
}
}
try {
/* … */
} catch (err) {
if (err instanceof ContactsApiError) {
return Response.json(
{ success: false, code: err.code, error: err.message },
{ status: toHttpStatus(err.contactsApiCode) }
);
}
throw err;
}
```
## API Reference
- `CONTACTS_API_CODES` — frozen registry returned by
`defineCodes("CONTACTS_API", [...])`.
- `ContactsApiErrorCode` — string-literal union of every member of
`CONTACTS_API_CODES`.
- `class ContactsApiError extends SuaveplanError<ContactsApiErrorCode>`
— constructor `(code, message, options?)`. Stores the original code
on `contactsApiCode` for ergonomic narrowing.
## Implementation Notes
- The registry is declared `as const`; `defineCodes` returns the frozen
mapping (`{ CODE: "CONTACTS_API.CODE", … }`) so callers cannot
accidentally mutate it.
- The constructor delegates to `SuaveplanError`, which threads
`cause`, `context`, and a default `name` through. No code path here
re-implements that — adding a new code only requires adding a string
literal to the `as const` array.