Skip to content

Message type generator: restore Dates and nested class instances without decorators #294

Closed

Description

@adenhertog

JsonSerializer loses runtime types: Dates arrive as strings and nested objects as plain objects. The current answer, bus-class-serializer, relies on class-transformer (unmaintained since 2021), needs legacy experimentalDecorators/emitDecoratorMetadata (not emitted by esbuild, tsx, Vite or TC39 decorators), a global reflect-metadata polyfill, calls constructors with no args, and fails silently on a forgotten @Type. Schema-first libraries were ruled out because messages should stay plain TypeScript.

Proposal

  • A bus generate-message-types command (shares the CLI package with CLI: apply and prune transport topology (queues, topics, subscriptions) #283 and Project scaffolding: npm create bus-app templates #269) reads the message library's source with the TypeScript compiler API, read-only like tsc --noEmit, and emits a plain .ts file (e.g. src/message-types.generated.ts) mapping each $name to the runtime type of every nested path: Date, Map, Set, BigInt, nested classes, arrays, optionals. No transformer or bundler plugin, so it compiles with any toolchain.
  • The default serializer uses the map to revive Dates and class instances at any depth. Without a map it still restores the top-level class from $name.
  • Unsupported types (functions, unresolvable types) fail generation; --check for CI; bus startup throws if a handled message has no map entry.
  • Plain-data messages (ISO date strings) stay the documented zero-setup option, and the path for plain JS projects.
  • Deprecate and remove bus-class-serializer, dropping reflect-metadata and class-transformer from the ecosystem. Breaking, so ship as minor with a Breaking: note and a MIGRATING.md entry.

Scope

  • Generator command plus --check
  • Revival map format and serializer support (nested, arrays, optionals, Map, Set, BigInt)
  • Startup validation for messages missing from the map
  • Tests, including a round-trip conformance case in bus-test (replacing the ClassSerializer round-trip test from build bus-test to dist and fix its dependency types #292)
  • Docs: messages guide, plain-data guidance, migration from bus-class-serializer
  • Remove bus-class-serializer and its reflect-metadata/class-transformer deps everywhere

Known limits, to be documented: revived objects are created from the prototype without running constructors, and #private fields aren't restored.

Related: #283, #269, #263.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestroadmapPart of the project roadmap

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions