first commit
This commit is contained in:
79
docs/networking/events/broadcast-channel/src/id/id.md
Normal file
79
docs/networking/events/broadcast-channel/src/id/id.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# id/id
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`generateId` is the shared 16-character lowercase-hex identifier generator
|
||||
used for tab IDs and per-message IDs throughout
|
||||
`@suaveplan/broadcast-channel`. The upstream library inlined two near-identical
|
||||
`generate*Id` helpers — pulling that into a single function with injectable
|
||||
`Rng` lets the channel core compute deterministic IDs in tests and resolves
|
||||
the enterprise-doc smell ("Two duplicate `generateTabId` / `generateMsgId`
|
||||
functions; should share via a local `internal/id.ts`").
|
||||
|
||||
The module also exports `defaultRng`, an `Rng` implementation backed by Web
|
||||
Crypto's `getRandomValues`. Browsers and modern Node / Bun all expose the
|
||||
global `crypto` object so `defaultRng` works in every supported runtime
|
||||
without any extra polyfill.
|
||||
|
||||
## Features
|
||||
|
||||
- Single helper for every ID the package produces.
|
||||
- Accepts any `Rng` (`@suaveplan/types`) — seeded RNGs make tests deterministic.
|
||||
- Honours optional `rng.nextBytes` when present (faster, fewer calls).
|
||||
- Pure-function fallback that derives 8 bytes from two `nextUint32()` calls.
|
||||
- Stable encoding: lowercase hex, fixed 16 characters, no separators.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { defaultRng, generateId } from "@suaveplan/broadcast-channel";
|
||||
|
||||
const tabId = generateId(defaultRng);
|
||||
// tabId === "a3f1c0...", 16 hex chars
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { generateId } from "@suaveplan/broadcast-channel";
|
||||
import type { Rng } from "@suaveplan/types";
|
||||
|
||||
function seededRng(values: readonly number[]): Rng {
|
||||
let i = 0;
|
||||
return {
|
||||
nextUint32: () => {
|
||||
const v = values[i % values.length] ?? 0;
|
||||
i++;
|
||||
return v >>> 0;
|
||||
},
|
||||
nextFloat() {
|
||||
return this.nextUint32() / 0x1_0000_0000;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const tabId = generateId(seededRng([0xdeadbeef, 0x01020304]));
|
||||
// tabId === "deadbeef01020304"
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `function generateId(rng: Rng): string` — returns a 16-character hex string built from 8 random bytes drawn from `rng`. Uses `rng.nextBytes(8)` when available, otherwise two `nextUint32()` calls.
|
||||
- `const defaultRng: Rng` — Web-Crypto-backed RNG suitable for production browser code. Exposes `nextUint32`, `nextFloat`, and `nextBytes`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
When `rng.nextBytes` is not supplied, the helper packs two unsigned 32-bit
|
||||
words into an 8-byte buffer in big-endian order, then encodes each byte as a
|
||||
two-character zero-padded hex pair. The big-endian packing is deliberate: it
|
||||
makes the seeded-RNG test contract human-readable (`0xdeadbeef` → first 4
|
||||
hex bytes `deadbeef`) and keeps the encoding stable if downstream code ever
|
||||
parses the ID back into bytes. The hex emission is the simplest two-character
|
||||
output that survives JSON / URL / localStorage transport without escaping. We
|
||||
avoid `crypto.randomUUID()` because the channel needs a fixed 16-hex shape
|
||||
for the leader-election sort to be deterministic and because randomUUID
|
||||
output is not available in every test sandbox.
|
||||
Reference in New Issue
Block a user