Initial Commit
This commit is contained in:
113
packages/foundation/core/error/README.md
Normal file
113
packages/foundation/core/error/README.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# @suaveplan/error - Foundation error substrate — SuaveplanError base class, stable code registry, cause-chain traversal, Zod-validated wire format (JSON + MessagePack), redaction, OTel span-event adapter, i18n resolver hook. Zero @suaveplan/* deps.
|
||||
|
||||
## Summary
|
||||
|
||||
Foundation error substrate for Suaveplan. Every non-testing `@suaveplan/*` package extends this library's `SuaveplanError` base class and uses its stable code registry. The package provides: `SuaveplanError<TCode>` — an abstract base with literal-typed discriminant codes, injectable clock, context bag, traceId, and cause chaining; `defineCodes(namespace, reasons)` — a frozen, literal-typed registry that makes error codes refactor-safe; `walkCauses(err)` — a cycle-safe, depth-bounded generator for traversing nested error causes; lossless JSON and binary wire formats (`toJSON`/`fromJSON`/`toBinary`/`fromBinary`) with Zod validation; `markSensitive`/`unwrapSensitive` for redaction at serialization boundaries; `toSpanEvent` for OpenTelemetry `exception` span events without an OTel SDK import; and a `setMessageResolver` hook for i18n. Zero `@suaveplan/*` runtime or peer dependencies — this is the lowest-level package in the stack.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [package-error](./src/base/package-error.md) — `ErrorPackageError` is the one concrete `SuaveplanError` subclass shipped by `@suaveplan/error` itself. It carries the…
|
||||
- [suaveplan-error](./src/base/suaveplan-error.md) — `SuaveplanError` is the abstract base class that every non-testing package in the project extends. It standardises the…
|
||||
- [causes](./src/causes/walk-causes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [walk-causes](./src/causes/walk-causes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam…
|
||||
- [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat…
|
||||
- [i18n](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [resolver](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [otel](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [to-span-event](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [redact](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [sensitive](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib…
|
||||
- [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r…
|
||||
- [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W…
|
||||
- [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS…
|
||||
<!-- end:auto-docs --> - [walk-causes](./src/causes/walk-causes.md) — <!-- begin:auto-docs --> _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam…
|
||||
- [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat…
|
||||
- [i18n](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [resolver](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [to-span-event](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [redact](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [sensitive](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib…
|
||||
- [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r…
|
||||
- [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W…
|
||||
- [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS…
|
||||
- [walk-causes](./src/causes/walk-causes.md) — <!-- begin:auto-docs --> _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam…
|
||||
- [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat…
|
||||
- [i18n](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [resolver](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [to-span-event](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [redact](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [sensitive](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib…
|
||||
- [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r…
|
||||
- [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W…
|
||||
- [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS…
|
||||
- [walk-causes](./src/causes/walk-causes.md) — <!-- begin:auto-docs --> _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam…
|
||||
- [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat…
|
||||
- [i18n](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [resolver](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [to-span-event](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [redact](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [sensitive](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib…
|
||||
- [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r…
|
||||
- [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W…
|
||||
- [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS…
|
||||
- [walk-causes](./src/causes/walk-causes.md) — <!-- begin:auto-docs --> _(no submodules)_- [define-codes](./src/codes/define-codes.md) — `defineCodes` is the canonical way to declare a stable, literal-typed error code registry for a package. It takes a nam…
|
||||
- [error-codes](./src/codes/error-codes.md) — `ERROR_CODES` is the package-local registry for `@suaveplan/error` itself. It enumerates every failure mode the foundat…
|
||||
- [i18n](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_ - [resolver](./src/i18n/resolver.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_ - [to-span-event](./src/otel/to-span-event.md) — <!-- begin:auto-docs --> _(no submodules)_- [redact](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_ - [sensitive](./src/redact/sensitive.md) — <!-- begin:auto-docs --> _(no submodules)_- [from-binary](./src/serialize/from-binary.md) — `fromBinary` is the decode counterpart to `toBinary`. It accepts a `Uint8Array` produced by `toBinary` (or any compatib…
|
||||
- [from-json](./src/serialize/from-json.md) — `fromJSON` is the decode counterpart to `toJSON`. It Zod-validates the incoming payload against `wireErrorSchema` and r…
|
||||
- [to-binary](./src/serialize/to-binary.md) — `toBinary` encodes any error-shaped value into a compact byte payload suitable for binary transports (message queues, W…
|
||||
- [to-json](./src/serialize/to-json.md) — `toJSON` serialises any error-shaped value to a wire-safe plain object that round-trips losslessly back through `fromJS…
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/error
|
||||
```
|
||||
|
||||
## Highlights
|
||||
|
||||
- **`SuaveplanError<TCode>`** — abstract base with literal-typed code discriminants, injectable clock, context, traceId, cause
|
||||
- **`defineCodes(namespace, reasons)`** — frozen, literal-typed code registry
|
||||
- **`walkCauses(err)`** — cycle-safe, depth-bounded cause-chain generator
|
||||
- **`toJSON`/`fromJSON`/`toBinary`/`fromBinary`** — lossless, Zod-validated wire format; binary form is UTF-8-encoded canonical JSON, no external encoder
|
||||
- **`markSensitive` / `unwrapSensitive`** — redaction tagging applied at the serialization boundary
|
||||
- **`toSpanEvent`** — OpenTelemetry `exception` span event payload, no OTel SDK import
|
||||
- **`setMessageResolver`** — i18n hook; default resolver returns the key verbatim
|
||||
|
||||
## Foundation rules honoured
|
||||
|
||||
- Zero `@suaveplan/*` runtime or peer deps
|
||||
- Runtime deps: `tslib`, `zod`
|
||||
- Zero Node / browser built-in references in `src/` (guarded by `tests/no-disallowed.test.ts`)
|
||||
- `sideEffects: false`, per-module subpath exports
|
||||
- 100% statement / branch / function / line coverage (guarded in `vitest.config.ts`)
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { defineCodes, SuaveplanError } from "@suaveplan/error";
|
||||
|
||||
export const AUTH_CODES = defineCodes("AUTH", [
|
||||
"LOGIN.INVALID",
|
||||
"LOGIN.LOCKED",
|
||||
] as const);
|
||||
|
||||
export class AuthError extends SuaveplanError<
|
||||
(typeof AUTH_CODES)[keyof typeof AUTH_CODES]
|
||||
> {
|
||||
public constructor(
|
||||
code: (typeof AUTH_CODES)[keyof typeof AUTH_CODES],
|
||||
key: string,
|
||||
options?: ConstructorParameters<typeof SuaveplanError>[2]
|
||||
) {
|
||||
super(code, key, options);
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthError(AUTH_CODES["LOGIN.INVALID"], "error.auth.login.invalid", {
|
||||
context: { user: "alice" },
|
||||
traceId: "trace-1",
|
||||
});
|
||||
```
|
||||
|
||||
## Wire format
|
||||
|
||||
`toJSON(err)` returns a plain object with `__suaveplanError: 1`, ready for JSON-safe transport. `fromJSON(value)` validates and reconstructs the payload. `toBinary` / `fromBinary` exchange the same content as a UTF-8 byte array.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
bunx turbo lint typecheck test --filter=@suaveplan/error
|
||||
bunx turbo test:coverage --filter=@suaveplan/error
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user