platform-documents
Template-based document generation engine supporting DOCX and PDF output. Uses pluggable renderers and template parsers with image processing via Sharp.
Package: @breadstone/archipel-platform-documents
Quick Start
typescript
import { Module } from '@nestjs/common';
import { DocumentModule } from '@breadstone/archipel-platform-documents';
@Module({
imports: [
DocumentModule.forRoot({
maxImageWidth: 1920,
maxImageHeight: 1080,
delimiters: { start: '[[', end: ']]' },
debug: false,
}),
],
})
export class AppModule {}Module Configuration
IDocumentModuleOptions
| Property | Type | Default | Description |
|---|---|---|---|
maxImageWidth | number | 1920 | Maximum width for embedded images |
maxImageHeight | number | 1080 | Maximum height for embedded images |
delimiters.start | string | '[[' | Template variable start delimiter |
delimiters.end | string | ']]' | Template variable end delimiter |
debug | boolean | false | Enable debug output |
DocumentEngine
Main orchestrator for document rendering.
Render from Template
typescript
import { DocumentEngine } from '@breadstone/archipel-platform-documents';
@Injectable()
export class InvoiceService {
constructor(private readonly _docEngine: DocumentEngine) {}
public async generateInvoice(data: IInvoiceData): Promise<Buffer> {
const result = await this._docEngine.render({
templateId: 'invoice-template',
data: {
invoiceNumber: data.number,
customerName: data.customerName,
items: data.items.map((item) => ({
description: item.description,
qty: item.quantity,
unitPrice: `€${item.unitPrice.toFixed(2)}`,
total: `€${(item.quantity * item.unitPrice).toFixed(2)}`,
})),
subtotal: `€${data.subtotal.toFixed(2)}`,
tax: `€${data.tax.toFixed(2)}`,
total: `€${data.total.toFixed(2)}`,
date: new Date().toLocaleDateString('de-DE'),
},
templateFormat: 'docx',
});
return result.buffer;
}
}Render from Buffer
typescript
const templateBuffer = await fs.readFile('./templates/contract.docx');
const result = await this._docEngine.render({
templateBuffer,
data: { clientName: 'Acme Corp', startDate: '2025-01-01' },
templateFormat: 'docx',
});Templates with Images
typescript
const result = await this._docEngine.render({
templateId: 'report-with-charts',
data: {
title: 'Q4 Report',
summary: 'Revenue increased by 23%.',
},
images: [
{
tag: 'revenueChart', // Matches [[revenueChart]] in template
buffer: chartImageBuffer,
contentType: 'image/png',
width: 800,
height: 400,
},
],
templateFormat: 'docx',
});Document Renderers
DOCX Renderer
Renders DOCX (Microsoft Word) documents using docxtemplater:
- Variable substitution:
[[variableName]] - Loops:
[[#items]][[name]] - [[price]][[/items]] - Conditionals:
[[#if showDiscount]]...[[/if]] - Image placeholders:
[[imageName]]
PDF Renderer
Renders PDF documents using pdf-lib:
- Text substitution in PDF form fields
- Image insertion
- Page manipulation
Image Processing
SharpImageProcessor
Resizes and optimizes images before embedding in documents:
typescript
import { SharpImageProcessor } from '@breadstone/archipel-platform-documents';
// Used internally by DocumentEngine
// Respects maxImageWidth and maxImageHeight from module optionsSupported formats: PNG, JPEG, WebP, TIFF, AVIF.
Real-World Example: Contract Generator
typescript
@Controller('api/v1/contracts')
export class ContractController {
constructor(
private readonly _docEngine: DocumentEngine,
private readonly _blobService: BlobService,
) {}
@Post(':id/generate')
public async generate(@Param('id') contractId: string, @Res() res: Response): Promise<void> {
const contract = await this._contractService.findById(contractId);
const result = await this._docEngine.render({
templateId: 'service-agreement',
data: {
clientName: contract.clientName,
startDate: contract.startDate.toLocaleDateString('de-DE'),
endDate: contract.endDate.toLocaleDateString('de-DE'),
monthlyFee: `€${contract.monthlyFee.toFixed(2)}`,
services: contract.services,
},
templateFormat: 'docx',
});
// Optionally store in blob storage
await this._blobService.uploadFile(
`contracts/${contractId}/${result.name}`,
result.buffer,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
);
res.set({
'Content-Type': result.contentType,
'Content-Disposition': `attachment; filename="${result.name}"`,
});
res.send(result.buffer);
}
}Exports Summary
| Export | Type | Description |
|---|---|---|
DocumentModule | NestJS Module | forRoot() configuration |
DocumentEngine | Service | Main rendering orchestrator |
BaseDocumentRenderer | Abstract class | Renderer base |
IDocumentRenderer | Interface | Renderer contract |
SharpImageProcessor | Service | Image resize/optimization |
IImageProcessor | Interface | Image processor contract |
DocumentFormat | Enum | 'docx' / 'pdf' |
TemplateFormat | Enum | Template format identifiers |
IRenderResult | Interface | Render output (buffer, name, contentType) |
IDocumentProbeReport | Interface | Template validation report |