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,76 @@
# errors
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Defines the structured error surface for `@suaveplan/cache-storage`. Every failure path inside the package — corrupt blob layouts, codec decode failures, oversized keys or values, propagated backend faults — is reported by throwing a `StorageCacheError` carrying one of the codes registered in `CACHE_STORAGE_CODES`. Consumers programmatically branch on `error.code` (a discriminated union literal like `"CACHE_STORAGE.CODEC_ERROR"`) instead of pattern-matching free-form message strings. The optional `key` discriminant identifies the cache key that produced the failure when one is known.
## Features
- 5-code registry built with `defineCodes("CACHE_STORAGE", [...])` so codes serialise identically across the OpenTelemetry span pipeline, the wire-format error envelope, and the i18n resolver.
- `StorageCacheError` extends `SuaveplanError<CacheStorageCode>` for cause-chain traversal and structured `traceId` / `context` propagation.
- Optional `key` discriminant carried on every instance — present on every code that originates at a key boundary (read, write, delete, validate).
- Every code is exercised by `errors.test.ts` against a real call site, satisfying the §13 step 0 reachability gate.
## Usage: Basic Example
```ts
import {
CACHE_STORAGE_CODES,
StorageCacheError,
} from "@suaveplan/cache-storage/errors";
try {
await cache.get("k");
} catch (err) {
if (
err instanceof StorageCacheError &&
err.code === CACHE_STORAGE_CODES.ENTRY_CORRUPT
) {
log.warn("Corrupted cache entry — deleting", { key: err.key });
}
}
```
## Usage: Advanced Example
```ts
import {
CACHE_STORAGE_CODES,
StorageCacheError,
} from "@suaveplan/cache-storage/errors";
function classify(err: unknown): "retry" | "fatal" | "ignore" {
if (!(err instanceof StorageCacheError)) return "fatal";
switch (err.code) {
case CACHE_STORAGE_CODES.BACKEND_ERROR:
return "retry";
case CACHE_STORAGE_CODES.ENTRY_CORRUPT:
case CACHE_STORAGE_CODES.CODEC_ERROR:
return "ignore"; // cache miss is safe
case CACHE_STORAGE_CODES.KEY_TOO_LONG:
case CACHE_STORAGE_CODES.VALUE_TOO_LARGE:
return "fatal";
default:
return "fatal";
}
}
```
## API Reference
| Export | Kind | Purpose |
| --- | --- | --- |
| `CACHE_STORAGE_CODES` | const | Frozen object mapping reason → `"CACHE_STORAGE.<REASON>"` value. |
| `CacheStorageCode` | type | Union of the registered code values. |
| `StorageCacheError` | class | `extends SuaveplanError<CacheStorageCode>`; constructor accepts `(code, messageKey, options?)` where options may include `key`, `cause`, `context`, `traceId`. |
| `StorageCacheErrorOptions` | type | `SuaveplanErrorOptions & { key?: string }`. |
Registered codes: `ENTRY_CORRUPT`, `CODEC_ERROR`, `BACKEND_ERROR`, `KEY_TOO_LONG`, `VALUE_TOO_LARGE`.
## Implementation Notes
Codes are intentionally minimal — five is enough to cover every failure mode `StorageCache` can produce. `BACKEND_ERROR` is the only code that wraps a foreign exception (the underlying `AbstractStorage.get` / `set`); the others originate inside the package and have well-defined call sites. Decode failures from the codec always surface as `CODEC_ERROR` even when the codec implementation throws something else — `StorageCache.#decodeBody` adapts arbitrary throwables into the canonical form.