import { error, isActionFailure, isHttpError, isRedirect, type Action } from '@sveltejs/kit'; import { ReadOnlyError } from './ledger/errors'; const STORAGE_MESSAGE = 'Could not save — the storage backend is unavailable. Please try again.'; const READ_ONLY_MESSAGE = 'The app is temporarily read-only; try again in a couple of minutes.'; /** * Wraps every action so an unexpected throw (bucket down, disk read-only, scrypt overload) * surfaces as a 503 the user can act on instead of a bare 500. Redirects, HttpErrors and * `fail()` results are the action's own control flow and pass through untouched. */ export function guarded>>(actions: T): T { const wrapped: Record> = {}; for (const [name, action] of Object.entries(actions)) { wrapped[name] = async (event) => { try { return await action(event); } catch (e) { if (isRedirect(e) || isHttpError(e) || isActionFailure(e)) throw e; if (e instanceof ReadOnlyError) error(503, READ_ONLY_MESSAGE); console.error('[action] storage failure', e); error(503, STORAGE_MESSAGE); } }; } return wrapped as T; }