fastify-xpdf
fastify-xpdf
PDF generation and manipulation for Fastify 5. Uses Puppeteer (Chrome headless) for HTML/Markdown/URL rendering and pdf-lib for form filling, merging, page extraction, and metadata — with optional automatic upload to S3-compatible storage via @xenterprises/fastify-xstorage.
Installation
npm install @xenterprises/fastify-xpdf
# Optional — required only if useStorage: true
npm install @xenterprises/fastify-xstorage
Quick Start
import Fastify from "fastify";
import xPDF from "@xenterprises/fastify-xpdf";
const fastify = Fastify();
await fastify.register(xPDF, {
format: "A4",
printBackground: true,
margin: { top: "1cm", right: "1cm", bottom: "1cm", left: "1cm" },
});
fastify.get("/reports/:id/pdf", async (request, reply) => {
const html = await renderReportHtml(request.params.id);
const { buffer } = await fastify.xPDF.generateFromHtml(html);
return reply
.header("Content-Type", "application/pdf")
.header("Content-Disposition", 'attachment; filename="report.pdf"')
.send(buffer);
});
await fastify.listen({ port: 3000 });
Options
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
headless | boolean | true | No | Run Puppeteer in headless mode |
args | string[] | ["--no-sandbox", "--disable-setuid-sandbox"] | No | Chrome launch arguments |
useStorage | boolean | false | No | Enable automatic upload to xStorage |
defaultFolder | string | "pdfs" | No | Default storage folder for saved PDFs |
format | string | "A4" | No | Default page format (A4, Letter, A3, A5, Tabloid, etc.) |
printBackground | boolean | true | No | Print background graphics and colours |
margin | object | { top: "1cm", right: "1cm", bottom: "1cm", left: "1cm" } | No | Default page margins (CSS units) |
Methods
All methods are on fastify.xPDF.
Generation (Puppeteer-based):
- generateFromHtml(html, options?) — Convert an HTML string to PDF.
- generateFromMarkdown(markdown, options?) — Convert a Markdown string to PDF.
- generateFromUrl(url, options?) — Render a live URL to PDF with Puppeteer.
Form operations (pdf-lib):
- fillForm(pdfBuffer, fieldValues, options?) — Fill and optionally flatten PDF form fields.
- listFormFields(pdfBuffer) — Enumerate all form fields in a PDF template.
Manipulation (pdf-lib):
- mergePDFs(pdfBuffers, options?) — Merge multiple PDFs into a single document.
- extractPages(pdfBuffer, pageIndices, options?) — Extract specific pages into a new document.
- getPageCount / getMetadata — Get page count or full metadata (title, author, dates, size).
Exported Helpers
Available via import { helpers } from "@xenterprises/fastify-xpdf/helpers":
| Helper | Description |
|---|---|
generatePdfFilename(baseName?) | Generate a unique filename with timestamp |
isValidPdfBuffer(buffer) | Returns true if buffer starts with %PDF header |
getPdfMetadata(buffer) | Returns { size } from a PDF buffer |
formatPdfOptions(options, defaults) | Merge per-call options with plugin defaults |
sanitizeFilename(filename) | Remove unsafe characters and lowercase |
wrapHtmlTemplate(content) | Wrap an HTML fragment in a full styled document |
parseMargin(margin) | Convert string or object margin to Puppeteer format |
getPageFormat(format?) | Return { width, height } in inches for a format name |
saveToStorage(fastify, buffer, filename, folder) | Upload a PDF buffer to xStorage |
Error Reference
All errors use the [xPDF] prefix.
| Error | Cause |
|---|---|
[xPDF] 'headless' option must be a boolean | Non-boolean headless at registration |
[xPDF] 'args' option must be an array of strings | Non-array args at registration |
[xPDF] 'useStorage' option must be a boolean | Non-boolean useStorage |
[xPDF] 'defaultFolder' option must be a string | Non-string defaultFolder |
[xPDF] 'format' option must be a string | Non-string format |
[xPDF] 'printBackground' option must be a boolean | Non-boolean printBackground |
[xPDF] 'margin' option must be an object... | Invalid margin at registration |
[xPDF] HTML content must be a non-empty string | Empty/null HTML in generateFromHtml |
[xPDF] Markdown content must be a non-empty string | Empty/null markdown |
[xPDF] URL must be a non-empty string | Empty/null URL |
[xPDF] URL must be a valid URL | Malformed URL string |
[xPDF] Invalid PDF buffer | Non-PDF buffer passed to manipulation methods |
[xPDF] fieldValues must be an object | Non-object fieldValues in fillForm |
[xPDF] pdfBuffers must be a non-empty array... | Empty/null array in mergePDFs |
[xPDF] One or more invalid PDF buffers provided | Invalid buffer in merge array |
[xPDF] pageIndices must be a non-empty array... | Invalid pageIndices in extractPages |
[xPDF] Each page index must be a non-negative integer | Non-integer or negative index |
[xPDF] Page index N out of range... | Index exceeds PDF page count |
[xPDF] Failed to initialize PDF browser | Puppeteer browser launch failure |
[xPDF] Failed to process PDF during merge | Corrupt PDF encountered during merge |
Environment Variables
| Variable | Required | Description |
|---|---|---|
PUPPETEER_HEADLESS | No | true/false — headless mode (default: true) |
PUPPETEER_ARGS | No | Comma-separated Chrome launch arguments |
PDF_DEFAULT_FORMAT | No | Default page format (default: A4) |
PDF_USE_STORAGE | No | Enable xStorage integration (default: false) |
PDF_DEFAULT_FOLDER | No | Default storage folder (default: pdfs) |
How It Works
The plugin uses two engines. Puppeteer handles HTML, Markdown, and URL-to-PDF generation: a single Chrome browser instance is lazily initialised on the first generation call, reused across requests, and closed via Fastify's onClose hook on shutdown. It auto-reconnects if the browser disconnects. pdf-lib handles all manipulation operations (form filling, merging, page extraction, metadata) in pure JavaScript with no browser. When useStorage: true and @xenterprises/fastify-xstorage is registered on the same Fastify instance, any method accepting saveToStorage: true will upload the result buffer to S3-compatible storage and include storageKey and url in the response. The plugin decorates Fastify with fastify.xPDF with a fastify >= 5.0.0 constraint.
AI Context
package: "@xenterprises/fastify-xpdf"
type: fastify-plugin
use-when: PDF generation from HTML/Markdown/URL via Puppeteer; PDF manipulation (form fill, merge, extract pages, metadata) via pdf-lib
decorator: fastify.xPDF (generateFromHtml, generateFromMarkdown, generateFromUrl, fillForm, listFormFields, mergePDFs, extractPages, getPageCount, getMetadata)
env: PUPPETEER_HEADLESS, PUPPETEER_ARGS, PDF_DEFAULT_FORMAT, PDF_USE_STORAGE, PDF_DEFAULT_FOLDER (all optional)
helper-exports: "@xenterprises/fastify-xpdf/helpers" (generatePdfFilename, isValidPdfBuffer, sanitizeFilename, wrapHtmlTemplate, parseMargin, etc.)
optional-integration: fastify-xstorage — register first if useStorage: true
