Files
2026-05-27 23:47:53 +01:00

5.2 KiB

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

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

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

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

new CircularReferenceError(path?: string, cause?: unknown)

Code: SERIALIZE.CODEC.CIRCULAR_REFERENCE. context.path is the dot-path string where the cycle was detected.

MaxDepthExceededError

new MaxDepthExceededError(depth: number, cause?: unknown)

Code: SERIALIZE.CODEC.MAX_DEPTH. context.depth is the depth value at which encoding was aborted.

MaxSizeExceededError

new MaxSizeExceededError(size: number, cause?: unknown)

Code: SERIALIZE.CODEC.MAX_SIZE. context.size is the approximate byte count.

UnsupportedTypeError

new UnsupportedTypeError(tag: string, cause?: unknown)

Code: SERIALIZE.CODEC.UNKNOWN_TAG. context.tag is the unrecognised tag string.

SerializationErrorContext

interface SerializationErrorContext {
  tag?: string;
  depth?: number;
  size?: number;
  path?: string;
}

SerializationErrorOptions

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.