working error

This commit is contained in:
Nate Kelley 2025-10-02 16:31:53 -06:00
parent f47891003e
commit d2c6328259
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
5 changed files with 50 additions and 53 deletions

View File

@ -1,19 +1,21 @@
import { chromium } from 'playwright'; import { type Browser, chromium, type Page } from 'playwright';
import { env } from '@/env'; import { env } from '@/env';
import { getSupabaseServerClient } from '@/integrations/supabase/server'; import { getSupabaseServerClient } from '@/integrations/supabase/server';
export const browserLogin = async ({ export const browserLogin = async <T = Buffer<ArrayBufferLike>>({
accessToken, accessToken,
width, width,
height, height,
fullPath, fullPath,
request, request,
callback,
}: { }: {
accessToken: string; accessToken: string;
width: number; width: number;
height: number; height: number;
fullPath: string; fullPath: string;
request: Request; request: Request;
callback: ({ page, browser }: { page: Page; browser: Browser }) => Promise<T>;
}) => { }) => {
const supabase = getSupabaseServerClient(); const supabase = getSupabaseServerClient();
const jwtPayload = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString()); const jwtPayload = JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString());
@ -63,17 +65,25 @@ export const browserLogin = async ({
const page = await context.newPage(); const page = await context.newPage();
const fullPathWithOrigin = `${origin}${fullPath}`; const fullPathWithOrigin = `${origin}${fullPath}`;
let pageError: Error | null = null;
page.on('console', (msg) => { page.on('console', (msg) => {
const hasError = msg.type() === 'error'; const text = msg.text();
if (hasError) { // React logs errors to console even when caught by error boundaries
browser.close(); if (msg.type() === 'error' && (text.includes('Error:') || text.includes('occurred in'))) {
throw new Error(`Error in browser: ${msg.text()}`); pageError = new Error(`Page error: ${text}`);
} }
}); });
await page.goto(fullPathWithOrigin, { waitUntil: 'networkidle' }); await page.goto(fullPathWithOrigin, { waitUntil: 'networkidle' });
return { context, browser, page }; const result = await callback({ page, browser });
if (pageError) {
throw pageError;
}
return { result };
} catch (error) { } catch (error) {
console.error('Error logging in to browser', error); console.error('Error logging in to browser', error);
await browser.close(); await browser.close();

View File

@ -0,0 +1,13 @@
export const createScreenshotResponse = ({
screenshotBuffer,
}: {
screenshotBuffer: Buffer<ArrayBufferLike>;
}) => {
if (!screenshotBuffer) {
throw new Error('Screenshot buffer is required');
}
return new Response(new Uint8Array(screenshotBuffer), {
headers: { 'Content-Type': 'image/png', 'Content-Length': screenshotBuffer.length.toString() },
});
};

View File

@ -1,5 +0,0 @@
import { z } from 'zod';
export const GetScreenshotRequestSharedSchema = z.object({});
export type GetScreenshotRequestShared = z.infer<typeof GetScreenshotRequestSharedSchema>;

View File

@ -1,7 +1,6 @@
import { createFileRoute } from '@tanstack/react-router'; import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetMetric } from '@/api/buster_rest/metrics'; import { prefetchGetMetric } from '@/api/buster_rest/metrics';
import { useGetUserBasicInfo } from '@/api/buster_rest/users/useGetUserInfo'; import { useGetUserBasicInfo } from '@/api/buster_rest/users/useGetUserInfo';
import { Route as ScreenshotsRoute } from '../_content';
import { GetMetricScreenshotQuerySchema } from '../metrics.$metricId.index'; import { GetMetricScreenshotQuerySchema } from '../metrics.$metricId.index';
export const Route = createFileRoute('/screenshots/_content/metrics/$metricId/content')({ export const Route = createFileRoute('/screenshots/_content/metrics/$metricId/content')({
@ -14,7 +13,7 @@ export const Route = createFileRoute('/screenshots/_content/metrics/$metricId/co
id: params.metricId, id: params.metricId,
version_number: search.version_number, version_number: search.version_number,
}); });
if (!res || true) { if (!res) {
throw new Error('Metric not found'); throw new Error('Metric not found');
} }
return { return {

View File

@ -1,11 +1,10 @@
import { createServerFileRoute } from '@tanstack/react-start/server'; import { createServerFileRoute } from '@tanstack/react-start/server';
import { z } from 'zod'; import { z } from 'zod';
import { browserLogin } from '@/api/server-functions/screenshots/browser-login'; import { browserLogin } from '@/api/server-functions/browser-login';
import { createScreenshotResponse } from '@/api/server-functions/screenshot-helpers';
import { getSupabaseServerClient } from '@/integrations/supabase/server'; import { getSupabaseServerClient } from '@/integrations/supabase/server';
import { createHrefFromLink } from '@/lib/routes'; import { createHrefFromLink } from '@/lib/routes';
const isDev = import.meta.env.DEV;
export const GetMetricScreenshotParamsSchema = z.object({ export const GetMetricScreenshotParamsSchema = z.object({
metricId: z.string(), metricId: z.string(),
}); });
@ -36,43 +35,26 @@ export const ServerRoute = createServerFileRoute('/screenshots/metrics/$metricId
Object.fromEntries(new URL(request.url).searchParams) Object.fromEntries(new URL(request.url).searchParams)
); );
const { browser, page } = await browserLogin({
accessToken,
width,
height,
fullPath: createHrefFromLink({
to: '/screenshots/metrics/$metricId/content',
params: { metricId },
search: { version_number, type, width, height },
}),
request,
});
try { try {
const screenshotBuffer = await page.screenshot({ const { result: screenshotBuffer } = await browserLogin({
type, accessToken,
}); width,
height,
if (!isDev) { fullPath: createHrefFromLink({
return new Response( to: '/screenshots/metrics/$metricId/content',
JSON.stringify({ params: { metricId },
success: true, search: { version_number, type, width, height },
}), }),
{ request,
status: 200, callback: async ({ page }) => {
headers: { const screenshotBuffer = await page.screenshot({
'Content-Type': 'application/json', type,
}, });
} return screenshotBuffer;
);
}
return new Response(new Uint8Array(screenshotBuffer), {
headers: {
'Content-Type': 'image/png',
'Content-Length': screenshotBuffer.length.toString(),
}, },
}); });
return createScreenshotResponse({ screenshotBuffer });
} catch (error) { } catch (error) {
console.error('Error capturing metric screenshot', error); console.error('Error capturing metric screenshot', error);
return new Response( return new Response(
@ -81,8 +63,6 @@ export const ServerRoute = createServerFileRoute('/screenshots/metrics/$metricId
}), }),
{ status: 500, headers: { 'Content-Type': 'application/json' } } { status: 500, headers: { 'Content-Type': 'application/json' } }
); );
} finally {
await browser.close();
} }
}, },
}); });