Expand ecash explorer capabilities

Add Fedimint discovery, dual SQLite/Postgres storage, richer review handling, and generated social imagery.
This commit is contained in:
michilis
2026-08-21 02:10:48 +02:00
parent aa1771ea20
commit 6f17b572b1
80 changed files with 7580 additions and 704 deletions
+39
View File
@@ -0,0 +1,39 @@
/**
* Read a response body up to `maxBytes`, or refuse it.
*
* `res.arrayBuffer()` and `res.json()` buffer however much the server sends before any
* size check can run, and a mint is an untrusted server: the abort timer bounds how
* *long* a read may take, this bounds how *large* it may get, and both are needed. The
* Content-Length header is checked first as a courtesy — a chunked or lying response
* still hits the streaming cap.
*
* Returns null when the body is over the limit or unreadable. The caller treats that
* exactly like a failed fetch.
*/
export async function readBodyBounded(res: Response, maxBytes: number): Promise<Buffer | null> {
const declared = Number(res.headers.get('content-length') ?? '');
if (Number.isFinite(declared) && declared > maxBytes) return null;
const reader = res.body?.getReader();
if (!reader) return null;
const chunks: Uint8Array[] = [];
let size = 0;
try {
for (;;) {
const { done, value } = await reader.read();
if (done) break;
size += value.byteLength;
if (size > maxBytes) {
await reader.cancel().catch(() => undefined);
return null;
}
chunks.push(value);
}
} catch {
// Aborted by the caller's timer, or the connection died mid-body.
return null;
}
return Buffer.concat(chunks);
}