# error-codes — stable CONTACTS_API.* registry _(no submodules)_ ## 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` — 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.