Add JSON import/export for full encounter state
Export and import encounter, undo/redo history, and player characters as a downloadable .json file. Export/import actions are in the action bar overflow menu. Import validates using existing rehydration functions and shows a confirmation dialog when replacing a non-empty encounter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
52
specs/007-json-import-export/quickstart.md
Normal file
52
specs/007-json-import-export/quickstart.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Quickstart: JSON Import/Export
|
||||
|
||||
**Feature**: 007-json-import-export
|
||||
**Date**: 2026-03-27
|
||||
|
||||
## Overview
|
||||
|
||||
Export and import the full application state (encounter, undo/redo history, player characters) as a JSON file. Enables backup/restore and sharing encounters between DMs.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **ExportBundle**: A JSON object containing `version`, `exportedAt`, `encounter`, `undoStack`, `redoStack`, and `playerCharacters`. This is the file format.
|
||||
- **Full replacement**: Import replaces all existing state — encounter, undo/redo, and player characters. It's not a merge.
|
||||
- **Validation reuse**: Import validation uses the same `rehydrateEncounter()` and player character validation functions that localStorage loading uses.
|
||||
|
||||
## Implementation Layers
|
||||
|
||||
### Domain Layer
|
||||
|
||||
No new domain functions are needed. The existing types (`Encounter`, `PlayerCharacter`, `UndoRedoState`) and validation functions are reused as-is.
|
||||
|
||||
A new `ExportBundle` type is defined in the domain layer as a pure data structure.
|
||||
|
||||
### Application Layer
|
||||
|
||||
A new use case for import validation and bundle assembly:
|
||||
- `validateImportBundle(data: unknown)` — validates and rehydrates an export bundle, returning the validated bundle or an error.
|
||||
|
||||
Export assembly is straightforward enough to live in the adapter layer (it's just reading and packaging existing state).
|
||||
|
||||
### Adapter Layer (Web)
|
||||
|
||||
- **Export**: Read state from contexts, assemble bundle, trigger browser download via `URL.createObjectURL()` + anchor element.
|
||||
- **Import**: File picker input, parse JSON, delegate to application-layer validation, show confirmation dialog if encounter is non-empty, replace state via context setters.
|
||||
- **UI**: Two new overflow menu items in the action bar — "Export Encounter" and "Import Encounter".
|
||||
|
||||
## File Locations
|
||||
|
||||
| Artifact | Path |
|
||||
|----------|------|
|
||||
| ExportBundle type | `packages/domain/src/types.ts` or new file |
|
||||
| Import validation use case | `packages/application/src/` |
|
||||
| Export/import adapter functions | `apps/web/src/persistence/` |
|
||||
| UI integration | `apps/web/src/components/action-bar.tsx` |
|
||||
| Confirmation dialog | `apps/web/src/components/` (new or reuse existing confirm pattern) |
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
- **Domain**: No new domain tests needed (existing types unchanged).
|
||||
- **Application**: Test `validateImportBundle()` with valid bundles, invalid bundles, missing fields, wrong types, and edge cases (empty encounter, empty stacks).
|
||||
- **Adapter**: Test export bundle assembly and import file handling.
|
||||
- **Integration**: Round-trip test — export then import should produce identical state.
|
||||
Reference in New Issue
Block a user