npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sme.up/doc-alchemist

v1.8.0-SNAPSHOT-20260206155450

Published

Library for generating documents in various formats, including Excel and PDF.

Readme

Doc Alchemist

A powerful TypeScript library for generating documents in various formats (PDF, Excel) with advanced support for data transformation, charts, and complex layouts.

Quick Start

import {
  pdfmakeDocumentToPdfData,
  WebupManagerData,
} from "@sme.up/doc-alchemist";
import { SmeupDataStructureType } from "@sme.up/doc-alchemist";

const webupManagerData: WebupManagerData = {
  mathLocale: "it-IT",
  datesLocale: "it-IT",
  themeBackground: "",
};

const doc = {
  content: [{ text: "Hello World", fontSize: 20, bold: true }],
};

const pdf = await pdfmakeDocumentToPdfData(doc, { webupManagerData });
await fs.writeFile("output.pdf", pdf);

Installation

npm install @sme.up/doc-alchemist

Features

  • PDF Generation with pdfmake integration
  • Excel Export from SmeUP data structures
  • Chart Generation (line, bar, pie)
  • Form Filling for existing PDFs
  • Data Transformation from SmeUP formats
  • Advanced Layouts with columns and boxes

PDF Generation Examples

Simple PDF from SmeUP DataTable

For quick PDF generation from a SmeUP DataTable without complex layouts, use dataTableToPdfData:

import { dataTableToPdfData } from "@sme.up/doc-alchemist";
import { SmeupDataStructureType } from "@sme.up/doc-alchemist";

const dataTable = {
  type: SmeupDataStructureType.SmeupDataTable,
  columns: [
    { name: "col1", title: "Product", visible: true, obj: { t: "", p: "" } },
    { name: "col2", title: "Quantity", visible: true, obj: { t: "NR", p: "" } },
    { name: "col3", title: "Price", visible: true, obj: { t: "NR", p: "" } },
  ],
  rows: [
    {
      cells: {
        col1: { value: "Product A", obj: { t: "", p: "", k: "Product A" } },
        col2: { value: "10", obj: { t: "NR", p: "", k: "10" } },
        col3: { value: "25.50", obj: { t: "NR", p: "", k: "25.50" } },
      },
    },
    {
      cells: {
        col1: { value: "Product B", obj: { t: "", p: "", k: "Product B" } },
        col2: { value: "5", obj: { t: "NR", p: "", k: "5" } },
        col3: { value: "45.00", obj: { t: "NR", p: "", k: "45.00" } },
      },
    },
  ],
  cover: {
    titles: {
      T01: "Sales Report",
      T02: "Q4 2023",
      T03: "Confidential",
    },
  },
};

const component = {
  smeupDataTable: dataTable,
  props: {},
};

const pdf = await dataTableToPdfData(component, webupManagerData);
await fs.writeFile("simple-table.pdf", pdf);

Generates a PDF with automatic table formatting, cover page with title/subtitle, and built-in styling using jsPDF.

Tables from SmeUP Data

For advanced layouts and customization, use pdfmakeDocumentToPdfData:

import { pdfmakeDocumentToPdfData } from "@sme.up/doc-alchemist";
import { SmeupDataStructureType } from "@sme.up/doc-alchemist";

const dataTable = {
  type: SmeupDataStructureType.SmeupDataTable,
  columns: [
    { name: "col1", title: "Name" },
    { name: "col2", title: "Description" },
    { name: "col3", title: "Status" },
    { name: "col4", title: "Date", obj: { t: "D8", p: "*YYMD" } },
    { name: "col5", title: "Amount", obj: { t: "NR", p: "" } },
  ],
  rows: [
    {
      cells: {
        col1: { value: "Item 1" },
        col2: { value: "First item description" },
        col3: { value: "Active" },
        col4: {
          value: "2023-11-15",
          obj: { t: "D8", p: "*YYMD", k: "20231115" },
        },
        col5: { value: "1250.50", obj: { t: "NR", p: "", k: "1250.50" } },
      },
    },
    {
      cells: {
        col1: { value: "Item 2" },
        col2: { value: "Second item description" },
        col3: { value: "Pending" },
        col4: {
          value: "2023-11-20",
          obj: { t: "D8", p: "*YYMD", k: "20231120" },
        },
        col5: { value: "3450.75", obj: { t: "NR", p: "", k: "3450.75" } },
      },
    },
  ],
};

const doc = {
  content: [
    { text: "Data in SmeUP format", fontSize: 20, bold: true },
    {
      table: {
        smeup: {
          data: dataTable,
        },
      },
      layout: "lightHorizontalLines",
    },
  ],
};

const pdf = await pdfmakeDocumentToPdfData(doc, { webupManagerData });
await fs.writeFile("table-output.pdf", pdf);

Generates a formatted table from SmeUP data structure with automatic column detection, date formatting, and number formatting.

Tables from FUN

const doc = {
  content: [
    { text: "Data retrieved from FUN", fontSize: 20, bold: true },
    {
      table: {
        smeup: {
          fun: "F(EXB;SERV;MET)",
        },
      },
      layout: "lightHorizontalLines",
    },
  ],
};

const context = {
  webupManagerData,
  getSmeupDataStructure: async (fun: string) => {
    // Your implementation to fetch data based on FUN
    return await fetchDataFromServer(fun);
  },
};

const pdf = await pdfmakeDocumentToPdfData(doc, context);
await fs.writeFile("fun-table.pdf", pdf);

Dynamically retrieves data using FUN expressions and renders it as a table.

Images in PDF

const doc = {
  content: [
    {
      table: {
        body: [
          ["Image from URL", "Image from Object"],
          [
            {
              stack: [
                {
                  image: {
                    smeup: {
                      url: "https://picsum.photos/seed/picsum/200/300",
                    },
                  },
                  width: 200,
                },
                { text: "URL-based image", margin: [0, 5, 0, 0] },
              ],
            },
            {
              stack: [
                {
                  image: {
                    smeup: {
                      obj: { t: "CN", p: "COL", k: "LANSTS" },
                    },
                  },
                },
                { text: "SmeUP object image", margin: [0, 5, 0, 0] },
              ],
            },
          ],
        ],
      },
    },
  ],
};

const pdf = await pdfmakeDocumentToPdfData(doc, {
  webupManagerData,
  fetchData: fetch,
  damSvcEndpoint: "https://your-dam-service.com",
});
await fs.writeFile("images.pdf", pdf);

Supports images from HTTP(S) URLs and SmeUP object references with automatic fetching and embedding.

Headers and Footers with Page Numbers

const doc = {
  styles: {
    header: { fontSize: 18, bold: true },
    footer: { fontSize: 8, italics: true },
  },
  header: {
    columns: [
      { text: "Document Title", alignment: "left", style: "header" },
      {
        text: "Page [CurrentPage] of [PageCount]",
        alignment: "right",
        fontSize: 10,
      },
    ],
    margin: [40, 20, 40, 10],
  },
  footer: {
    columns: [
      {
        text: "Generated on " + new Date().toLocaleDateString(),
        alignment: "left",
        fontSize: 8,
      },
      {
        text: "[CurrentPage]/[PageCount]",
        alignment: "right",
        fontSize: 8,
      },
    ],
    margin: [40, 10, 40, 20],
  },
  content: [
    { text: "This is the first page.", pageBreak: "after" },
    { text: "This is the second page", pageBreak: "after" },
    { text: "This is the third page." },
  ],
  pageMargins: [40, 60, 40, 60],
};

const pdf = await pdfmakeDocumentToPdfData(doc, { webupManagerData });
await fs.writeFile("header-footer.pdf", pdf);

Automatically replaces [CurrentPage] and [PageCount] placeholders with actual page numbers.

Custom Table Layouts

const doc = {
  content: [
    { text: "Table with Custom Layout", fontSize: 20, bold: true },
    {
      table: {
        headerRows: 1,
        body: [
          [
            { text: "Header 1", bold: true, fillColor: "#CCCCCC" },
            { text: "Header 2", bold: true, fillColor: "#CCCCCC" },
            { text: "Header 3", bold: true, fillColor: "#CCCCCC" },
          ],
          ["Row 1, Cell 1", "Row 1, Cell 2", "Row 1, Cell 3"],
          ["Row 2, Cell 1", "Row 2, Cell 2", "Row 2, Cell 3"],
          ["Row 3, Cell 1", "Row 3, Cell 2", "Row 3, Cell 3"],
        ],
      },
      layout: {
        hLineWidth: 2,
        vLineWidth: 1,
        hLineColor: "#0000FF",
        vLineColor: "#FF0000",
      },
    },
  ],
};

const pdf = await pdfmakeDocumentToPdfData(doc, { webupManagerData });
await fs.writeFile("custom-layout.pdf", pdf);

Creates tables with custom border colors, widths, and cell styling.

Charts in PDF

import { ChartType, ChartOptions } from "@sme.up/doc-alchemist";

const doc = {
  content: [
    { text: "Sales Report with Charts", fontSize: 20, bold: true },

    // Line Chart
    {
      chart: {
        smeup: {
          fun: "F(EXA;SERV;MET)",
          options: {
            Typ: ChartType.LINE,
            Series: "VALORI|VALCAL",
            Title: "Monthly Values Chart",
            ForceWidth: "500",
            ForceHeight: "300",
          } as ChartOptions,
        },
      },
      margin: [0, 0, 0, 20],
    },

    // Bar Chart
    {
      chart: {
        smeup: {
          fun: "F(EXA;SERV;MET)",
          options: {
            Typ: ChartType.BAR,
            Series: "VALORI|VALCAL",
            Title: "Monthly Values Chart",
            ForceWidth: "500",
            ForceHeight: "300",
          } as ChartOptions,
        },
      },
      margin: [0, 0, 0, 20],
    },

    // Pie Chart
    {
      chart: {
        smeup: {
          fun: "F(EXA;SERV;MET)",
          options: {
            Typ: ChartType.PIE,
            Series: "VALORI",
            Title: "Monthly Values Chart",
            ForceWidth: "500",
            ForceHeight: "300",
          } as ChartOptions,
        },
      },
    },
  ],
};

const context = {
  webupManagerData,
  getSmeupDataStructure: async (fun: string) => {
    return await fetchChartData(fun);
  },
};

const pdf = await pdfmakeDocumentToPdfData(doc, context);
await fs.writeFile("charts.pdf", pdf);

Generates line, bar, and pie charts as SVG images embedded in PDF documents.

Box Layouts

import { BoxOptions } from "@sme.up/doc-alchemist";

const doc = {
  content: [
    // Single Column Layout
    { text: "Single column with default layout", fontSize: 14, bold: true },
    {
      box: {
        smeup: {
          fun: "F(EXB;SERV;MET)",
          options: {
            Columns: "col1|col2|col3|col4|col5",
            Cols: "1",
          } as BoxOptions,
        },
      },
      margin: [0, 0, 0, 20],
    },

    // Three Column Layout
    { text: "Three columns layout", fontSize: 14, bold: true },
    {
      box: {
        smeup: {
          fun: "F(EXB;SERV;MET)",
          options: {
            Columns: "col1|col4|col5",
            Cols: "3",
            LayoutNbr: "2",
          } as BoxOptions,
        },
      },
      margin: [0, 0, 0, 20],
    },

    // Two Column Layout with Images
    { text: "Two columns with images", fontSize: 14, bold: true },
    {
      box: {
        smeup: {
          fun: "F(EXB;SERV;MET)",
          options: {
            Columns: "img|col1|col4|col5",
            Cols: "2",
            LayoutNbr: "5",
          } as BoxOptions,
        },
      },
    },
  ],
  styles: {
    box__label: { fontSize: 10, color: "#990000" },
    box__value: { fontSize: 10, bold: true },
  },
};

const pdf = await pdfmakeDocumentToPdfData(doc, context);
await fs.writeFile("box-layout.pdf", pdf);

Creates flexible box layouts with 1, 2, or 3 columns, supporting different layout patterns and image integration.

Cell Styling in Tables

const dataTable = {
  type: SmeupDataStructureType.SmeupDataTable,
  columns: [
    { name: "col1", title: "Product" },
    { name: "col2", title: "Status" },
  ],
  rows: [
    {
      cells: {
        col1: {
          value: "Item 1",
          styleAttributes: {
            FontULine: "Yes",
            FontBold: "Yes",
            FontItalic: "Yes",
            FontColor: "R000G000B150",
            BackColor: "R173G219B239",
          },
        },
        col2: { value: "Active" },
      },
    },
  ],
};

const doc = {
  content: [
    {
      table: {
        smeup: { data: dataTable },
      },
    },
  ],
};

const pdf = await pdfmakeDocumentToPdfData(doc, { webupManagerData });
await fs.writeFile("styled-table.pdf", pdf);

Applies custom styling to individual cells including colors, bold, italic, and underline.


Excel Export

Export SmeUP DataTable to Excel

import { dataTableToExcelData } from "@sme.up/doc-alchemist";

const dataTable = {
  type: SmeupDataStructureType.SmeupDataTable,
  columns: [
    { name: "col1", title: "Name" },
    { name: "col2", title: "Value" },
  ],
  rows: [
    { cells: { col1: { value: "Item 1" }, col2: { value: "100" } } },
    { cells: { col1: { value: "Item 2" }, col2: { value: "200" } } },
  ],
};

const excelBuffer = await dataTableToExcelData(
  dataTable,
  webupManagerData,
  "Sheet1",
);

await fs.writeFile("output.xlsx", excelBuffer);

Export SmeUP DataTree to Excel

import { dataTreeToExcelData } from "@sme.up/doc-alchemist";

const dataTree = {
  type: SmeupDataStructureType.SmeupDataTree,
  columns: [
    { name: "col1", title: "Category" },
    { name: "col2", title: "Count" },
  ],
  children: [
    {
      value: "Parent 1",
      cells: { col1: { value: "Parent 1" }, col2: { value: "10" } },
      children: [
        {
          value: "Child 1.1",
          cells: { col1: { value: "Child 1.1" }, col2: { value: "5" } },
          children: [],
        },
      ],
    },
  ],
};

const excelBuffer = await dataTreeToExcelData(
  dataTree,
  webupManagerData,
  "TreeSheet",
);

await fs.writeFile("tree.xlsx", excelBuffer);

Exports hierarchical tree structures to Excel with proper indentation.


Chart Generation

Generate Chart as SVG

import { dataTableToChart } from "@sme.up/doc-alchemist";
import { ChartType } from "@sme.up/doc-alchemist";

const chartData = {
  type: SmeupDataStructureType.SmeupDataTable,
  columns: [
    { name: "month", title: "Month" },
    { name: "sales", title: "Sales" },
  ],
  rows: [
    { cells: { month: { value: "Jan" }, sales: { value: "1000" } } },
    { cells: { month: { value: "Feb" }, sales: { value: "1500" } } },
    { cells: { month: { value: "Mar" }, sales: { value: "1200" } } },
  ],
};

const chartOptions = {
  Typ: ChartType.BAR,
  Series: "sales",
  Title: "Monthly Sales",
  ForceWidth: "600",
  ForceHeight: "400",
};

const chartSvg = await dataTableToChart(chartData, chartOptions);

await fs.writeFile("chart.svg", chartSvg);

Generates standalone chart SVG strings from SmeUP data structures using ECharts.


PDF Form Filling

Fill Existing PDF Forms

import { fillPdfForm } from "@sme.up/doc-alchemist";

const templatePdf = await fs.readFile("template.pdf");

const formData = {
  firstName: "John",
  lastName: "Doe",
  email: "[email protected]",
  phone: "555-1234",
};

const filledPdf = await fillPdfForm(templatePdf, formData, {
  flatten: true, // Optional: flatten form fields after filling
});

await fs.writeFile("filled-form.pdf", filledPdf);

Fills existing PDF forms with data and optionally flattens fields to prevent further editing.


Advanced Features

Mixed Content in Single Document

const doc = {
  content: [
    {
      text: "Complete Report",
      fontSize: 24,
      bold: true,
      margin: [0, 0, 0, 20],
    },

    // Section with table
    { text: "Data Summary", fontSize: 18, bold: true, margin: [0, 0, 0, 10] },
    {
      table: {
        smeup: { fun: "F(EXB;SERV;MET)" },
      },
      layout: "lightHorizontalLines",
      margin: [0, 0, 0, 20],
    },

    // Section with chart
    {
      text: "Visual Analysis",
      fontSize: 18,
      bold: true,
      margin: [0, 0, 0, 10],
    },
    {
      chart: {
        smeup: {
          fun: "F(EXA;SERV;MET)",
          options: {
            Typ: ChartType.LINE,
            Series: "VALORI|VALCAL",
            Title: "Trend Analysis",
            ForceWidth: "500",
            ForceHeight: "300",
          },
        },
      },
      margin: [0, 0, 0, 20],
    },

    // Section with images
    {
      text: "Supporting Images",
      fontSize: 18,
      bold: true,
      margin: [0, 0, 0, 10],
    },
    {
      columns: [
        {
          image: {
            smeup: { url: "https://example.com/image1.png" },
          },
          width: 200,
        },
        {
          image: {
            smeup: { obj: { t: "CN", p: "COL", k: "LOGO" } },
          },
          width: 200,
        },
      ],
    },
  ],
  header: {
    text: "Page [CurrentPage] of [PageCount]",
    alignment: "right",
    margin: [40, 20],
  },
};

const pdf = await pdfmakeDocumentToPdfData(doc, context);
await fs.writeFile("complete-report.pdf", pdf);

Combines tables, charts, images, and formatted text in a single comprehensive document.


API Reference

Core Functions

dataTableToPdfData(component, webupManagerData)

Generates a simple PDF from a SmeUP DataTable with automatic formatting and cover page.

const pdf = await dataTableToPdfData(
  component: {
    smeupDataTable: SmeupDataTable,
    props: GenericObject
  },
  webupManagerData: WebupManagerData
): Promise<Buffer | Uint8Array>

Best for quick table exports with minimal configuration. Includes automatic cover page generation with titles and logos.

pdfmakeDocumentToPdfData(doc, context)

Converts a pdfmake document definition into PDF binary data.

const pdf = await pdfmakeDocumentToPdfData(
  doc: TDocumentDefinitions,
  context: Partial<PdfMakeConverterContext>
): Promise<Uint8Array>

dataTableToExcelData(dataTable, webupManagerData, sheetName)

Exports SmeUP DataTable to Excel format.

const excel = await dataTableToExcelData(
  dataTable: SmeupDataTable,
  webupManagerData: WebupManagerData,
  sheetName?: string
): Promise<Buffer>

dataTreeToExcelData(dataTree, webupManagerData, sheetName)

Exports SmeUP DataTree to Excel format with hierarchy.

const excel = await dataTreeToExcelData(
  dataTree: SmeupDataTree,
  webupManagerData: WebupManagerData,
  sheetName?: string
): Promise<Buffer>

dataTableToChart(dataTable, options)

Generates chart SVG string from SmeUP data.

const svg = await dataTableToChart(
  dataTable: SmeupDataTable,
  options: ChartOptions
): Promise<string>

fillPdfForm(pdfBuffer, formData, options)

Fills existing PDF forms with data.

const filled = await fillPdfForm(
  pdfBuffer: Uint8Array,
  formData: Record<string, string>,
  options?: FillPdfFormOptions
): Promise<Uint8Array>

Context Configuration

interface PdfMakeConverterContext {
  webupManagerData: WebupManagerData;
  getSmeupDataStructure?: (fun: string) => Promise<any>;
  fetchData?: (url: string) => Promise<Response>;
  damSvcEndpoint?: string;
}

interface WebupManagerData {
  mathLocale: string;
  datesLocale: string;
  themeBackground: string;
}

Development

Build

npm run build

Test

npm test

Debug Examples

Run the debug script to see all features in action:

npm start

This generates sample PDFs in the output/ directory demonstrating all capabilities.


License

Apache-2.0


Support

For issues and feature requests, visit: GitHub Repository


Additional Resources

  • See debug-pdfmake.ts for complete working examples
  • Check the tests/ directory for unit test examples
  • Explore the src/types/ directory for TypeScript type definitions