Files
skills/docs/networking/events/event-sourcing/src/upcasting/upcaster/upcaster.md
2026-05-29 08:20:56 +01:00

2.5 KiB

upcaster

(no submodules)

Purpose

Provides event schema migration via a registry-based upcaster pattern. When an aggregate's event payloads evolve over time, old events stored in the event store can be transparently migrated to newer schemas on load. Each upcaster migrates from one payload version to the next, forming a chain that upcastEvents walks automatically.

Features

  • registerUpcaster(options) — adds a migration function for eventType at fromVersion → toVersion
  • upcastEvents(events, options?) — walks the upcaster chain for each event, applying all registered migrations
  • clearUpcasters() — resets the registry (for test isolation)
  • requireComplete option — throws UPCASTER_MISSING if the chain does not terminate for an event type
  • Chain limit of 100 steps prevents infinite loops from misconfigured upcasters

Usage: Basic Example

import { registerUpcaster, upcastEvents } from "@suaveplan/event-sourcing";

registerUpcaster({
  eventType: "OrderPlaced",
  fromVersion: 1,
  toVersion: 2,
  upcast: (payload) => ({
    ...(payload as object),
    currency: "USD", // added in v2
  }),
});

const migrated = upcastEvents(oldEvents);

Usage: Advanced Example

import { registerUpcaster, upcastEvents, clearUpcasters } from "@suaveplan/event-sourcing";

// Chain: v1 -> v2 -> v3
registerUpcaster({ eventType: "OrderPlaced", fromVersion: 1, toVersion: 2, upcast: addCurrency });
registerUpcaster({ eventType: "OrderPlaced", fromVersion: 2, toVersion: 3, upcast: addTaxId });

const events = await store.load("order-1");
const migrated = upcastEvents(events);

// In tests: clean up
clearUpcasters();

API Reference

registerUpcaster(options: UpcasterOptions)

Registers options.upcast to migrate payloads from options.fromVersion to options.toVersion for options.eventType.

upcastEvents(events, options?)

  • options.requireComplete — if true, throws UPCASTER_MISSING when chain has gaps
  • Returns a new array of events with migrated payloads (original events are not mutated)

clearUpcasters()

Resets the global registry. Use in afterEach during tests.

Implementation Notes

The upcaster registry is module-level (global singleton). This matches the typical pattern for event schema registries. The 100-step chain limit prevents runaway loops while supporting realistic migration depths. The requireComplete check is a best-effort safeguard and does not guarantee the upcaster graph has no cycles.