Add library export and import
The only backup was the Docker volume. Export writes the caller's whole library as JSON or CSV; import reads either back, into the same account or a different one. Rows are matched on title + system rather than id, so a file is portable between accounts and instances, and the same game on three consoles stays three entries. Merge adds and updates but deletes nothing. Replace wipes first, and is gated behind an explicit confirm dialog in the UI. dryRun reports what would happen and writes nothing. CSV is hand-rolled rather than pulling a dependency, but handles the parts that actually bite: quoted fields containing commas, escaped quotes, embedded newlines and CRLF endings. That is not hypothetical here — 101 of the 105 descriptions contain newlines, and two titles contain accents, so a naive split-on-comma would corrupt most of the library. Exports carry a BOM so Excel reads them as UTF-8. Verified against the real library, not just fixtures: 105 games exported to CSV, imported into a scratch account and re-exported compare identical field for field. 15 new tests cover round-trip fidelity, merge vs replace, dry run, per-user isolation on the destructive path, malformed input, and the awkward-quoting case. 51 backend tests total. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -169,6 +169,24 @@ Parsing an infobox is messier than it looks, and the guards matter:
|
||||
Four games have no usable article: a typo'd title (`Brett Hull Hocky 95`),
|
||||
`Dragon Ball Z Budokai`, and two niche releases.
|
||||
|
||||
### Export and import
|
||||
|
||||
Until this existed, the only backup was the Docker volume.
|
||||
|
||||
- `GET /api/library/export?format=json|csv`
|
||||
- `POST /api/library/import?mode=Merge|Replace&dryRun=true` (multipart `file`)
|
||||
|
||||
Both are in the UI on the account page. JSON round-trips exactly and is the
|
||||
right choice for a backup; CSV opens in a spreadsheet and is written with a BOM
|
||||
so Excel does not mangle `Pokémon`. **Box art images are not bundled** — they
|
||||
live in the upload volume, and a library imported into a fresh instance will
|
||||
reference art that is not there until the fetcher runs again.
|
||||
|
||||
Rows are matched on **title + system**, so the same game on three consoles stays
|
||||
three entries. `Merge` adds and updates but never deletes; `Replace` wipes the
|
||||
library first and is confirmed twice in the UI. `dryRun` reports exactly what
|
||||
would happen and writes nothing.
|
||||
|
||||
### Database changes
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user