mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 03:55:38 -04:00
- 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
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { ORPCError } from "@orpc/client";
|
|
|
|
import type { AppErrorCode } from "@sofa/api/errors";
|
|
|
|
export function getAppErrorCode(error: unknown): AppErrorCode | null {
|
|
if (
|
|
error instanceof ORPCError &&
|
|
error.data &&
|
|
typeof error.data === "object" &&
|
|
"code" in error.data &&
|
|
typeof error.data.code === "string"
|
|
) {
|
|
return error.data.code as AppErrorCode;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Must be called inside a render/hook body with the `t` from useLingui()
|
|
export function appErrorMessages(
|
|
t: (template: TemplateStringsArray, ...args: unknown[]) => string,
|
|
): Record<AppErrorCode, string> {
|
|
return {
|
|
TITLE_NOT_FOUND: t`Title not found`,
|
|
PERSON_NOT_FOUND: t`Person not found`,
|
|
INTEGRATION_NOT_FOUND: t`Integration not found`,
|
|
BACKUP_NOT_FOUND: t`Backup not found`,
|
|
BACKUP_DELETE_FAILED: t`Failed to delete backup`,
|
|
BACKUP_RESTORE_FAILED: t`Backup restoration failed`,
|
|
JOB_NOT_FOUND: t`Job not found`,
|
|
TMDB_NOT_CONFIGURED: t`TMDB API key is not configured`,
|
|
IMPORT_INVALID_FILE: t`Invalid import file`,
|
|
IMPORT_PAYLOAD_TOO_LARGE: t`Import payload is too large`,
|
|
IMPORT_ALREADY_RUNNING: t`An import is already in progress`,
|
|
IMPORT_CANNOT_CANCEL: t`This import cannot be cancelled`,
|
|
REGISTRATION_CLOSED: t`Registration is currently closed`,
|
|
EXPORT_FAILED: t`Failed to export data`,
|
|
};
|
|
}
|
|
|
|
export function getErrorMessage(
|
|
error: unknown,
|
|
t: (template: TemplateStringsArray, ...args: unknown[]) => string,
|
|
fallback?: string,
|
|
): string {
|
|
const code = getAppErrorCode(error);
|
|
if (code) {
|
|
const messages = appErrorMessages(t);
|
|
if (code in messages) return messages[code as keyof typeof messages];
|
|
}
|
|
return fallback ?? t`Something went wrong`;
|
|
}
|