Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1x 1x 8x 8x 8x 8x 8x 6x 6x 7x 6x 6x 1x | // Admin Communication History Log routes (spec: communication_history_log).
//
// Ops/legal CSV export — includes ALL entries (Ops-only ones too) with full
// timestamps, event types, actor ids, and visibility flags. Mounted under
// /api/admin/communication-logs; the parent admin router already applies
// contextMiddleware + requirePlatformAdmin.
import { Hono } from "hono";
import { csvField } from "../../lib/csv";
import { handleError } from "../../lib/response";
import type { ContextVariables } from "../../middleware";
type Env = { Bindings: CloudflareBindings; Variables: ContextVariables };
const app = new Hono<Env>();
// GET /api/admin/communication-logs/export[?inquiryId=N] — CSV download
app.get("/export", async (c) => {
try {
const dal = c.get("dal");
const inquiryIdParam = c.req.query("inquiryId");
const inquiryId = inquiryIdParam
? Number.parseInt(inquiryIdParam, 10)
: undefined;
const rows =
inquiryId && Number.isFinite(inquiryId)
? await dal.communicationLogs.listByInquiry(inquiryId)
: await dal.communicationLogs.listAll();
const header =
"id,inquiry_id,event_type,actor_type,actor_id,visibility,metadata,created_at";
const lines = rows.map((r) =>
[
csvField(r.id),
csvField(r.inquiryId),
csvField(r.eventType),
csvField(r.actorType),
csvField(r.actorId),
csvField(r.visibility),
csvField(r.metadata),
csvField(r.createdAt.toISOString()),
].join(","),
);
const csv = [header, ...lines].join("\n");
return c.body(csv, 200, {
"Content-Type": "text/csv; charset=utf-8",
"Content-Disposition": `attachment; filename="communication-logs${inquiryId ? `-inquiry-${inquiryId}` : ""}.csv"`,
});
} catch (err) {
return handleError(c, err);
}
});
export default app;
|