#!/usr/bin/env ts-node /** * Master Brochure Generator * * Generates a multi-page PDF brochure containing all products. * Combines Payload CMS marketing text with Excel technical data. */ import * as fs from 'fs'; import * as path from 'path'; import * as React from 'react'; import { renderToBuffer } from '@react-pdf/renderer'; import { getAllProducts } from '../lib/products'; import { getExcelTechnicalDataForProduct, preloadExcelData } from '../lib/excel-products'; import { PDFBrochure } from '../lib/pdf-brochure'; import { ProductData as PDFProductData } from '../lib/pdf-datasheet'; const CONFIG = { outputDir: path.join(process.cwd(), 'public/downloads'), locales: ['en', 'de'] as const, } as const; async function ensureOutputDir() { if (!fs.existsSync(CONFIG.outputDir)) { fs.mkdirSync(CONFIG.outputDir, { recursive: true }); } } async function generateBrochure(locale: 'en' | 'de') { console.log(`\nGenerating brochure for locale: ${locale.toUpperCase()}...`); // 1. Load data const products = await getAllProducts(locale); console.log(`- Loaded ${products.length} products from Payload`); // 2. Map and Enrich const pdfProducts: PDFProductData[] = products.map((p, index) => { const excelData = getExcelTechnicalDataForProduct({ slug: p.slug, sku: p.frontmatter.sku, name: p.frontmatter.title, }); return { id: index + 1, name: p.frontmatter.title, sku: p.frontmatter.sku, shortDescriptionHtml: p.frontmatter.description, descriptionHtml: p.frontmatter.description, applicationHtml: '', featuredImage: p.frontmatter.images[0] || null, images: p.frontmatter.images, categories: p.frontmatter.categories.map(name => ({ name })), attributes: excelData?.attributes || [], }; }); if (pdfProducts.length === 0) { console.warn(`! No products found for ${locale}. Skipping.`); return; } // 3. Render console.log(`- Rendering PDF with ${pdfProducts.length} pages...`); const buffer = await renderToBuffer( React.createElement(PDFBrochure, { products: pdfProducts, locale, title: locale === 'de' ? 'Produktkatalog' : 'Product Catalog', subtitle: '2026', }) ); // 4. Save const fileName = `KLZ_Cables_Brochure_2026_${locale.toUpperCase()}.pdf`; const filePath = path.join(CONFIG.outputDir, fileName); fs.writeFileSync(filePath, buffer); const stats = fs.statSync(filePath); console.log(`āœ“ Generated: ${fileName} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`); } async function main() { const start = Date.now(); console.log('--- KLZ Brochure Generator ---'); try { await ensureOutputDir(); preloadExcelData(); for (const locale of CONFIG.locales) { await generateBrochure(locale); } console.log(`\nāœ… Brochure generation completed in ${((Date.now() - start) / 1000).toFixed(2)}s`); } catch (error) { console.error('\nāŒ Fatal error:', error); process.exit(1); } } main().catch(console.error);