first commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# `@suaveplan/license` — codec/payload
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`packPayload` and `unpackPayload` are the 72-bit payload codec on top of
|
||||
the bitpack primitives. They emit exactly 9 bytes (the binary contract
|
||||
shared with upstream `@suaveplan/license`) and walk the 9 schema fields
|
||||
in the canonical order declared by `FIELD_BITS`.
|
||||
|
||||
`packPayload` raises `LicenseError(LICENSE.PAYLOAD_OUT_OF_RANGE)` when a
|
||||
field exceeds its declared bit width (via the underlying bitpacker).
|
||||
`unpackPayload` raises `LicenseError(LICENSE.MALFORMED)` for any input
|
||||
length other than `PAYLOAD_BYTES` (9).
|
||||
|
||||
## Features
|
||||
|
||||
- Bit-for-bit wire compatibility with upstream's `packPayload` /
|
||||
`unpackPayload`.
|
||||
- Field-bound validation via `SimpleBitPacker.packUint`, surfaced as
|
||||
typed `LicenseError`s.
|
||||
- Strict 9-byte length invariant on both sides — no implicit truncation
|
||||
or padding.
|
||||
- Returns a fresh `Uint8Array`; safe to mutate the caller's buffer.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
packPayload,
|
||||
unpackPayload,
|
||||
} from "@suaveplan/license/codec/payload/payload";
|
||||
import { PackageTier, TimeEncodingType } from "@suaveplan/license/types/license";
|
||||
|
||||
const bytes = packPayload({
|
||||
version: 2,
|
||||
signingKeyId: 0,
|
||||
productId: 1,
|
||||
packageTier: PackageTier.PRO,
|
||||
flags: 0,
|
||||
timeEncodingType: TimeEncodingType.NONE,
|
||||
timeValue: 0,
|
||||
featureMask: 0,
|
||||
nonce: 0x123,
|
||||
});
|
||||
console.log(bytes.length); // 9
|
||||
const round = unpackPayload(bytes);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Catching a field-overflow at the generation boundary:
|
||||
|
||||
```ts
|
||||
import { LicenseError } from "@suaveplan/license";
|
||||
import { packPayload } from "@suaveplan/license/codec/payload/payload";
|
||||
|
||||
try {
|
||||
packPayload({ /* ...valid */ productId: 64 } as never); // 6 bits, max 63
|
||||
} catch (err) {
|
||||
if (err instanceof LicenseError && err.code === "LICENSE.PAYLOAD_OUT_OF_RANGE") {
|
||||
// surface to the user as a form-validation failure
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `packPayload(payload: LicensePayload): Uint8Array`
|
||||
|
||||
Pack a payload to its 9-byte representation. Throws
|
||||
`LicenseError(LICENSE.PAYLOAD_OUT_OF_RANGE)` on field overflow.
|
||||
|
||||
### `unpackPayload(data: Uint8Array): LicensePayload`
|
||||
|
||||
Unpack a 9-byte buffer. Throws `LicenseError(LICENSE.MALFORMED)` for
|
||||
any other length.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The unpacker casts `timeEncodingType` to the `TimeEncodingType` enum
|
||||
even though the bit width (2) admits any value in `[0, 3]` — all four
|
||||
values map to legitimate enum members, so the cast is safe. The
|
||||
constant `PAYLOAD_BYTES = 9` lives in `constants/constants.ts` so any
|
||||
future schema change (which would require a `LICENSE_VERSION` bump)
|
||||
updates a single source of truth.
|
||||
Reference in New Issue
Block a user