import { getPool } from "../../db/index.js"; // Audit rows carry no user_id, so they are attributed via event OR agreement // uuid — deliberately wider than the event-only listAudit view. export async function getStorage(userId) { const client = await getPool(); try { const row = ( await client.query( `WITH ua AS ( SELECT a.audit_id, a.digest FROM audit a WHERE a.event_id IN (SELECT event_id_uuid FROM event WHERE user_id = $1) OR a.agreement_id IN (SELECT agreement_id_uuid FROM agreement WHERE user_id = $1) ) SELECT (SELECT COALESCE(SUM(pg_column_size(data)), 0)::bigint FROM event_data WHERE user_id = $1) AS core_on_disk, (SELECT COALESCE(SUM(octet_length(data)), 0)::bigint FROM event_data WHERE user_id = $1) AS core_logical, COALESCE(SUM(pg_column_size(ua.digest)), 0)::bigint + COALESCE((SELECT SUM(pg_column_size(s.jws)) FROM audit_signature s WHERE s.audit_id IN (SELECT audit_id FROM ua)), 0)::bigint AS audit_on_disk, COALESCE(SUM(octet_length(ua.digest)), 0)::bigint + COALESCE((SELECT SUM(octet_length(s.jws)) FROM audit_signature s WHERE s.audit_id IN (SELECT audit_id FROM ua)), 0)::bigint AS audit_logical FROM ua`, [userId], ) ).rows[0]; const coreOnDisk = Number(row.core_on_disk); const auditOnDisk = Number(row.audit_on_disk); const coreLogical = Number(row.core_logical); const auditLogical = Number(row.audit_logical); return { onDisk: { core: coreOnDisk, audit: auditOnDisk, total: coreOnDisk + auditOnDisk }, logical: { core: coreLogical, audit: auditLogical, total: coreLogical + auditLogical }, }; } finally { await client.release(); } }