first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
# header
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Defines the 32-byte fixed-width metadata header that `StorageCache` prepends to every cached value. The header carries `createdAt`, `expiresAt`, `flags`, and `hitCount` so the cache can recover TTL semantics over any byte-oriented `AbstractStorage` without a side-channel metadata API. Fixed width keeps reads single-range and avoids a second round-trip when the underlying store supports byte-range fetches.
## Features
- 32 bytes, big-endian, deterministic layout — byte-identical between writers and readers across runtimes.
- Two `u64` fields (`createdAt`, `expiresAt`) accommodate millisecond timestamps well past the year 10000.
- One `u32` `flags` word carries codec selector bits (`FLAG_CODEC_JSON`) and a `FLAG_HAS_METADATA` presence bit reserved for downstream extensions.
- One `u32` `hitCount` saturates at 2³² − 1 — informational only; not rewritten on read in this version.
- 8 reserved bytes at the tail leave room for future extension without a version bump.
- Bounds-checked `encodeHeader` — out-of-range fields surface as `StorageCacheError("CACHE_STORAGE.ENTRY_CORRUPT")` rather than producing a silently truncated blob.
## Usage: Basic Example
```ts
import { decodeHeader, encodeHeader } from "@suaveplan/cache-storage/header";
const bytes = encodeHeader({
createdAt: Date.now(),
expiresAt: 0,
flags: 0,
hitCount: 0,
});
const meta = decodeHeader(bytes);
```
## Usage: Advanced Example
```ts
import {
decodeHeader,
encodeHeader,
FLAG_CODEC_JSON,
FLAG_HAS_METADATA,
HEADER_BYTES,
} from "@suaveplan/cache-storage/header";
function packEntry(value: Uint8Array, ttlMs: number): Uint8Array {
const now = Date.now();
const head = encodeHeader({
createdAt: now,
expiresAt: ttlMs > 0 ? now + ttlMs : 0,
flags: FLAG_HAS_METADATA | FLAG_CODEC_JSON,
hitCount: 0,
});
const out = new Uint8Array(HEADER_BYTES + value.length);
out.set(head, 0);
out.set(value, HEADER_BYTES);
return out;
}
function unpackEntry(blob: Uint8Array): {
meta: ReturnType<typeof decodeHeader>;
body: Uint8Array;
} {
return { meta: decodeHeader(blob), body: blob.subarray(HEADER_BYTES) };
}
```
## API Reference
| Export | Kind | Purpose |
| --- | --- | --- |
| `HEADER_BYTES` | const number `32` | Fixed length of the metadata header. |
| `HeaderMeta` | interface | `{ createdAt: number; expiresAt: number; flags: number; hitCount: number }`. |
| `encodeHeader(meta)` | function | Returns a fresh 32-byte `Uint8Array`. Throws `StorageCacheError("CACHE_STORAGE.ENTRY_CORRUPT")` when any field is out of range. |
| `decodeHeader(bytes)` | function | Parses the leading 32 bytes. Throws `StorageCacheError("CACHE_STORAGE.ENTRY_CORRUPT")` when the buffer is shorter. |
| `FLAG_HAS_METADATA` | const number | Bit 0 — set by `StorageCache` on every encode. |
| `FLAG_CODEC_JSON` | const number | Bit 1 — set when the body was produced by `JsonCodec` (for future routing). |
## Implementation Notes
`u64` values are split into two `u32` big-endian writes (`high * 2³² + low`) so the encoder runs without `BigInt` overhead. `decodeHeader` is the inverse. The reserved 8 bytes at offset 24..31 are zeroed at encode time to keep on-disk parity bytewise stable; future versions may stuff version markers there without breaking forward decoders that mask the field.