npm package: @sme.up/doc-alchemist
Description: Library for generating documents in various formats, including Excel and PDF.
Author: Smeup LAB
Latest version: 2.1.0-SNAPSHOT-20260408131428

# 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

```typescript
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

```bash
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`:

```typescript
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`:

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

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

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

const formData = {
  firstName: "John",
  lastName: "Doe",
  email: "john.doe@example.com",
  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

```typescript
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.

```typescript
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.

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

#### `dataTableToExcelData(dataTable, webupManagerData, sheetName)`

Exports SmeUP DataTable to Excel format.

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

#### `dataTreeToExcelData(dataTree, webupManagerData, sheetName)`

Exports SmeUP DataTree to Excel format with hierarchy.

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

#### `dataTableToChart(dataTable, options)`

Generates chart SVG string from SmeUP data.

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

#### `fillPdfForm(pdfBuffer, formData, options)`

Fills existing PDF forms with data.

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

### Context Configuration

```typescript
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

```bash
npm run build
```

### Test

```bash
npm test
```

### Debug Examples

Run the debug script to see all features in action:

```bash
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](https://github.com/smeup/doc-alchemist)

---

## Additional Resources

- See [debug-pdfmake.ts](debug-pdfmake.ts) for complete working examples
- Check the `tests/` directory for unit test examples
- Explore the `src/types/` directory for TypeScript type definitions