import puppeteer from 'puppeteer-core'; import type { ApiResponse } from '@/types/api'; import type { Slide } from '@/types/carousel'; export interface RenderRequest { slides: Slide[]; template: string; palette: string; variant?: string; } export interface RenderResult { images: string[]; format: string; } // OS-specific chromium paths const CHROMIUM_PATHS: Record = { win32: [ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', 'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe' ], linux: [ '/usr/bin/chromium', '/usr/bin/chromium-browser', '/usr/bin/google-chrome' ], darwin: [ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' ] }; function getExecutablePath(): string | undefined { const platform = process.platform as string; const paths = CHROMIUM_PATHS[platform] || CHROMIUM_PATHS.linux; const fs = require('fs'); for (const p of paths) { if (fs.existsSync(p)) return p; } return undefined; } const PALETTE_COLORS: Record = { blue: { bg: '#2563eb', text: '#ffffff' }, green: { bg: '#16a34a', text: '#ffffff' }, orange: { bg: '#ea580c', text: '#ffffff' }, purple: { bg: '#9333ea', text: '#ffffff' }, mono: { bg: '#111827', text: '#ffffff' }, }; function buildSlideHTML(slide: Slide, palette: string, index: number, total: number): string { const colors = PALETTE_COLORS[palette] || PALETTE_COLORS.blue; return `
${slide.headline}
${slide.body}
${slide.cta ? `
${slide.cta}
` : ''} `; } export async function renderCarousel(req: RenderRequest): Promise> { let browser; try { const executablePath = getExecutablePath(); if (!executablePath) { throw new Error('Chromium executable not found. Install Chrome/Chromium.'); } browser = await puppeteer.launch({ executablePath, args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] }); const page = await browser.newPage(); await page.setViewport({ width: 1080, height: 1080 }); const images: string[] = []; for (let i = 0; i < req.slides.length; i++) { const slide = req.slides[i]; const html = buildSlideHTML(slide, req.palette, i, req.slides.length); await page.setContent(html, { waitUntil: 'load' }); const buffer = await page.screenshot({ type: 'png' }); images.push('data:image/png;base64,' + buffer.toString('base64')); } await browser.close(); return { success: true, data: { images, format: 'png' }, }; } catch (error) { if (browser) await browser.close(); console.error('[render] puppeteer failed:', error); const msg = error instanceof Error ? error.message : String(error); return { success: false, error: \`Failed to render images: \${msg}\`, }; } }