@todayai-labs/tck-bundle-format
Runtime-agnostic primitives for the .tckb wire format — pack, unpack, hash, integrity. Same code runs in Node and the browser.
Runtime-agnostic primitives for .tckb envelopes. No node:* imports, no Vite hooks — just fflate and crypto.subtle.digest. The same code runs in the bundler (Node), the host loader (browser), the dev-server plugin, and platform BFFs.
This is the package that defines the wire format. Every producer (bundler, ad-hoc tooling) and every consumer (host, dev server, BFF) routes through packTckb / unpackTckb from here — symmetry is structural.
See the full .tckb wire format page for the byte-level spec.
Surface
| Export | What it does |
|---|---|
packTckb(input): Promise<Uint8Array> | Construct the envelope bytes from { mjs, manifest, css? }. Producer entry point. integrity and bundleHash are intentionally not input fields — they're derived from the supplied bytes by the packer (the bytes ARE the truth). |
unpackTckb(bytes, options?): Promise<UnpackedBundle> | Parse + verify. Returns { bundleHash, mjs, css, manifest, integrity, mjsByteLength }. |
TckbUnpackError | Thrown on any structural problem: malformed zip, missing required entries, bad JSON, integrity mismatch, hash claim mismatch. |
parseManifest, parseManifestRaw, WidgetManifestSummary | Structural manifest parse — just enough to identify a bundle without pulling in the full SDK. |
parseIntegrity, verifyIntegrity, IntegrityEntry, IntegrityFile | Integrity-file parsing + digest verification. |
sha384Base64Url, sha384Base64UrlOfString, isSha384Base64Url, SHA384_BASE64URL_LENGTH | The wire-format hash: SHA-384, base64url unpadded, 64 ASCII chars. |
UnpackedBundle.mjsByteLength
The unzipped byte length of widget.mjs as carried inside the .tckb envelope. Not the .tckb file size; not the gzipped transfer size. Use this when enforcing a byte budget for widgets.
Source
- Package:
packages/tck-bundle-format - Producer:
src/pack.ts - Consumer:
src/unpack.ts - Hash primitives:
src/hash.ts