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

3.6 KiB

error-codes — MIGRATION_* registry and MigrationError

(no submodules)

Purpose

Defines the stable, namespaced error registry for @suaveplan/api-migrations. Every public failure path in the package raises a MigrationError carrying exactly one of the six MIGRATION.* codes defined here. The codes are authored once at draft time and may not be renumbered or renamed without an OpenSpec change, so consumers may branch on the literal string values across versions.

The pairing of defineCodes("MIGRATION", [...]) (from @suaveplan/error) with a typed SuaveplanError subclass keeps the surface narrow: the runtime sees a frozen registry object, TypeScript sees a literal union, and consumers get an instanceof MigrationError narrowing the code field to MigrationErrorCode.

Features

  • Frozen registry of exactly six codes.
  • MigrationError is a public-constructor subclass of SuaveplanError.
  • instanceof MigrationError narrows error.code to MigrationErrorCode.
  • The migrationCode field is a synonym for code typed as the literal union, useful inside generic helpers that have already widened code.
  • Every code is exercised by the package's spec-conformance test.

Usage: Basic Example

import {
    MIGRATION_CODES,
    MigrationError,
} from "@suaveplan/api-migrations/error-codes/error-codes";

throw new MigrationError(
    MIGRATION_CODES.DIRECTORY_NOT_FOUND,
    "Migration directory does not exist: ./db/migrations",
    { context: { dir: "./db/migrations" } }
);

Usage: Advanced Example

import {
    MIGRATION_CODES,
    MigrationError,
    type MigrationErrorCode,
} from "@suaveplan/api-migrations/error-codes/error-codes";

function isRecoverable(code: MigrationErrorCode): boolean {
    return (
        code === MIGRATION_CODES.CHECKSUM_DRIFT ||
        code === MIGRATION_CODES.INVALID_FILE_NAME
    );
}

try {
    await runner.runFromDirectory("./db/migrations");
} catch (err) {
    if (err instanceof MigrationError && isRecoverable(err.code)) {
        // Operator-fixable conditions: stale file or rename.
        console.error("Recoverable migration error:", err.code, err.context);
    } else {
        throw err;
    }
}

API Reference

  • MIGRATION_CODES — frozen registry { TABLE_BOOTSTRAP_FAILED, APPLY_FAILED, CHECKSUM_DRIFT, DIRECTORY_NOT_FOUND, INVALID_FILE_NAME, ROLLBACK_NOT_SUPPORTED }, each value the literal string of the form "MIGRATION.<NAME>".
  • type MigrationErrorCode — union of the six literal strings.
  • class MigrationError extends SuaveplanError<MigrationErrorCode> — constructor (code, message, options?). options.context and options.cause are forwarded to the base class. migrationCode is a typed alias of code.

Implementation Notes

  • The registry is authored as as const and passed to defineCodes, which freezes the resulting object and returns a strongly typed map. Renaming or renumbering codes is a breaking change that must be made through OpenSpec.
  • MigrationError's constructor is public so call sites may instantiate it directly; SuaveplanError's constructor is protected and would otherwise refuse construction outside of subclasses.
  • migrationCode exists in addition to code because some generic helpers (logging, OTel attribute attachment) widen the type to string for ergonomics; tests and downstream consumers that want the narrow union read migrationCode instead.
  • Every code is thrown from at least one production call site — see src/api-migrations.spec-conformance.test.ts for the inventory.