From 6c1828ca02bd420adbdc390ccd493dcd6f874f90 Mon Sep 17 00:00:00 2001 From: theMackabu Date: Sat, 25 Apr 2026 18:10:29 -0700 Subject: [PATCH] improve .json path for report --- docs/reports/src/reports.ts | 47 ++++++++++++++++++++++++++++++++++--- docs/reports/src/routes.ts | 12 ++++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/reports/src/reports.ts b/docs/reports/src/reports.ts index 830d04f..0b22671 100644 --- a/docs/reports/src/reports.ts +++ b/docs/reports/src/reports.ts @@ -5,6 +5,22 @@ import { generate as generateShortUuid } from 'short-uuid'; import { frames as frameTable, reportFrames, reports, type CrashReport } from './schema'; type ReportDb = ReturnType; +type ReportFrameRow = { + frame: string; + frameHash: string; + frameIndex: number; +}; + +export type RawReport = { + id: string; + trace: string; + firstSeenAt: string; + lastSeenAt: string; + hitCount: number; + expiresAt: string; + report: CrashReport; + frames: ReportFrameRow[]; +}; async function reportTrace(report: CrashReport): Promise { const traceInput = JSON.stringify({ @@ -24,7 +40,7 @@ async function reportTrace(report: CrashReport): Promise { const reportFromRows = ( row: typeof reports.$inferSelect, - frameRows: { frame: string }[], + frameRows: ReportFrameRow[], ): CrashReport => ({ schema: 1, runtime: 'ant', @@ -64,10 +80,12 @@ async function insertReportFrames(db: ReportDb, reportId: string, frames: string ); } -async function getReportFrames(db: ReportDb, reportId: string): Promise<{ frame: string }[]> { +async function getReportFrames(db: ReportDb, reportId: string): Promise { return db .select({ frame: frameTable.frame, + frameHash: reportFrames.frameHash, + frameIndex: reportFrames.frameIndex, }) .from(reportFrames) .innerJoin(frameTable, eq(reportFrames.frameHash, frameTable.hash)) @@ -75,14 +93,37 @@ async function getReportFrames(db: ReportDb, reportId: string): Promise<{ frame: .orderBy(asc(reportFrames.frameIndex)); } -export async function getReport(db: ReportDb, id: string): Promise { +async function getReportRow(db: ReportDb, id: string): Promise { const [row] = await db.select().from(reports).where(eq(reports.id, id)).limit(1); + return row ?? null; +} + +export async function getReport(db: ReportDb, id: string): Promise { + const row = await getReportRow(db, id); if (!row) return null; const frames = await getReportFrames(db, row.id); return reportFromRows(row, frames); } +export async function getRawReport(db: ReportDb, id: string): Promise { + const row = await getReportRow(db, id); + + if (!row) return null; + const frames = await getReportFrames(db, row.id); + + return { + id: row.id, + trace: row.trace, + firstSeenAt: row.firstSeenAt, + lastSeenAt: row.lastSeenAt, + hitCount: row.hitCount, + expiresAt: row.expiresAt, + report: reportFromRows(row, frames), + frames, + }; +} + export async function createReport(db: ReportDb, report: CrashReport): Promise { const id = generateShortUuid(); const trace = await reportTrace(report); diff --git a/docs/reports/src/routes.ts b/docs/reports/src/routes.ts index a37a4e1..0670601 100644 --- a/docs/reports/src/routes.ts +++ b/docs/reports/src/routes.ts @@ -4,7 +4,7 @@ import type { Bindings } from './env'; import { drizzle } from 'drizzle-orm/d1'; import { CrashReportSchema } from './schema'; import { renderBlank, renderReport } from './view'; -import { createReport, getReport } from './reports'; +import { createReport, getRawReport, getReport } from './reports'; import { getAntLogoDataUrl, @@ -48,7 +48,15 @@ app.get('/og/:image', async c => { app.get('/:id', async c => { const db = drizzle(c.env.DB); - const id = c.req.param('id'); + const pathId = c.req.param('id'); + + if (pathId.endsWith('.json')) { + const report = await getRawReport(db, pathId.slice(0, -5)); + if (!report) return c.json({ error: 'not found' }, 404); + return c.json(report, 200); + } + + const id = pathId; const report = await getReport(db, id); if (!report) return c.html(renderBlank(), 404); -- 2.51.2