Files
initiative/apps/web/src/persistence/player-character-storage.ts
Lukas 1de00e3d8e
All checks were successful
CI / check (push) Successful in 1m16s
CI / build-image (push) Has been skipped
Move entity rehydration to domain layer, fix tempHp gap
Rehydration functions (reconstructing typed domain objects from untyped
JSON) lived in persistence adapters, duplicating domain validation.
Adding a field required updating both the domain type and a separate
adapter function — the adapter was missed for `level`, silently dropping
it on reload. Now adding a field only requires updating the domain type
and its co-located rehydration function.

- Add `rehydratePlayerCharacter` and `rehydrateCombatant` to domain
- Persistence adapters delegate to domain instead of reimplementing
- Add `tempHp` validation (was silently dropped during rehydration)
- Tighten initiative validation to integer-only
- Exhaustive domain tests (53 cases); adapter tests slimmed to round-trip
- Remove stale `jsinspect-plus` Knip ignoreDependencies entry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:12:41 +01:00

34 lines
868 B
TypeScript

import type { PlayerCharacter } from "@initiative/domain";
import { rehydratePlayerCharacter } from "@initiative/domain";
const STORAGE_KEY = "initiative:player-characters";
export function savePlayerCharacters(characters: PlayerCharacter[]): void {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(characters));
} catch {
// Silently swallow errors (quota exceeded, storage unavailable)
}
}
export function loadPlayerCharacters(): PlayerCharacter[] {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (raw === null) return [];
const parsed: unknown = JSON.parse(raw);
if (!Array.isArray(parsed)) return [];
const characters: PlayerCharacter[] = [];
for (const item of parsed) {
const pc = rehydratePlayerCharacter(item);
if (pc !== null) {
characters.push(pc);
}
}
return characters;
} catch {
return [];
}
}