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

3.0 KiB

error-codes/error-codes.ts

(no submodules)

Purpose

Owns the stable SITE.* error-code registry and the SiteError class used by every public API path in @suaveplan/api-plugin-site. Each code is a stable string that consumers can pattern-match without relying on message text — important for cross-version compatibility, log aggregation, alert routing, and HTTP-status mapping. Centralising the codes in one file makes the contract auditable in a single grep and prevents new code paths from inventing ad-hoc strings.

The registry is built with defineCodes("SITE", [...]) from @suaveplan/error, which freezes the array into a readonly object whose values are namespaced "SITE.<KEY>". SiteError extends SuaveplanError<SiteErrorCode> so instanceof SiteError narrows error.code to the literal-union SiteErrorCode.

Features

  • 14 canonical codes covering input validation, lifecycle wiring, site CRUD, domain CRUD, resolution failures, and bootstrap failures.
  • SiteError constructor accepts SuaveplanErrorOptions so callers can attach cause, context, and structured fields.
  • Stable string codes — error.code === SITE_CODES.SITE_NOT_FOUND survives minification and i18n.
  • Per-code doc comment naming the HTTP status the route layer maps to.
  • Zero runtime dependencies beyond @suaveplan/error.

Usage: Basic

import { SITE_CODES, SiteError } from "@suaveplan/api-plugin-site/error-codes/error-codes";

if (site === null) {
    throw new SiteError(SITE_CODES.SITE_NOT_FOUND, `site '${id}' not found`);
}

Usage: Advanced

import { SITE_CODES, SiteError } from "@suaveplan/api-plugin-site/error-codes/error-codes";

try {
    await db.query("SELECT * FROM site WHERE id = $p0", [id]);
} catch (cause) {
    throw new SiteError(SITE_CODES.STORAGE_ERROR, "SurrealDB query failed", {
        cause: cause instanceof Error ? cause : undefined,
        context: { statusCode: 502, id },
    });
}

// Discrimination at a boundary:
if (err instanceof SiteError && err.code === SITE_CODES.DOMAIN_ALREADY_CLAIMED) {
    return c.json({ error: err.message }, 409);
}

API Reference

  • SITE_CODES — readonly object of 14 keys mapped to namespaced "SITE.<KEY>" literals.
  • SiteErrorCode — string-literal union of every value in SITE_CODES.
  • class SiteError extends SuaveplanError<SiteErrorCode> — constructor (code, message, options?). Exposes siteCode as a typed alias of code.

Implementation Notes

  • The registry is the contract: deleting a code to satisfy a coverage gate is forbidden by AGENTS.md §2c. Every code MUST be thrown by at least one production path, asserted by error-codes.test.ts.
  • HTTP statuses are documented per-code but the mapping is performed by the route layer (routes/) via error.context.statusCode — the registry itself is transport-agnostic.
  • New codes require a registry edit, an OpenSpec change, and a test that drives the new throw path. There are no silent additions.