6.4 KiB
Capability Spec Delta: bitpacker-streaming (bitpacker-stub-completion)
Package: @suaveplan/bitpacker-streaming
Status: PROPOSED
Every requirement below carries a
**Verified by:**line at authoring time.
ADDED Requirements
Requirement: StreamingBitPacker class
The package SHALL export StreamingBitPacker<T extends BitPackerSchema> extends EventEmitter matching upstream streaming.ts (L14-L406). The class SHALL expose packStream(data, options) and unpackStream(packed, options), both returning Promise<Uint8Array> (pack) / Promise<SchemaTypeToDataType<T>> (unpack). Both methods SHALL emit progress events as chunks complete and chunk events with the bytes of each completed chunk; chunk size SHALL come from options.chunkSize (default 1024).
Scenario: packStream round-trips through unpackStream
- WHEN a 100 KiB object is
packStream-ed and the result isunpackStream-ed under the same schema - THEN the unpacked value deep-equals the input
Scenario: progress events fire in chunk order
- WHEN
packStreamis called on data that produces 8 chunks - THEN 8
progressevents fire with{ index, total: 8, percent }in monotonically increasing order; the final event haspercent === 1
Scenario: chunk events carry chunk bytes
- WHEN
packStreamruns withemitProgress: true - THEN each
chunkevent's payload is aUint8Arraywhose concatenation equals the final return value byte-for-byte
Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"packStream / unpackStream round-trip preserves the value" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"emits progress events in monotonic chunk order" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"chunk events concatenate to the final byte output"
Requirement: chunkProcessor invoked per chunk
If options.chunkProcessor is supplied, the streaming bit-packer SHALL invoke it on each chunk before emitting / returning, awaiting the result. If the processor throws, packStream / unpackStream SHALL throw BitpackerError with code BITPACKER.STREAM_CHUNK_PROCESSOR_FAILED, chaining the original error.
Scenario: chunkProcessor mutates chunks before delivery
- WHEN
chunkProcessoris(chunk) => xor(chunk, 0xff)and the produced bytes are XOR'd back before unpack - THEN the round-trip succeeds
Scenario: chunkProcessor failure surfaces as coded error
- WHEN
chunkProcessorthrows on chunk 3 - THEN
packStreamrejects withBitpackerErrorcodeBITPACKER.STREAM_CHUNK_PROCESSOR_FAILEDwhosecauseis the original error andcontext.chunkIndex === 3
Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"chunkProcessor mutates chunks before delivery" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"chunkProcessor failure surfaces as STREAM_CHUNK_PROCESSOR_FAILED"
Requirement: validateChunks gates pack/unpack on validation
When options.validateChunks is true, the streaming bit-packer SHALL run the underlying BitPacker.validate over the input (pack) or unpacked output (unpack) and reject before emitting if validation fails, throwing BitpackerError with code BITPACKER.STREAM_VALIDATION_FAILED.
Scenario: validation gate rejects malformed input
- WHEN
validateChunks: trueand the input violates the schema (e.g. value out ofu8range) - THEN
packStreamrejects withBitpackerErrorcodeBITPACKER.STREAM_VALIDATION_FAILEDAND nochunkevents fire
Scenario: validation gate disabled by default
- WHEN
validateChunksis omitted - THEN packing proceeds without validation; encoder errors surface natively
Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"validateChunks: true rejects malformed input with STREAM_VALIDATION_FAILED" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.spec-conformance.test.ts::"validateChunks default is false"
Requirement: AbortSignal propagation
packStream and unpackStream SHALL accept options.signal: AbortSignal. When the signal is already aborted at call time, the call SHALL reject immediately with BitpackerError code BITPACKER.STREAM_ABORTED. When abort fires mid-stream, the in-flight chunk SHALL complete and then the call SHALL reject with the same code; no subsequent chunks SHALL be processed or emitted.
Scenario: pre-aborted signal rejects immediately
- WHEN
signal.aborted === trueat call time - THEN
packStreamrejects synchronously withBitpackerErrorcodeBITPACKER.STREAM_ABORTED
Scenario: mid-stream abort halts further chunks
- WHEN
abort()fires after the 2nd of 8 chunks completes - THEN chunks 3..8 do NOT emit
chunkevents and the promise rejects withBITPACKER.STREAM_ABORTED
Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"pre-aborted signal rejects immediately with STREAM_ABORTED" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"mid-stream abort halts further chunk emission"
MODIFIED Requirements
Requirement: Synchronous chunked helpers delegate to StreamingBitPacker
The existing packToChunks, unpackFromChunks, and unpackFromChunksAsync functions SHALL be preserved with their current signatures, but their implementation SHALL delegate to StreamingBitPacker so behavior stays synchronized. The async helper SHALL honour AbortSignal (already true today; pin behavior in test).
Scenario: packToChunks output equals StreamingBitPacker.packStream concatenation
- WHEN the same data + schema is run through
packToChunksand throughpackStreamand the chunks of each are concatenated - THEN the byte-arrays are equal
Verified by: packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"packToChunks delegates to packStream" AND packages/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.test.ts::"unpackFromChunksAsync honours AbortSignal"