4.4 KiB
registry
(no submodules)
Purpose
Maintains a global singleton map of type definitions that the JSON and MessagePack codecs consult to encode and decode non-primitive JavaScript values in a round-trip-safe way. Each entry maps a string tag to an encoder/decoder pair and a constructor reference, enabling both forward lookup (value → tag) and reverse lookup (tag → value reconstruction).
The registry ships with 17 built-in entries covering the types most commonly lost by JSON.stringify: Date, Map, Set, BigInt, the six TypedArray variants, URL, RegExp, and three special sentinel tags for undefined, NaN, and ±Infinity.
Features
registerType(def)— add a custom type; throwsSERIALIZE.REGISTRY.DUPLICATE_TAGon tag collision with a different constructor; idempotent for identical re-registrationsunregisterType(tag)— remove by tag; silent if absent (useful for test cleanup)listTypes()— enumerate all current entries as an array ofTypeDefinitiongetType(tag)— look up by tag string; returnsundefinedif absentgetTypeByCtor(ctor)— look up by constructor; returnsundefinedif absent- 14 built-in type definitions registered at module load time
- Three special sentinel definitions for
undefined,NaN, and±Infinity
Usage: Basic Example
import { registerType, unregisterType } from "@suaveplan/serialize";
class Color {
constructor(public hex: string) {}
}
registerType({
tag: "__Color",
ctor: Color,
encode: (v) => (v as Color).hex,
decode: (enc) => new Color(enc as string),
});
// After registration, serialize/deserialize will handle Color instances.
// Clean up in tests:
unregisterType("__Color");
Usage: Advanced Example
import {
getType,
getTypeByCtor,
listTypes,
registerType,
} from "@suaveplan/serialize";
class Vector2 {
constructor(public x: number, public y: number) {}
}
registerType({
tag: "__Vector2",
ctor: Vector2,
encode: (v) => { const vec = v as Vector2; return [vec.x, vec.y]; },
decode: (enc) => { const [x, y] = enc as [number, number]; return new Vector2(x, y); },
});
// Look up by tag
const def = getType("__Vector2");
console.log(def?.tag); // "__Vector2"
// Look up by ctor
const def2 = getTypeByCtor(Vector2);
console.log(def2?.tag); // "__Vector2"
// Enumerate all registered types
const all = listTypes();
console.log(all.map((d) => d.tag));
API Reference
registerType(def: TypeDefinition): void
Registers a custom type. Throws SerializationError with code SERIALIZE.REGISTRY.DUPLICATE_TAG if the same tag string is already registered for a different constructor. Registering the same tag+ctor pair again is a silent no-op (idempotent).
unregisterType(tag: string): void
Removes the registration for tag and its associated constructor from both internal maps. Silent if the tag was never registered.
listTypes(): TypeDefinition[]
Returns a snapshot array of all registered TypeDefinition objects at the time of the call.
getType(tag: string): TypeDefinition | undefined
Returns the TypeDefinition for the given tag, or undefined if no entry exists.
getTypeByCtor(ctor: Function): TypeDefinition | undefined
Returns the TypeDefinition whose ctor reference matches, or undefined if none is registered for that constructor.
TypeDefinition
interface TypeDefinition {
tag: string;
ctor: Function;
encode: (value: unknown) => unknown;
decode: (encoded: unknown) => unknown;
}
Implementation Notes
- Two parallel
Mapinstances (_byTagand_byCtor) are kept in sync to give O(1) lookup in both directions without requiring full list iteration. - Built-in registrations use an internal
registerBuiltinhelper that force-sets both maps, making them immune to the duplicate-tag guard that external callers hit. This allows the module to be loaded multiple times in test environments without throwing. - The sentinel entries for
undefined,NaN, and±Infinityuse placeholder constructors (Object,Number,Boolean) that will never match a real value viagetTypeByCtor; they are only reached via thegetType(tag)path during deserialization. - TypedArray
Float32ArrayandFloat64Arrayencode to plain number arrays; precision loss forFloat32Arrayis intentional and matches the original in-memory representation.