3.0 KiB
error-codes
Purpose
Defines the canonical error-code registry for @suaveplan/installer and the
InstallerError class that carries those codes. Every failure path inside
the host — manifest validation, plugin discovery, prompt validation,
plan validation, conflict resolution, apply, and rollback — surfaces as an
InstallerError with a literal-typed code drawn from this registry. That
contract makes failures machine-classifiable: callers can write exhaustive
switch statements on code and add new codes only by extending the
registry, never by string-matching free-form messages.
Features
- Frozen registry built via
defineCodes("INSTALLER", [...])from@suaveplan/error, soObject.isFrozen(INSTALLER_CODES)istrueat module load time. - All codes are namespaced as
INSTALLER.<REASON>strings. InstallerErrorextendsSuaveplanError<InstallerErrorCode>soinstanceofplus.codenarrowing remains exhaustive.- Public widened constructor — callers can
throw new InstallerError(code, key, options)directly without going through a factory. - Stable code surface: nine reasons (
PLUGIN_NOT_FOUND,PLUGIN_LOAD_FAILED,PLUGIN_INVALID_MANIFEST,PROMPT_VALIDATION_FAILED,PLAN_FAILED,APPLY_CONFLICT,APPLY_FAILED,ROLLBACK_FAILED,ABORTED).
Basic Example
import { INSTALLER_CODES, InstallerError } from "@suaveplan/installer";
throw new InstallerError(
INSTALLER_CODES.PLUGIN_NOT_FOUND,
"installer.plugin.not_found",
{ context: { id: "agent-skills" } }
);
Advanced Example
import { InstallerError } from "@suaveplan/installer";
function classify(err: unknown): string {
if (!(err instanceof InstallerError)) return "unknown";
switch (err.code) {
case "INSTALLER.PLUGIN_NOT_FOUND":
return "missing-plugin";
case "INSTALLER.APPLY_CONFLICT":
return "conflict";
case "INSTALLER.ROLLBACK_FAILED":
return "fatal-rollback";
default:
return "other";
}
}
API Reference
INSTALLER_CODES— frozen{ [K]: "INSTALLER.K" }map. Read-only at runtime and at the type level.type InstallerErrorCode— union of everyINSTALLER.*literal in the registry.class InstallerError extends SuaveplanError<InstallerErrorCode>— carriescode,message, optionalcause,context,timestamp, andtraceIdfrom the base class.
Implementation Notes
defineCodes freezes the returned object so consumers cannot mutate the
registry — this matches the conformance assertion in
error-codes.spec-conformance.test.ts (INSTALLER-09). The
InstallerError constructor sets this.name = "InstallerError" because
SuaveplanError's default new.target.name is reset by some bundlers and
the explicit assignment guarantees stable serialised names. Every throw
inside this package should pick a code from this registry; throwing a bare
Error from internal code is treated as a regression by the conformance
suite.