Files
2026-05-27 23:29:53 +01:00

11 KiB
Raw Permalink Blame History

@suaveplan/pdf - Server-tier PDF 1.4 generation toolkit (Chunks A–D): typed PDF error registry, Zod boundary schemas, OpenTelemetry counters + histograms, unit conversion, hex/RGB colour utilities, page-size + margin types, hand-rolled PDF 1.4 binary writer (with FlateDecode + AbortSignal + injectable Clock), chainable content-stream encoder, document elements (text / table / image / divider) with Zod boundaries and AbortSignal propagation, style cascade with default theme, block-flow layout engine with header/footer slots, fluent DocumentBuilder, and orchestrating renderDocument entry point round-trippable via pdf-parse.

Server-tier PDF 1.4 generation toolkit. Chunk A foundation — pure utilities + cross-cutting wiring (typed error registry, Zod boundary schemas, OpenTelemetry counters + histograms, unit + colour utilities, page-size + margin types). The low-level writer, element primitives, layout engine, document builder, renderer, templates, and React preview component land in subsequent chunks (B–E). See enterprise-pdf/tasks.md for the chunk roadmap.

Documentation tree

  • colors — Colour utilities for @suaveplan/pdf. The PDF specification stores colours as three floats in the 0-1 range (consu…
    • colors — Colour utilities for @suaveplan/pdf. The PDF specification stores colours as three floats in the 0-1 range (consu…
  • content-stream — ContentStreamEncoder is the chainable builder for PDF 1.4 content streams used by every page emitted by `@suaveplan/p…
    • content-stream — ContentStreamEncoder is the chainable builder for PDF 1.4 content streams used by every page emitted by `@suaveplan/p…
  • divider-element — DividerElement renders a horizontal or vertical rule into a PDF content stream. It is the lightweight separator primi…
    • divider-element — DividerElement renders a horizontal or vertical rule into a PDF content stream. It is the lightweight separator primi…
  • document-builder — The DocumentBuilder provides a chainable, deterministic API for assembling a PDF document tree without touching the l…
    • document-builder — The DocumentBuilder provides a chainable, deterministic API for assembling a PDF document tree without touching the l…
  • error-codes — Declares the stable PDF.* error-code registry and the PdfError class used by every public function in `@suaveplan/p…
    • error-codes — Declares the stable PDF.* error-code registry and the PdfError class used by every public function in `@suaveplan/p…
  • image-element — ImageElement is the bitmap primitive of @suaveplan/pdf. It accepts raw JPEG or PNG bytes, decodes them at construct…
    • image-element — ImageElement is the bitmap primitive of @suaveplan/pdf. It accepts raw JPEG or PNG bytes, decodes them at construct…
  • image-registry — The ImageRegistry allocates and reuses PDF Image XObjects across the lifetime of a single renderDocument call. Each…
    • image-registry — The ImageRegistry allocates and reuses PDF Image XObjects across the lifetime of a single renderDocument call. Each…
  • layout-engine — The LayoutEngine owns the block-flow geometry the renderer walks to position each element on the page. It computes ef…
    • layout-engine — The LayoutEngine owns the block-flow geometry the renderer walks to position each element on the page. It computes ef…
  • pdf-writer — PdfWriter is the low-level binary writer that emits valid PDF 1.4 byte streams. It manages indirect-object allocation…
    • pdf-writer — PdfWriter is the low-level binary writer that emits valid PDF 1.4 byte streams. It manages indirect-object allocation…
  • render-pipeline — Internal pipeline helpers that the top-level renderDocument orchestrator delegates to. Splitting placement and slot-r…
    • render-pipeline — Internal pipeline helpers that the top-level renderDocument orchestrator delegates to. Splitting placement and slot-r…
  • renderer — renderDocument is the top-level orchestrator that turns a Document AST (produced by DocumentBuilder) into a real…
    • renderer — renderDocument is the top-level orchestrator that turns a Document AST (produced by DocumentBuilder) into a real…
  • schemas — Zod boundary schemas for the public surface of @suaveplan/pdf. Every value crossing the package boundary from untrust…
    • schemas — Zod boundary schemas for the public surface of @suaveplan/pdf. Every value crossing the package boundary from untrust…
  • style-resolver — The StyleResolver resolves a fully-populated PdfStyle from the package defaults, an active theme, an optional base…
    • style-resolver — The StyleResolver resolves a fully-populated PdfStyle from the package defaults, an active theme, an optional base…
  • table-element — TableElement is the tabular-data primitive of @suaveplan/pdf. It accepts a typed column definition + row array and…
    • table-element — TableElement is the tabular-data primitive of @suaveplan/pdf. It accepts a typed column definition + row array and…
  • telemetry — OpenTelemetry surface for @suaveplan/pdf. PDF generation is a load-bearing primitive in any system that emits invoice…
    • telemetry — OpenTelemetry surface for @suaveplan/pdf. PDF generation is a load-bearing primitive in any system that emits invoice…
  • invoice-template — createInvoiceTemplate(data, options?) converts a typed InvoiceData payload into a renderer-ready Document for pro…
    • invoice-template — createInvoiceTemplate(data, options?) converts a typed InvoiceData payload into a renderer-ready Document for pro…
  • receipt-template — createReceiptTemplate(data, options?) converts a typed ReceiptData payload into a renderer-ready Document for com…
    • receipt-template — createReceiptTemplate(data, options?) converts a typed ReceiptData payload into a renderer-ready Document for com…
  • report-template — createReportTemplate(data, options?) converts a typed ReportData payload into a renderer-ready Document for multi…
    • report-template — createReportTemplate(data, options?) converts a typed ReportData payload into a renderer-ready Document for multi…
  • text-element — TextElement is the flowed-text primitive of @suaveplan/pdf. It accepts a content string plus typography options (fo…
    • text-element — TextElement is the flowed-text primitive of @suaveplan/pdf. It accepts a content string plus typography options (fo…
  • types — Defines the page-size + page-config primitives used across every other module in @suaveplan/pdf. PDF measurements are…
    • page-size — Defines the page-size + page-config primitives used across every other module in @suaveplan/pdf. PDF measurements are…
  • units — Unit-conversion utilities for @suaveplan/pdf. PDF's native measurement is the point (1pt = 1/72 inch); every co…
    • units — Unit-conversion utilities for @suaveplan/pdf. PDF's native measurement is the point (1pt = 1/72 inch); every co…

Install

bun add @suaveplan/pdf

Surface (Chunk A)

Subpath Symbols
@suaveplan/pdf/error-codes PDF_CODES, PdfError, asPdfError, PdfErrorCode
@suaveplan/pdf/schemas UnitSchema, HexColorSchema, RgbColorSchema, MarginsSchema, PageConfigSchema, DocumentMetadataSchema, parseOrThrow, parseHexColor
@suaveplan/pdf/telemetry createPdfObservability, six record* helpers, PdfObservability
@suaveplan/pdf/units Unit, toPoints, fromPoints, convert, parseUnit, formatUnit
@suaveplan/pdf/colors RgbColor, PdfColor, hexToRgb, rgbToPdfColor, hexToPdfColor, rgbToHex, lighten, darken, COLORS, isTransparent
@suaveplan/pdf/types PageSize, PAGE_DIMENSIONS, Margins, DEFAULT_MARGINS, DocumentMetadata, PageConfig, DEFAULT_PAGE_CONFIG, DocumentDefinition, PageDefinition, ElementNode

The package barrel @suaveplan/pdf re-exports every symbol above.

Example

import {
    convert,
    hexToPdfColor,
    parseOrThrow,
    PageConfigSchema,
    PAGE_DIMENSIONS,
    PageSize,
    PDF_CODES,
} from "@suaveplan/pdf";

const a4 = PAGE_DIMENSIONS[PageSize.A4];
const inchInMm = convert(1, "in", "mm"); // ≈ 25.4
const accent = hexToPdfColor("#3366cc"); // PDF-native 0-1 triple

const page = parseOrThrow(
    PageConfigSchema,
    requestBody.page,
    PDF_CODES.INVALID_PAGE_CONFIG,
    "bad page config"
);

Dependencies

  • @suaveplan/error — typed-error base.
  • @suaveplan/opentelemetry — counter / histogram helpers.
  • @suaveplan/types — shared Clock etc. for later chunks.
  • @opentelemetry/api — meter / tracer global API.
  • zod — boundary validation.
  • tslib — runtime helpers.

No third-party PDF dependency. Chunk B will keep the hand-rolled PDF 1.4 writer the upstream package ships with — the spec is small enough that shipping a custom 200 LOC implementation is preferable to pulling in pdfkit (~600 KB unpacked, CommonJS-only, includes unrelated PNG and font subsystems).

Roadmap

  • Chunk B — pdf-writer/, content-stream/ (low-level binary writer + content stream encoder).
  • Chunk C — text-element/, table-element/, image-element/, divider-element/.
  • Chunk D — layout-engine/, style-resolver/, document-builder/, renderer/.
  • Chunk E — invoice-template/, receipt-template/, report-template/, pdf-preview/ (React).

Quality gate

bunx turbo lint typecheck test build --filter=@suaveplan/pdf
bunx turbo test:coverage --filter=@suaveplan/pdf

100 / 100 / 100 / 100 Istanbul coverage on every Chunk A module.