Initial Commit
This commit is contained in:
151
packages/foundation/data/serialize/src/errors/serialize-error.md
Normal file
151
packages/foundation/data/serialize/src/errors/serialize-error.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# serialize-error
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the error hierarchy for `@suaveplan/serialize`. All errors thrown by this package extend `SerializationError`, which in turn extends `SuaveplanError` from `@suaveplan/error`. This design ensures every thrown error carries a stable, machine-readable code string (`SERIALIZE.*`) so callers can programmatically distinguish between circular references, depth overflows, size overflows, and unknown type tags without parsing human-readable messages.
|
||||
|
||||
The contextual payload (`SerializationErrorContext`) transports structural metadata — tag names, recursion depths, byte sizes, and dot-path strings — that would otherwise require expensive re-traversal to reconstruct after the fact.
|
||||
|
||||
## Features
|
||||
|
||||
- `SerializationError` — base class; extends `SuaveplanError<SerializationErrorCode>` with an optional `SerializationErrorContext`
|
||||
- `CircularReferenceError` — emitted when a cycle is detected in the input object graph; includes the dot-path where the cycle was encountered
|
||||
- `MaxDepthExceededError` — emitted when recursion depth exceeds the caller-configured `maxDepth`; includes the depth value
|
||||
- `MaxSizeExceededError` — emitted when the serialized byte count exceeds `maxSize`; includes the approximate size in bytes
|
||||
- `UnsupportedTypeError` — emitted during deserialization when a `__t` tag has no registered decoder; includes the unknown tag string
|
||||
- Exported `SerializationErrorCode` union type for exhaustive `switch` narrowing
|
||||
- Re-exported `SERIALIZE_CODES` constant map for use in tests and error construction
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```typescript
|
||||
import {
|
||||
CircularReferenceError,
|
||||
MaxDepthExceededError,
|
||||
SerializationError,
|
||||
} from "@suaveplan/serialize";
|
||||
|
||||
try {
|
||||
// serialization call here
|
||||
} catch (err) {
|
||||
if (err instanceof CircularReferenceError) {
|
||||
console.error("Cycle at", err.context?.path);
|
||||
} else if (err instanceof SerializationError) {
|
||||
console.error("Serialization failed:", err.code);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```typescript
|
||||
import {
|
||||
SERIALIZE_CODES,
|
||||
SerializationError,
|
||||
UnsupportedTypeError,
|
||||
type SerializationErrorCode,
|
||||
} from "@suaveplan/serialize";
|
||||
|
||||
function handleSerializeError(err: unknown): never {
|
||||
if (!(err instanceof SerializationError)) throw err;
|
||||
|
||||
const code: SerializationErrorCode = err.code;
|
||||
switch (code) {
|
||||
case SERIALIZE_CODES["CODEC.CIRCULAR_REFERENCE"]:
|
||||
throw new Error(`Cycle at path: ${err.context?.path ?? "unknown"}`);
|
||||
case SERIALIZE_CODES["CODEC.MAX_DEPTH"]:
|
||||
throw new Error(`Too deep: ${err.context?.depth}`);
|
||||
case SERIALIZE_CODES["CODEC.MAX_SIZE"]:
|
||||
throw new Error(`Too large: ${err.context?.size} bytes`);
|
||||
case SERIALIZE_CODES["CODEC.UNKNOWN_TAG"]:
|
||||
throw new Error(`No decoder for tag: ${err.context?.tag}`);
|
||||
default:
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// UnsupportedTypeError carries the unknown tag
|
||||
const e = new UnsupportedTypeError("__MyCustomClass");
|
||||
console.log(e.context?.tag); // "__MyCustomClass"
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `SerializationError`
|
||||
|
||||
```typescript
|
||||
class SerializationError extends SuaveplanError<SerializationErrorCode> {
|
||||
constructor(
|
||||
code: SerializationErrorCode,
|
||||
messageKey: string,
|
||||
options?: SerializationErrorOptions,
|
||||
): void
|
||||
}
|
||||
```
|
||||
|
||||
- `code` — one of the `SERIALIZE.*` codes
|
||||
- `messageKey` — i18n key resolved via `@suaveplan/error` resolver
|
||||
- `options.cause` — underlying error, chained via `Error.cause`
|
||||
- `options.context` — `SerializationErrorContext` metadata
|
||||
|
||||
### `CircularReferenceError`
|
||||
|
||||
```typescript
|
||||
new CircularReferenceError(path?: string, cause?: unknown)
|
||||
```
|
||||
|
||||
Code: `SERIALIZE.CODEC.CIRCULAR_REFERENCE`. `context.path` is the dot-path string where the cycle was detected.
|
||||
|
||||
### `MaxDepthExceededError`
|
||||
|
||||
```typescript
|
||||
new MaxDepthExceededError(depth: number, cause?: unknown)
|
||||
```
|
||||
|
||||
Code: `SERIALIZE.CODEC.MAX_DEPTH`. `context.depth` is the depth value at which encoding was aborted.
|
||||
|
||||
### `MaxSizeExceededError`
|
||||
|
||||
```typescript
|
||||
new MaxSizeExceededError(size: number, cause?: unknown)
|
||||
```
|
||||
|
||||
Code: `SERIALIZE.CODEC.MAX_SIZE`. `context.size` is the approximate byte count.
|
||||
|
||||
### `UnsupportedTypeError`
|
||||
|
||||
```typescript
|
||||
new UnsupportedTypeError(tag: string, cause?: unknown)
|
||||
```
|
||||
|
||||
Code: `SERIALIZE.CODEC.UNKNOWN_TAG`. `context.tag` is the unrecognised tag string.
|
||||
|
||||
### `SerializationErrorContext`
|
||||
|
||||
```typescript
|
||||
interface SerializationErrorContext {
|
||||
tag?: string;
|
||||
depth?: number;
|
||||
size?: number;
|
||||
path?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### `SerializationErrorOptions`
|
||||
|
||||
```typescript
|
||||
interface SerializationErrorOptions {
|
||||
cause?: unknown;
|
||||
context?: SerializationErrorContext;
|
||||
}
|
||||
```
|
||||
|
||||
### `SerializationErrorCode`
|
||||
|
||||
Union type of all `SERIALIZE.*` code strings; use with exhaustive `switch` statements.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- `SerializationError` maps `SerializationErrorOptions.context` to the generic `Record<string, unknown>` shape expected by `SuaveplanErrorOptions` without widening the exported interface — callers always get the narrow `SerializationErrorContext` type.
|
||||
- Each subclass uses a specific constructor signature (only the meaningful fields, not the full code/key/options triple) to make throw sites readable and to prevent code/message mismatches.
|
||||
- The `SERIALIZE_CODES` constant is defined in a separate `codes.ts` module and re-exported from here so that the error file is self-contained for consumers who only import errors.
|
||||
Reference in New Issue
Block a user