first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
# `error-codes` — `MIGRATION_*` registry and `MigrationError`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
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
```ts
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.