first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# `schemas/frame.schemas`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Zod boundary schemas for the two structured payload shapes the WebRTC
|
||||
drive transport speaks on the wire: chunk-request and advertisement.
|
||||
Frames themselves are length-prefixed binary blobs validated by the
|
||||
`framing/frame` module; once the type discriminator is read, the
|
||||
payload bytes are projected into one of the shapes validated here so
|
||||
that consumers handling the payload at the application layer get a
|
||||
Zod-safe value rather than raw bytes.
|
||||
|
||||
The shapes match the canonical `DriveTransport` contract from
|
||||
`@suaveplan/drive-mesh`: file ids are hex-encoded (`64` lowercase
|
||||
hex chars) and advertisements carry a `totalChunks` field alongside
|
||||
the gzipped bitset. Anything else fails Zod validation and surfaces
|
||||
as a `DriveTransportWebRtcError(FRAME_INVALID)` at the transport
|
||||
boundary.
|
||||
|
||||
## Features
|
||||
|
||||
- `RequestChunkPayloadSchema` — `{ fileId: string(hex64), chunkId: uint32 }`.
|
||||
- `AdvertisementPayloadSchema` — `{ fileId: string(hex64), totalChunks: uint32, bitsetGzip: Uint8Array(>0) }`.
|
||||
- `FILE_ID_BYTES` — the raw 32-byte wire length constant.
|
||||
- `FILE_ID_HEX_LENGTH` — the corresponding `64` hex-char length.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
RequestChunkPayloadSchema,
|
||||
} from "@suaveplan/drive-transport-webrtc";
|
||||
|
||||
const parsed = RequestChunkPayloadSchema.parse({
|
||||
fileId: "ab".repeat(32),
|
||||
chunkId: 42,
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
AdvertisementPayloadSchema,
|
||||
decodeAdvertisement,
|
||||
decodeFrame,
|
||||
FRAME_TYPE,
|
||||
} from "@suaveplan/drive-transport-webrtc";
|
||||
|
||||
function projectAdvertisement(frameBytes: Uint8Array) {
|
||||
const frame = decodeFrame(frameBytes);
|
||||
if (frame.type !== FRAME_TYPE.ADVERTISEMENT) return undefined;
|
||||
const decoded = decodeAdvertisement(frame.payload);
|
||||
return AdvertisementPayloadSchema.parse(decoded);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `FILE_ID_BYTES: 32` — re-exported raw-bytes constant for the
|
||||
on-the-wire form.
|
||||
- `FILE_ID_HEX_LENGTH: 64` — corresponding hex-char length for the
|
||||
public API form.
|
||||
- `RequestChunkPayloadSchema` — Zod object with exact-64-char hex
|
||||
`fileId` refinement and `chunkId` clamped to non-negative uint32.
|
||||
- `AdvertisementPayloadSchema` — Zod object enforcing the hex
|
||||
`fileId`, a uint32 `totalChunks`, and a non-empty `bitsetGzip`
|
||||
payload.
|
||||
- `RequestChunkPayload` / `AdvertisementPayload` — inferred TypeScript
|
||||
types.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The schemas live outside the codec module so that consumers who want
|
||||
to validate at the application boundary (e.g. before queueing a
|
||||
request for retry) can do so without re-importing the binary codec.
|
||||
The `bitsetGzip` field is asserted non-empty because every well-formed
|
||||
gzip stream is at least a few bytes; an empty value usually indicates
|
||||
a slicing bug at the sender, which we surface eagerly. `chunkId` and
|
||||
`totalChunks` are clamped to uint32 to match the wire encoding
|
||||
(`DataView.setUint32`).
|
||||
Reference in New Issue
Block a user