Leon4gr45/builder
0
1/**2 * Deployment Thumbnail Capture Utility3 * Captures a screenshot of a published deployment via a hidden iframe.4 * Returns a base64 data URL -- caller is responsible for persisting.5 */6 7import { captureIframeScreenshot, waitForResources } from './screenshot';8 9export interface DeploymentCaptureOptions {10 captureWidth?: number;11 captureHeight?: number;12 outputWidth?: number;13 outputHeight?: number;14 quality?: number;15 timeout?: number;16}17 18const DEFAULTS: Required<DeploymentCaptureOptions> = {19 captureWidth: 1280,20 captureHeight: 720,21 outputWidth: 640,22 outputHeight: 360,23 quality: 0.8,24 timeout: 15000,25};26 27/**28 * Capture a screenshot of a published deployment URL.29 * @returns base64 data URL, or null on failure30 */31export async function captureDeploymentScreenshot(32 deploymentUrl: string,33 options: DeploymentCaptureOptions = {}34): Promise<string | null> {35 const opts = { ...DEFAULTS, ...options };36 37 return new Promise((resolve) => {38 const iframe = document.createElement('iframe');39 iframe.style.position = 'fixed';40 iframe.style.top = '-10000px';41 iframe.style.left = '-10000px';42 iframe.style.width = `${opts.captureWidth}px`;43 iframe.style.height = `${opts.captureHeight}px`;44 iframe.style.border = 'none';45 iframe.src = deploymentUrl;46 47 let timeoutId: number | null = null;48 let resolved = false;49 50 const cleanup = () => {51 if (timeoutId) clearTimeout(timeoutId);52 if (iframe.parentElement) document.body.removeChild(iframe);53 };54 55 const done = (result: string | null) => {56 if (resolved) return;57 resolved = true;58 cleanup();59 resolve(result);60 };61 62 timeoutId = window.setTimeout(() => done(null), opts.timeout);63 64 iframe.onload = async () => {65 try {66 if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; }67 timeoutId = window.setTimeout(() => done(null), 12000);68 69 try {70 const doc = iframe.contentDocument || iframe.contentWindow?.document;71 if (doc) await waitForResources(doc, 2500, 8000);72 else await new Promise(r => setTimeout(r, 2500));73 } catch {74 await new Promise(r => setTimeout(r, 2500));75 }76 77 const screenshot = await captureIframeScreenshot(78 iframe,79 opts.captureWidth,80 opts.captureHeight,81 opts.outputWidth,82 opts.outputHeight,83 opts.quality,84 false85 );86 87 done(screenshot);88 } catch {89 done(null);90 }91 };92 93 iframe.onerror = () => done(null);94 document.body.appendChild(iframe);95 });96}97 