UNPKG

safeer-pdf-generator

Version:

Framework-agnostic PDF generation library with chunking, merging, S3 upload, and email delivery

341 lines 10.9 kB
/** * Core type definitions for PDF Reporter */ import type { PdfEventEmitter } from './core/PdfEventEmitter.js'; export interface LoggingAdapter { debug(message: string, ...args: any[]): void; info(message: string, ...args: any[]): void; warn(message: string, ...args: any[]): void; error(message: string, ...args: any[]): void; } export interface ColumnDefinition { key: string; title: string; dataIndex: string; flex?: number; type?: 'image' | 'boolean' | 'text' | 'link'; } export interface UserInfo { /** Company/tenant name. Shown in the header and the footer's center line. */ name?: string; email?: string; mobile?: string; companyLogo?: string; companyName?: string; companyLogoBase64?: string; /** * Person who generated the report. Shown only in the footer's left * "Generated by …" line. When unset, that line is omitted entirely (no * placeholder text). Decoupled from `name` so the company name no longer * appears as the author. */ generatedBy?: string; } /** * Configuration for the PDF footer (rendered by MergeService.addPageNumbers). * All toggles default to true. Pass `footer: false` on PdfGenerationOptions to * disable the entire footer (including the separator line). */ export interface FooterConfig { /** Master toggle. Default: true. */ show?: boolean; /** Toggle the "Generated by …" line (footer left). Default: true. */ showGeneratedBy?: boolean; /** Toggle the "<company> • <year>" line (footer center). Default: true. */ showCompany?: boolean; /** Toggle the "Page X of Y" line (footer right). Default: true. */ showPageNumbers?: boolean; /** String/format overrides. EN/AR defaults still apply when unset. */ labels?: { /** Override the "Generated by" prefix (e.g. "Préparé par"). */ generatedBy?: string; /** Override the "Page X of Y" formatter. */ page?: (current: number, total: number) => string; }; } export interface InfoSection { label: string; value: string; } export interface ChunkingOptions { enabled?: boolean; chunkSize?: number; maxConcurrency?: number; } export interface PuppeteerOptions { executablePath?: string; args?: string[]; headless?: boolean; protocolTimeout?: number; /** * Pass an existing Puppeteer Browser instance (e.g., from puppeteer-cluster or generic-pool). * When provided, the package will use this browser instead of launching a new one, * and will NOT close it when done — only pages will be closed. */ browserInstance?: any; } export interface PdfOptions { format?: string; landscape?: boolean; printBackground?: boolean; margin?: { top?: string; left?: string; right?: string; bottom?: string; }; displayHeaderFooter?: boolean; } export interface LogoFetchOptions { inlineAsBase64?: boolean; fetcher?: (url: string) => Promise<string>; } export interface TotalsConfig { columns: string[]; aggregator?: (rows: any[], col: string) => any; } export interface HooksConfig { beforeChunkRender?: (params: any) => void | Promise<void>; afterChunkRender?: (result: Buffer, params: any) => void | Promise<void>; beforeMerge?: (chunks: Buffer[]) => void | Promise<void>; afterMerge?: (merged: Buffer) => void | Promise<void>; transformHtml?: (html: string, stage: 'pre' | 'post') => string; transformColumnValue?: (value: any, column: ColumnDefinition, row: any) => any; } export interface S3UploadConfig { bucket: string; region: string; accessKeyId?: string; secretAccessKey?: string; folder?: string; acl?: string; contentType?: string; endpoint?: string; } /** * Configuration for writing the generated PDF to local disk. * Composes with other destinations (s3, email, webhook) — all run independently. */ export interface LocalFsConfig { /** Destination directory. Relative paths resolve from process.cwd(). */ path: string; /** Override the auto-generated filename (defaults to result.fileName). */ filename?: string; /** Create parent directories recursively if missing. Default: true. */ createDir?: boolean; /** Overwrite existing files. When false, throws if the target exists. Default: true. */ overwrite?: boolean; } export interface LocalFsResult { /** Absolute path to the written file. */ path: string; /** Size of the written file in bytes (equal to result.sizeBytes). */ sizeBytes: number; } /** * Configuration for webhook dispatch after PDF generation */ export interface WebhookConfig { /** URL to send the POST request to */ url: string; /** Secret for HMAC-SHA256 signature (sent as X-Webhook-Signature header) */ secret?: string; /** Pass-through metadata included in the webhook payload (e.g., tenantId, userId) */ metadata?: Record<string, any>; /** Request timeout in milliseconds (default: 10000) */ timeoutMs?: number; } export interface EmailSendConfig { to: string; from?: string; subject?: string; transport?: any; smtp?: { host: string; port: number; secure?: boolean; auth: { user: string; pass: string; }; }; attachmentMode?: 'attachment' | 'link'; template?: string | EmailTemplateFunction; } export type EmailTemplateFunction = (context: EmailTemplateContext) => string; export interface EmailTemplateContext { title: string; generatedAt: string; downloadUrl?: string; fileSizeMB: number; user?: UserInfo; company?: { name?: string; }; } export interface TemplateCompilerFunction { (params: TemplateCompilerParams): TemplateCompilerResult; } export interface TemplateCompilerParams { title: string; data: any[]; columns: ColumnDefinition[]; locale?: string; reportDate?: string | Date; userInfo?: UserInfo; infoSection?: InfoSection[]; pdfFilteredColumns?: string[]; translationFn?: (key: string) => string; chunkInfo?: { current: number; total: number; startRow: number; endRow: number; }; /** * Custom CSS to inject into the template's <style> block. * Use this to override table styling, colors, fonts, etc. */ customCss?: string; /** * Custom HTML to inject before or after the data table. * Useful for adding summaries, charts, disclaimers, etc. */ customHtml?: { beforeTable?: string; afterTable?: string; }; } export interface TemplateCompilerResult { html: string; header: string; footer: string; } export interface PdfGenerationOptions { title: string; data: any[]; columns: ColumnDefinition[]; locale?: string; reportDate?: string | Date; userInfo?: UserInfo; infoSection?: InfoSection[]; filteredColumnKeys?: string[]; translationFn?: (key: string) => string; chunking?: ChunkingOptions; template?: string | TemplateCompilerFunction; headerTemplate?: string | ((ctx: any) => string); footerTemplate?: string | ((ctx: any) => string); includeTotals?: boolean; totalsConfig?: TotalsConfig; email?: EmailSendConfig | false; s3?: S3UploadConfig | false; /** Write the generated PDF to a local file. Composes with `s3`, `email`, and `webhook`. */ localFs?: LocalFsConfig | false; /** * Footer rendering controls. Pass `false` to disable the entire footer * (separator + all lines). Pass an object to toggle individual lines or * override labels. Default: all lines visible, with the "Generated by" * line omitted when `userInfo.generatedBy` is unset. */ footer?: FooterConfig | false; /** * @deprecated Not implemented. The package always returns a Buffer in `result.buffer`. * For local-file output use `localFs: { path }`. Slated for removal in 2.0. */ return?: 'buffer' | 'stream' | 'file'; /** * @deprecated Not implemented. Use `localFs: { path }` instead. * Slated for removal in 2.0. */ outputPath?: string; logoFetch?: LogoFetchOptions; hooks?: HooksConfig; timeoutMs?: number; puppeteer?: PuppeteerOptions; pdf?: PdfOptions; logging?: LoggingAdapter; /** * Custom CSS injected into the template's style block (overrides default styles) */ customCss?: string; /** * Custom HTML injected before/after the data table in the template */ customHtml?: { beforeTable?: string; afterTable?: string; }; /** * Optional event emitter for lifecycle events (generation:started, s3:upload:complete, error, etc.) */ events?: PdfEventEmitter; /** * Optional webhook configuration to dispatch HTTP POST upon completion. * Set to false to explicitly disable. */ webhook?: WebhookConfig | false; } export interface PdfGenerationResult { buffer: Buffer; sizeBytes: number; pageCount: number; durationMs: number; fileName: string; metadata: { title: string; chunkCount: number; rows: number; generatedAt: string; }; s3?: { url: string; key: string; }; email?: { sent: boolean; to?: string; messageId?: string; error?: string; }; localFs?: LocalFsResult; } export interface MergePdfsOptions { logging?: LoggingAdapter; } export interface S3UploadResult { url: string; key: string; } export interface EmailResult { sent: boolean; messageId?: string; error?: string; } export interface UploaderAdapter { upload(buffer: Buffer, filename: string, mimeType: string, options?: any): Promise<S3UploadResult>; } export interface EmailSenderAdapter { send(options: EmailSendConfig, buffer: Buffer, filename: string): Promise<EmailResult>; } export declare class PdfGenerationError extends Error { cause?: Error | undefined; constructor(message: string, cause?: Error | undefined); } export declare class TemplateError extends Error { cause?: Error | undefined; constructor(message: string, cause?: Error | undefined); } export declare class S3UploadError extends Error { cause?: Error | undefined; constructor(message: string, cause?: Error | undefined); } export declare class EmailError extends Error { cause?: Error | undefined; constructor(message: string, cause?: Error | undefined); } export declare class ChunkProcessingError extends Error { chunkIndex?: number | undefined; cause?: Error | undefined; constructor(message: string, chunkIndex?: number | undefined, cause?: Error | undefined); } //# sourceMappingURL=types.d.ts.map