# `sanitizeKey` _(no submodules)_ ## Purpose The `sanitizeKey` boundary validates every caller-supplied IndexedDB primary key before it crosses the public API surface of `IndexedDbStorage`. Strict validation up front prevents two classes of failure: silent corruption from malformed keys (control characters that confuse later debugging tooling, empty strings that masquerade as falsy values), and security issues where attacker-controlled keys could mimic path-traversal patterns even though IndexedDB itself does not interpret slashes. The sanitiser keeps the package's key contract aligned with the sibling `@suaveplan/storage-browser-opfs` `sanitizeKey`, so a caller can swap backends behind `AbstractStorage` without seeing a different validation contract. ## Features - Rejects non-string input, empty strings, and keys longer than 1024 characters (`KEY_TOO_LONG`). - Rejects keys with C0 control characters (0x00-0x1F) or DEL (0x7F). - Rejects POSIX-absolute keys (`/foo`) and `..` traversal segments — defensive guards for callers that later use keys as path-like identifiers. - Returns the validated key unchanged on success — no normalisation surprises. - All rejections throw `IndexedDbError` with `INDEXEDDB.INVALID_KEY` or `INDEXEDDB.KEY_TOO_LONG` and attach the offending key (truncated for `KEY_TOO_LONG`) to the error's `key` discriminant. ## Usage: Basic Example ```ts import { sanitizeKey } from "@suaveplan/storage-browser-indexeddb/key-sanitizer"; const safe = sanitizeKey("user/42/profile"); console.log(safe); // "user/42/profile" ``` ## Usage: Advanced Example ```ts import { INDEXEDDB_CODES, IndexedDbError, } from "@suaveplan/storage-browser-indexeddb/error-codes"; import { sanitizeKey } from "@suaveplan/storage-browser-indexeddb/key-sanitizer"; function validateBatch(keys: string[]): { ok: string[]; bad: { key: string; reason: string }[] } { const ok: string[] = []; const bad: { key: string; reason: string }[] = []; for (const key of keys) { try { ok.push(sanitizeKey(key)); } catch (err) { if (err instanceof IndexedDbError && err.code === INDEXEDDB_CODES.INVALID_KEY) { bad.push({ key, reason: err.message }); } else if (err instanceof IndexedDbError && err.code === INDEXEDDB_CODES.KEY_TOO_LONG) { bad.push({ key, reason: "too long" }); } else { throw err; } } } return { ok, bad }; } ``` ## API Reference - `sanitizeKey(key: string): string` — Returns `key` unchanged when valid. Throws `IndexedDbError(INDEXEDDB.INVALID_KEY)` for non-strings, empty strings, control characters, absolute paths, and `..` segments. Throws `IndexedDbError(INDEXEDDB.KEY_TOO_LONG)` when the key exceeds 1024 characters; the error's `key` discriminant carries the first 64 characters followed by an ellipsis so logs don't leak large payloads. ## Implementation Notes The maximum length of 1024 characters is shared with `@suaveplan/storage-browser-opfs/key-sanitizer` and `@suaveplan/storage`'s own `AbstractStorage.validateKey` (where the limit is also 1024). Aligning the boundary across backends keeps the public contract predictable. The sanitiser does NOT normalise Windows `\` separators to POSIX `/` (the OPFS sanitiser does) because IndexedDB primary keys are opaque strings — there is no filesystem semantic to enforce — and quiet rewriting would surprise callers that compare keys later. The runtime-level `typeof` guard is defensive against JavaScript callers that pass non-strings (the TypeScript signature already excludes them at compile time); we preserve the check rather than rely on type erasure alone.