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,92 @@
# `error-codes`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Stable error-code registry for `@suaveplan/api-plugin-notifications`. The
module exports a frozen `NOTIFICATIONS_PLUGIN_CODES` map produced by the
`defineCodes("NOTIFICATIONS_PLUGIN", [...])` helper from `@suaveplan/error`,
plus a concrete `NotificationsPluginError` class that extends
`SuaveplanError<NotificationsPluginErrorCode>`. The namespace literal
deliberately differs from `EVENTS` (owned by `@suaveplan/events`) and
`EVENTS_PLUGIN` (owned by `@suaveplan/api-plugin-events`) so the global
registry never silently shadows codes registered by sibling packages.
## Features
- Eighteen stable codes spanning configuration, lifecycle, repository,
device-token, route, and APN-transport failure modes.
- Type-level narrowing via `NotificationsPluginErrorCode` so any
`instanceof NotificationsPluginError` check pins `error.code` to one
of the declared literals.
- Structured `context` and `cause` passthrough — the constructor
forwards every `SuaveplanErrorOptions` field to the base class so
Zod `ZodError`s, raw `Error`s, and arbitrary telemetry context all
travel together.
- A spec-conformance test reflects the registry at load time and
greps the rest of `src/` to assert every code is referenced from a
real `throw new NotificationsPluginError(...)` site.
## Usage: Basic
```ts
import {
NOTIFICATIONS_PLUGIN_CODES,
NotificationsPluginError,
} from "@suaveplan/api-plugin-notifications";
throw new NotificationsPluginError(
NOTIFICATIONS_PLUGIN_CODES.NOTIFICATION_NOT_FOUND,
"Notification not found",
{ context: { id: "notification:abc" } }
);
```
## Usage: Advanced
Catch handlers narrow `error.code` to the registered literals so
branch-by-code routing stays type-safe without string literals leaking:
```ts
try {
await createNotification(...);
} catch (err) {
if (err instanceof NotificationsPluginError) {
switch (err.code) {
case NOTIFICATIONS_PLUGIN_CODES.APN_SEND_FAILED:
case NOTIFICATIONS_PLUGIN_CODES.APN_SERVICE_UNAVAILABLE:
return scheduleRetry(err);
case NOTIFICATIONS_PLUGIN_CODES.UNAUTHENTICATED:
case NOTIFICATIONS_PLUGIN_CODES.FORBIDDEN:
return reject403(err);
default:
throw err;
}
}
throw err;
}
```
## API Reference
- `NOTIFICATIONS_PLUGIN_CODES` — frozen record of literal codes
(`{ INVALID_CONFIG: "NOTIFICATIONS_PLUGIN.INVALID_CONFIG", ... }`).
- `NotificationsPluginErrorCode` — type alias of the value union.
- `NotificationsPluginError(code, message, options?)` — concrete error
class. Stores `code` on both the base `code` field and a redundant
`notificationsPluginCode` field to keep type narrowing crisp when the
base class is generic over the union.
## Implementation Notes
`defineCodes` accepts a namespace literal and a `readonly` tuple of
suffix literals; the helper returns a frozen record keyed by the suffix
with values `"<namespace>.<suffix>"`. Mutating the result is rejected
at runtime by the `Object.freeze` step inside `@suaveplan/error`. The
spec-conformance test depends on the constant identifier
(`NOTIFICATIONS_PLUGIN_CODES.SOMETHING`) appearing literally in source
files, so codes MUST be referenced by their constant name — not the
string literal — at every throw site.