Files
sofa/apps/web/src/lib/error-messages.ts
T
jake 61013ee41f 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
2026-03-21 17:12:15 -04:00

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`;
}