X Enterprises
fastify-xpdf

PDF Helpers

Standalone utility functions for filename generation, buffer validation, option merging, HTML templating, margin parsing, and storage upload — importable from the xpdf helpers sub-path.

PDF Helpers

Imported from @xenterprises/fastify-xpdf/helpers. These helpers are used internally by the plugin's generation and manipulation methods but are also available for standalone use — e.g. in preprocessing pipelines, custom route handlers, or test fixtures.

Usage

import {
  generatePdfFilename,
  isValidPdfBuffer,
  getPdfMetadata,
  formatPdfOptions,
  sanitizeFilename,
  wrapHtmlTemplate,
  parseMargin,
  getPageFormat,
  saveToStorage,
} from '@xenterprises/fastify-xpdf/helpers'

Functions

generatePdfFilename(baseName?)

Generate a unique PDF filename with a millisecond timestamp suffix.

Parameters:

NameTypeRequiredDescription
baseNamestringNoBase name without extension. Defaults to "document".

Returns: string — e.g. "report-1719856800000.pdf".


isValidPdfBuffer(buffer)

Check whether a buffer begins with the %PDF magic bytes.

Parameters:

NameTypeRequiredDescription
bufferBufferYesBuffer to inspect.

Returns: booleantrue if the buffer starts with %PDF.


getPdfMetadata(buffer)

Extract basic metadata from a PDF buffer.

Parameters:

NameTypeRequiredDescription
bufferBufferYesValid PDF buffer.

Returns: { size: number }size is the byte length of the buffer.


formatPdfOptions(options, defaults)

Merge per-call PDF options with plugin-level defaults, with per-call values taking precedence. margin is deep-merged so partial margin overrides keep the remaining defaults.

Parameters:

NameTypeRequiredDescription
optionsobjectYesPer-call options (any subset of Puppeteer PDF options).
defaultsobjectYesPlugin-level default options to fall back to.

Returns: object — Merged options object.


sanitizeFilename(filename)

Replace unsafe characters with underscores and lowercase the result.

Parameters:

NameTypeRequiredDescription
filenamestringYesRaw filename string.

Returns: string — Sanitized, lowercased filename safe for use in storage keys and Content-Disposition headers.


wrapHtmlTemplate(content)

Wrap an HTML fragment in a complete, styled HTML document suitable for Puppeteer rendering.

Parameters:

NameTypeRequiredDescription
contentstringYesHTML fragment or full body content.

Returns: string — A complete <!DOCTYPE html> document with base styles applied.


parseMargin(margin)

Convert a margin value — string shorthand or object — to the object format Puppeteer expects.

Parameters:

NameTypeRequiredDescription
marginstring | { top?, right?, bottom?, left? }YesMargin shorthand (e.g. "1cm") or an object with individual sides.

Returns: { top: string; right: string; bottom: string; left: string }


getPageFormat(format?)

Resolve a named page format to its width and height in inches.

Parameters:

NameTypeRequiredDescription
formatstringNoFormat name: "A4", "Letter", "A3", "A5", "Tabloid", etc. Defaults to "A4" (also the fallback for unknown names).

Returns: { width: number; height: number } — Dimensions in inches.


saveToStorage(fastify, buffer, filename, folder)

Upload a PDF buffer to xStorage (fastify.xStorage). Returns null when @xenterprises/fastify-xstorage is not registered on the instance; upload failures are logged (message only) and re-thrown.

Note: the plugin's own methods (generateFromHtml, fillForm, etc.) guard their per-call saveToStorage: true option and throw an actionable error when xStorage is missing — calling this helper directly does not. Prefer the plugin methods when possible.

Parameters:

NameTypeRequiredDescription
fastifyFastifyInstanceYesThe Fastify instance with xStorage decorated.
bufferBufferYesPDF buffer to upload.
filenamestringYesDestination filename (used as storage key base).
folderstringYesStorage folder prefix (e.g. "pdfs", "reports/2024").

Returns: Promise<{ storageKey: string; url: string } | null>null when xStorage is not registered.


Examples

Generate a safe filename for a report

import { generatePdfFilename, sanitizeFilename } from '@xenterprises/fastify-xpdf/helpers'

const base = sanitizeFilename('Q1 Revenue Report')
// "q1_revenue_report"

const filename = generatePdfFilename(base)
// "q1_revenue_report-1719856800000.pdf"

Validate a buffer before manipulating

import { isValidPdfBuffer } from '@xenterprises/fastify-xpdf/helpers'

fastify.post('/merge', async (request, reply) => {
  const data = await request.file()
  const buffer = await data.toBuffer()

  if (!isValidPdfBuffer(buffer)) {
    return reply.status(400).send({ error: 'Uploaded file is not a valid PDF' })
  }

  const merged = await fastify.xPdf.mergePDFs([existingBuffer, buffer])
  return reply.type('application/pdf').send(merged.buffer)
})

Wrap markdown-converted HTML before rendering

import { wrapHtmlTemplate, parseMargin } from '@xenterprises/fastify-xpdf/helpers'
import { marked } from 'marked'

const html = wrapHtmlTemplate(marked(markdownContent))
const margin = parseMargin('2cm')
// { top: "2cm", right: "2cm", bottom: "2cm", left: "2cm" }

const { buffer } = await fastify.xPdf.generateFromHtml(html, { margin })

Upload a generated PDF directly to storage

import { generatePdfFilename, saveToStorage } from '@xenterprises/fastify-xpdf/helpers'

fastify.post('/invoices/:id/pdf', async (request, reply) => {
  const html = await buildInvoiceHtml(request.params.id)
  const { buffer } = await fastify.xPdf.generateFromHtml(html)

  const filename = generatePdfFilename(`invoice-${request.params.id}`)
  const result = await saveToStorage(fastify, buffer, filename, 'invoices')
  if (!result) {
    return reply.status(503).send({ error: 'Storage is not configured' })
  }

  return reply.send({ url: result.url, key: result.storageKey })
})

Get page dimensions for a custom layout

import { getPageFormat, formatPdfOptions } from '@xenterprises/fastify-xpdf/helpers'

const dims = getPageFormat('A5')
// { width: 5.83, height: 8.27 }

const merged = formatPdfOptions(
  { printBackground: false },
  { format: 'A5', margin: { top: '1cm', right: '1cm', bottom: '1cm', left: '1cm' }, printBackground: true }
)
// printBackground: false wins; format and margin from defaults

See also


AI Context

import: "@xenterprises/fastify-xpdf/helpers"
use-when: >
  When you need PDF utility functions outside of the plugin's main methods —
  e.g. validating uploaded PDFs before processing, generating unique filenames,
  wrapping HTML fragments before passing to generateFromHtml, or uploading
  PDF buffers directly to xStorage.
functions:
  - generatePdfFilename: Unique timestamped filename (baseName-Date.now().pdf)
  - isValidPdfBuffer: Check %PDF header
  - getPdfMetadata: Returns { size } from buffer
  - formatPdfOptions: Merge per-call options with plugin defaults (deep-merges margin)
  - sanitizeFilename: Replace unsafe chars with underscores and lowercase
  - wrapHtmlTemplate: Wrap HTML fragment in full styled document
  - parseMargin: Convert string/object margin to Puppeteer format
  - getPageFormat: Resolve format name to { width, height } in inches (falls back to A4)
  - saveToStorage: Upload buffer to fastify.xStorage — returns null when xStorage is not registered, re-throws upload errors
Copyright © 2026