buster/apps/web/src/routes/screenshots/metrics.$metricId.index.tsx

61 lines
2.2 KiB
TypeScript
Raw Normal View History

2025-10-03 03:39:24 +08:00
import { createServerFileRoute } from '@tanstack/react-start/server';
import { chromium } from 'playwright';
import { z } from 'zod';
2025-10-03 03:50:26 +08:00
import { Route as MetricContentRoute } from './metrics.$metricId.content';
2025-10-03 03:39:24 +08:00
2025-10-03 03:50:26 +08:00
export const GetMetricScreenshotParamsSchema = z.object({
2025-10-03 03:39:24 +08:00
metricId: z.string(),
});
2025-10-03 03:50:26 +08:00
export const GetMetricScreenshotQuerySchema = z.object({
2025-10-03 03:39:24 +08:00
version_number: z.coerce.number().min(1).optional(),
width: z.coerce.number().min(100).max(3840).default(800),
height: z.coerce.number().min(100).max(2160).default(450),
2025-10-03 03:50:26 +08:00
type: z.enum(['png', 'jpeg']).default('png'),
2025-10-03 03:39:24 +08:00
});
2025-10-03 03:50:26 +08:00
export const ServerRoute = createServerFileRoute('/screenshots/metrics/$metricId/').methods({
2025-10-03 03:39:24 +08:00
GET: async ({ request, params }) => {
console.time('capture screenshot');
const { metricId } = GetMetricScreenshotParamsSchema.parse(params);
2025-10-03 03:50:26 +08:00
const { version_number, type, width, height } = GetMetricScreenshotQuerySchema.parse(
2025-10-03 03:39:24 +08:00
Object.fromEntries(new URL(request.url).searchParams)
);
const origin = new URL(request.url).origin;
console.timeLog('capture screenshot', 'params parsed');
const browser = await chromium.launch();
console.timeLog('capture screenshot', 'browser launched');
try {
const page = await browser.newPage({
viewport: { width, height },
});
console.timeLog('capture screenshot', 'page created');
2025-10-03 03:50:26 +08:00
const fullPath = `${origin}${MetricContentRoute.fullPath}`;
2025-10-03 03:39:24 +08:00
await page.goto(fullPath, { waitUntil: 'networkidle' });
console.timeLog('capture screenshot', 'page navigated');
const screenshotBuffer = await page.screenshot({
2025-10-03 03:50:26 +08:00
type,
2025-10-03 03:39:24 +08:00
});
console.timeLog('capture screenshot', 'screenshot taken');
console.timeEnd('capture screenshot');
return new Response(new Uint8Array(screenshotBuffer), {
headers: {
'Content-Type': 'image/png',
'Content-Length': screenshotBuffer.length.toString(),
},
});
} catch (error) {
// console.error('Error capturing metric screenshot', error);
return new Response(
JSON.stringify({
message: 'Failed to capture screenshot',
}),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
} finally {
await browser.close();
}
},
});