Files
skills/docs/api-stack/api/api-plugin-events/src/error-codes/error-codes.md
2026-05-29 08:20:56 +01:00

3.8 KiB

error-codes

(no submodules)

Purpose

Defines the stable error-code registry and concrete error class for @suaveplan/api-plugin-events. Every failure path in the plugin — configuration validation, lifecycle wiring, repository write paths, route-handler authorisation — raises an EventsPluginError carrying exactly one of the twelve EVENTS_PLUGIN.* codes. The registry is the contract: consumers branch on error.code === EVENTS_PLUGIN_CODES.RSVP_NOT_FOUND and receive EventsPluginErrorCode narrowing for free.

The namespace literal is "EVENTS_PLUGIN" rather than the obvious "EVENTS" to avoid a hard collision with @suaveplan/events (the typed event-bus already shipped ). The event-bus library owns the EVENTS_* prefix; this plugin uses the longer prefix so both registries can coexist in the same project without either having to rename codes downstream.

Features

  • 12 documented codes covering every public failure surface.
  • EventsPluginError extends SuaveplanError so instanceof narrows error.code to EventsPluginErrorCode.
  • Side-effect-free import — import "./error-codes.js" for code registry registration with zero runtime cost.
  • cause chain + context bag forwarded to the @suaveplan/error base class for OTel span events and i18n resolution.

Usage: Basic Example

import {
    EVENTS_PLUGIN_CODES,
    EventsPluginError,
} from "@suaveplan/api-plugin-events";

throw new EventsPluginError(
    EVENTS_PLUGIN_CODES.EVENT_NOT_FOUND,
    "Event not found"
);

Usage: Advanced Example

import {
    EVENTS_PLUGIN_CODES,
    EventsPluginError,
    type EventsPluginErrorCode,
} from "@suaveplan/api-plugin-events";

function describe(code: EventsPluginErrorCode): string {
    switch (code) {
        case EVENTS_PLUGIN_CODES.INVALID_CONFIG:
            return "configuration rejected by Zod";
        case EVENTS_PLUGIN_CODES.EVENT_CREATE_FAILED:
            return "adapter returned no row from CREATE event";
        default:
            return code;
    }
}

try {
    // ...
} catch (err) {
    if (err instanceof EventsPluginError) {
        const label = describe(err.code);
        // forward to logger / OTel
        console.error(label, err.context, err.cause);
    }
}

API Reference

EVENTS_PLUGIN_CODES

A frozen object mapping each code key to its stable string value:

  • INVALID_CONFIG — Zod-validated options were rejected.
  • SERVICE_NOT_AVAILABLE — required ServiceRegistry slot missing.
  • ROUTE_PREFIX_COLLISION — onReady would shadow existing routes.
  • EVENT_CREATE_FAILED / EVENT_UPDATE_FAILED — adapter returned no row.
  • RSVP_CREATE_FAILED / RSVP_UPDATE_FAILED — adapter returned no row.
  • RSVP_NOT_FOUND / EVENT_NOT_FOUND — lookup miss.
  • UNAUTHENTICATED — c.get("user") was missing on a route.
  • FORBIDDEN — non-creator hit a mutating endpoint.
  • INVITE_LIMIT_EXCEEDED — user_ids length exceeded the runtime cap.

EventsPluginErrorCode

Union of all values in EVENTS_PLUGIN_CODES — useful for exhaustive switch over caught errors.

EventsPluginError

class EventsPluginError extends SuaveplanError<EventsPluginErrorCode> {
    constructor(
        code: EventsPluginErrorCode,
        message: string,
        options?: SuaveplanErrorOptions
    );
    readonly eventsPluginCode: EventsPluginErrorCode;
}

Implementation Notes

The 12-code registry is fixed for 0.x — adding a code is a minor bump, removing or renaming one is a major bump. The error-codes.test.ts reflects over the registry and grep-asserts each value reaches a throw new EventsPluginError call site under src/; that test is the canonical proof that no code is a dangling declaration. Removing a code to make the test pass is explicitly banned by AGENTS.md §2c — wire the missing throw site instead.