first commit
This commit is contained in:
65
docs/persistence/storage/storage-file/src/error-codes.md
Normal file
65
docs/persistence/storage/storage-file/src/error-codes.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# `error-codes`
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the frozen `STORAGE_FILE_CODES` registry and the `StorageFileError` class used by every public path in `@suaveplan/storage-file`. The registry is the contract: every code is intentionally thrown from at least one production path, and downstream consumers assert on `error.code` rather than parsing message text. The class extends `@suaveplan/error.SuaveplanError` so it integrates with the OTel span-event adapter and the error-envelope wire format.
|
||||
|
||||
## Features
|
||||
|
||||
- 8 frozen codes covering missing keys, permissions, IO failures, invalid input, atomic-write rollback, option validation, abort, and key length overrun.
|
||||
- `StorageFileErrorCode` union type derived from the registry — exhaustive `switch` statements get compile-time enforcement.
|
||||
- `StorageFileError` carries an optional `key` discriminant so callers can correlate a failure with the offending key without parsing strings.
|
||||
- All codes are namespaced `STORAGE_FILE.*` for unambiguous registry filtering in centralised error reporters.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { StorageFileError, STORAGE_FILE_CODES } from "@suaveplan/storage-file";
|
||||
|
||||
try {
|
||||
await storage.get("../../etc/passwd");
|
||||
} catch (err) {
|
||||
if (err instanceof StorageFileError && err.code === STORAGE_FILE_CODES.INVALID_KEY) {
|
||||
// caller-friendly message
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { StorageFileError, STORAGE_FILE_CODES, type StorageFileErrorCode } from "@suaveplan/storage-file";
|
||||
|
||||
function classify(code: StorageFileErrorCode): "client" | "server" {
|
||||
switch (code) {
|
||||
case STORAGE_FILE_CODES.INVALID_KEY:
|
||||
case STORAGE_FILE_CODES.KEY_TOO_LONG:
|
||||
case STORAGE_FILE_CODES.INVALID_OPTIONS:
|
||||
return "client";
|
||||
case STORAGE_FILE_CODES.NOT_FOUND:
|
||||
case STORAGE_FILE_CODES.PERMISSION_DENIED:
|
||||
case STORAGE_FILE_CODES.IO_FAILED:
|
||||
case STORAGE_FILE_CODES.ATOMIC_WRITE_FAILED:
|
||||
case STORAGE_FILE_CODES.ABORTED:
|
||||
return "server";
|
||||
}
|
||||
}
|
||||
|
||||
throw new StorageFileError(STORAGE_FILE_CODES.NOT_FOUND, "no such key", {
|
||||
key: "/orders/42.json",
|
||||
cause: undefined,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `STORAGE_FILE_CODES` — frozen object map of code names to fully-qualified strings (`STORAGE_FILE.NOT_FOUND`, etc.). Exhaustive: 8 codes.
|
||||
- `StorageFileErrorCode` — union derived from `(typeof STORAGE_FILE_CODES)[keyof typeof STORAGE_FILE_CODES]`.
|
||||
- `StorageFileError` — class extending `SuaveplanError<StorageFileErrorCode>`. Constructor: `(code, message, options?)`. Properties: inherited `code`, inherited `cause`, additional `key?: string`.
|
||||
- `StorageFileErrorOptions` — extends `SuaveplanErrorOptions` with optional `key`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Codes are registered by `defineCodes("STORAGE_FILE", [...])`. The registration is idempotent: importing this module multiple times does not re-register or throw.
|
||||
- The list is closed by design — adding a new failure mode requires an spec change so consumers can update their handlers in lockstep.
|
||||
- `name` is set to `"StorageFileError"` so `instanceof` and `error.name` checks both work.
|
||||
Reference in New Issue
Block a user