first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user