# Transform Stream Schemas ## Purpose Zod schemas for the option bundles consumed by `createPackTransformStream`, `createUnpackTransformStream`, and the framing helpers (`addFrame`, `parseFrames`, `createFramedPackStream`, `createFramedUnpackStream`). Each schema is the runtime gatekeeper at the corresponding boundary — `framingConfigSchema` validates the frame-strategy descriptor, and `packTransformOptionsSchema` / `unpackTransformOptionsSchema` validate the per-call tuning bundles. The framing schema deliberately does NOT enforce cross-field requirements (e.g. "if `type === 'length-prefix'` then `lengthPrefixSize` is required"). The runtime parser tolerates the extra fields, and forcing the cross-field check at parse time would force callers to always specify `lengthPrefixSize: 4` even when defaulting it. Strict-mode rejects unknown keys; the runtime parser is the authority on which combinations make sense. ## Features - `framingConfigSchema` — discriminated by `type` (`length-prefix` / `delimiter` / `fixed-size` / `none`) - `packTransformOptionsSchema` — `batchSize`, `highWaterMark`, `onProgress` - `unpackTransformOptionsSchema` — `highWaterMark`, `onProgress`, `headerSize` - Identity-preserving `z.custom` for `onProgress` - `Uint8Array` instance check for `delimiter` (rejects array-of-numbers literals) - `as unknown as z.ZodType` casts for EOPT mismatches ## Usage: Basic Example ```ts import { framingConfigSchema, packTransformOptionsSchema, } from "@suaveplan/bitpacker-streaming"; const framing = framingConfigSchema.parse({ type: "length-prefix", lengthPrefixSize: 4, }); const packOpts = packTransformOptionsSchema.parse({ batchSize: 4, highWaterMark: 16, onProgress: (p) => console.log(p), }); ``` ## Usage: Advanced Example ```ts import { addFrame, framingConfigSchema, parseFrames, unpackTransformOptionsSchema, } from "@suaveplan/bitpacker-streaming"; // Validate framing at the boundary, then trust the parsed shape downstream: function withFraming(rawFraming: unknown, payload: Uint8Array) { const cfg = framingConfigSchema.parse(rawFraming); return addFrame(payload, cfg); } // Per-call unpack options, including a length-prefix header width: const unpackOpts = unpackTransformOptionsSchema.parse({ highWaterMark: 32, headerSize: 4, }); ``` ## API Reference ### `framingConfigSchema: z.ZodType` Strict schema for the `FramingConfig` discriminator. `type` is one of four literal tokens. `lengthPrefixSize` is restricted to `1 | 2 | 4`. `delimiter` must be a `Uint8Array` (not a `number[]` literal). `fixedSize` is a positive integer. ### `packTransformOptionsSchema: z.ZodType` Strict schema. `batchSize` and `highWaterMark` are positive integers. `onProgress` is a function preserved by identity. ### `unpackTransformOptionsSchema: z.ZodType` Strict schema. `highWaterMark` and `headerSize` are positive integers. `onProgress` is a function preserved by identity. ## Implementation Notes - **No cross-field validation.** A `length-prefix` framing without `lengthPrefixSize` is technically incomplete, but the runtime parser defaults it to `4` and tolerates the omission. Forcing a cross-field rule at parse time would over-constrain callers. - **`Uint8Array` instance check on `delimiter`.** A `[0x0a]` literal looks like a delimiter but does not implement the typed-array surface the parser uses (`.subarray`, `.byteLength`). Refusing it at parse time prevents a silent type coercion that would surface as an obscure runtime error. - **`as unknown as` casts.** Same EOPT mismatch as elsewhere in this change. Runtime semantics are identical.