feat: add user data export and sofa export re-import support

- Add `GET /api/export/user-data` route that streams a JSON attachment of the authenticated user's full library data, named `sofa-export-<name>-<date>.json`
- Add `generateUserExport` in `@sofa/core/export` and a matching `parseSofaExport` parser so exported files can be re-imported via the existing import pipeline
- Register `sofa` as a new `ImportSource` in the API contract/schemas and wire up `parseSofaExport` in the `parseFile` procedure
- Add `EXPORT_FAILED` error code to the API error registry and surface it in web and native error-message maps
- Update the account settings section with export/import UI (download button, import progress)
- Add tests for `generateUserExport`, `parseSofaExport`, and round-trip fidelity
This commit is contained in:
2026-03-21 17:12:15 -04:00
parent 58cf2e689f
commit 61013ee41f
23 changed files with 1214 additions and 39 deletions
@@ -8,6 +8,7 @@ import {
insertImportJob,
parseLetterboxdExport,
parseSimklPayload,
parseSofaExport,
parseTraktPayload,
processImportJob,
readImportJob,
@@ -57,6 +58,19 @@ export const parseFile = os.imports.parseFile.use(authed).handler(async ({ input
result = parseSimklPayload(json as Parameters<typeof parseSimklPayload>[0]);
break;
}
case "sofa": {
let json: unknown;
try {
json = await file.json();
} catch {
throw new ORPCError("BAD_REQUEST", {
message: "Invalid JSON file",
data: { code: AppErrorCode.IMPORT_INVALID_FILE },
});
}
result = parseSofaExport(json);
break;
}
}
return {