first commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# `sanitizeKey`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user