# `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."`. `SiteError extends SuaveplanError` 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 ```ts 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 ```ts 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."` literals. - `SiteErrorCode` — string-literal union of every value in `SITE_CODES`. - `class SiteError extends SuaveplanError` — 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.