You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sims-hq/apps/hq/src/pdf.ts

34 lines
1.1 KiB
TypeScript

import puppeteer, { type Browser } from 'puppeteer'
/**
* HTML → PDF via puppeteer. The browser is a lazy module-level singleton:
* launch costs ~1s, so it starts on first render and is reused after.
* Guarding with a promise (not the Browser) makes concurrent first calls
* share one launch instead of racing two Chromes.
*/
let browserPromise: Promise<Browser> | null = null
function getBrowser(): Promise<Browser> {
browserPromise ??= puppeteer.launch()
return browserPromise
}
export async function renderPdf(html: string): Promise<Buffer> {
const page = await (await getBrowser()).newPage()
try {
await page.setContent(html, { waitUntil: 'load' })
const bytes = await page.pdf({ format: 'A4', printBackground: true })
return Buffer.from(bytes)
} finally {
await page.close()
}
}
/** For tests/scripts that must let the process exit; the server never calls it. */
export async function closePdfBrowser(): Promise<void> {
if (browserPromise === null) return
const b = await browserPromise
browserPromise = null
await b.close()
}