/** * Parse JSON without throwing. * ───────────────────────────────────────────────────────────────────────────── * `JSON.parse` on untrusted input (decrypted DM/gift-wrap payloads, relay event * content, persisted localStorage blobs) throws on any malformed byte. A single * bad value can crash an async message-processing loop (local DoS — messages * stop rendering until reload) or crash-loop the app on boot before a Zod schema * gets a chance to validate. * * `safeJson` returns the provided fallback instead of throwing, so callers can * skip a bad item and keep going. Pair with schema validation (e.g. Zod) for the * happy path — this only guarantees you never throw. * * @example * const data = safeJson(raw, {} as MyShape); * const parsed = MySchema.safeParse(safeJson(stored, {})); */ export function safeJson(raw: string, fallback: T): T { try { return JSON.parse(raw) as T; } catch { return fallback; } }