first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# `payload-codec`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Encodes and decodes the wire envelope used to ship a single event from the main-process `EventBus` across a `MessagePort` to a worker-tier subscriber. Includes a depth-bounded structured-clone safety probe so payloads that cannot survive the transfer are rejected at the source rather than producing opaque `DataCloneError` exceptions at runtime.
The codec is intentionally conservative: anything beyond plain JSON-shaped data plus a small list of well-known cloneable host types (`Date`, `RegExp`, `Map`, `Set`, `ArrayBuffer`, typed arrays) is rejected with `EVENTS_PROXY.UNSERIALISABLE_PAYLOAD`. This matches the structured-clone algorithm but is checked synchronously and surfaces the offending path.
## Features
- `EventEnvelopeSchema` Zod schema for the wire frame (`{ topic, payload, traceId? }`).
- `encodeEnvelope(topic, payload, traceId?)` runs the probe, then constructs the envelope. Throws an `EventsProxyError` carrying the offending path on rejection.
- `decodeEnvelope(raw)` Zod-validates an inbound frame.
- `probeStructuredClone(value)` returns the offending path or `null`. Detects functions, symbols, `WeakMap`/`WeakSet`, class instances, cycles, and over-deep graphs (limit `MAX_PROBE_DEPTH = 64`).
- `DEFAULT_BACKPRESSURE_HIGH_WATER = 1024` — the default per-subscription queue cap.
## Usage: Basic
```ts
import {
encodeEnvelope,
decodeEnvelope,
} from "@suaveplan/api-events-worker-proxy/payload-codec";
const wire = encodeEnvelope("billing.invoice.created", { invoiceId: "i_1" });
const decoded = decodeEnvelope(wire);
console.log(decoded.topic, decoded.payload);
```
## Usage: Advanced
```ts
import {
probeStructuredClone,
encodeEnvelope,
} from "@suaveplan/api-events-worker-proxy/payload-codec";
import {
EventsProxyError,
EVENTS_PROXY_CODES,
} from "@suaveplan/api-events-worker-proxy/error-codes";
const payload = {
invoiceId: "i_1",
whenIssued: new Date(),
handler: () => undefined,
};
const offender = probeStructuredClone(payload);
if (offender !== null) {
throw new EventsProxyError(
EVENTS_PROXY_CODES.UNSERIALISABLE_PAYLOAD,
`payload rejected at ${offender}`
);
}
const wire = encodeEnvelope("invoice.flagged", payload);
```
## API Reference
- `EventEnvelopeSchema` — `z.object({ topic: z.string().min(1), traceId: z.string().optional(), payload: z.unknown() })`.
- `WireEventEnvelope` — `z.infer<typeof EventEnvelopeSchema>`.
- `encodeEnvelope(topic: string, payload: unknown, traceId?: string): WireEventEnvelope`.
- `decodeEnvelope(raw: unknown): WireEventEnvelope`.
- `probeStructuredClone(value: unknown): string | null` — returns the offending JSON-path-like string or `null`.
- `MAX_PROBE_DEPTH: number` — `64`.
- `DEFAULT_BACKPRESSURE_HIGH_WATER: number` — `1024`.
## Implementation Notes
The probe walks the object graph synchronously with a `WeakSet` cycle detector, accumulating the offending JSON path. It deliberately rejects class instances (`Object.getPrototypeOf(value) !== Object.prototype`) because the receiving side reconstructs them as plain objects, breaking `instanceof`. `Date`, `RegExp`, `Map`, `Set`, `ArrayBuffer`, and `ArrayBuffer.isView`-typed values are recognised explicitly because they ARE structured-clone safe even though they have non-`Object` prototypes. The depth bound of 64 is generous for legitimate payloads but cuts off pathological inputs. Cycles are detected by `WeakSet`; the probe reports the path that re-entered the visited set rather than recursing infinitely.