Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
# serialization
## Purpose
Round-trip-preserving structured serialization for the Suaveplan monorepo — tagged JSON (Date, Map, Set, BigInt, Uint8Array, URL, RegExp, custom tags), MessagePack binary profile, streaming encode/decode via Web Streams, and a pluggable type registry. Eval-safe by default with the `serialize-javascript` adapter isolated to the opt-in `/unsafe` subpath; all errors flow through `SerializationError` codes registered under the `SERIALIZE.*` namespace.
## Requirements
### SZ-01 — Eval-safe by default
The main export (`@suaveplan/serialize`) MUST NEVER execute arbitrary code during parse. All reconstruction happens via the type registry's `decode` functions. The `serialize-javascript` adapter is isolated to the `@suaveplan/serialize/unsafe` subpath and MUST NOT appear in the main bundle (enforced by tree-shake test).
### SZ-02 — Round-trip fidelity for built-in types
`serialize → deserialize` MUST produce a deep-equal value for all built-in types: `Date`, `Map`, `Set`, `BigInt`, `Uint8Array`, `Int8Array`, `Int16Array`, `Int32Array`, `Uint16Array`, `Uint32Array`, `Float32Array`, `Float64Array`, `URL`, `RegExp`. Plain objects, arrays, `null`, `undefined`, `string`, `number`, `boolean` MUST also round-trip. `NaN` and `Infinity` MUST be tagged (JSON `null` fallback is not acceptable).
### SZ-03 — Tagged JSON format
The serialized JSON format MUST use a `{ "__t": "<tag>", "v": <encoded> }` envelope for non-primitive types. Tags are short stable strings registered in the type registry. The format MUST be human-readable and diff-friendly.
### SZ-04 — Cycle detection
Any value containing a circular reference MUST throw `CircularReferenceError` (code `SERIALIZE.CODEC.CIRCULAR_REFERENCE`) before any output is produced. Detection uses a `WeakSet` and is depth-bounded to `maxDepth` (default: 100).
### SZ-05 — Type registry
`registerType(def)` MUST be idempotent for the same tag+ctor pair and MUST throw `SerializationError` (code `SERIALIZE.REGISTRY.DUPLICATE_TAG`) if the same tag is registered for a different constructor.
### SZ-06 — MessagePack profile
`encodeBinary → decodeBinary` MUST produce bit-identical output for identical inputs (field ordering canonicalised via sorted keys). Custom tags MUST be encoded as MessagePack extension types.
### SZ-07 — Streaming
`encodeStream` MUST chunk output into frames compatible with `decodeStream`. The Web Streams `ReadableStream` API is used (no Node.js stream dependency). Both MUST honour `AbortSignal`.
### SZ-08 — Unsafe subpath isolation
The `@suaveplan/serialize/unsafe` subpath MUST be a separate entry point. Any code importing only `@suaveplan/serialize` (main) MUST NOT have `serialize-javascript` in its bundle. This is verified by an automated tree-shake test.
### SZ-09 — Structured errors
All thrown errors MUST extend `SerializationError` which extends `SuaveplanError`. Subclasses: `CircularReferenceError`, `MaxDepthExceededError`, `MaxSizeExceededError`, `UnsupportedTypeError`. Codes under `SERIALIZE.*` namespace.
### SZ-10 — Zod schemas for options
`SerializeOptions` and `DeserializeOptions` MUST have corresponding Zod schemas. Inputs are validated at the public boundary (invalid options throw `SerializationError` with context).
### SZ-11 — OTel instrumentation
`serialize.payload_bytes` histogram (by format label) and `serialize.error.total` counter (by code label) MUST be emitted via `@opentelemetry/api`. No-ops without exporter.
### SZ-12 — sideEffects: false + coverage 100%
`"sideEffects": false`. Tree-shake test. Vitest thresholds at 100/100/100/100. No `.skip` / `.only` in `src/`.