@speresps/pdf-module 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,1168 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # @speresps/pdf-module
2
+
3
+ A reusable PDF generation and document management module for **Node.js and Next.js applications**. It provides Persian (Farsi) and RTL-compatible PDF generation using `pdfmake-rtl`, embedded Vazirmatn fonts, customizable headers and footers, table and text templates, paginated reports, server-side PDF storage, and browser downloads.
4
+
5
+ The module includes four PDF generation methods:
6
+
7
+ - `generatePDFTable()` — Generate a PDF containing a table.
8
+ - `generatePDFText()` — Generate a PDF containing text.
9
+ - `generatePDFTextAndTable()` — Generate a PDF containing text followed by a table.
10
+ - `generatePDFTextAndTableWithPagination()` — Generate a PDF containing repeated text and separately paginated tables.
11
+
12
+ Generated PDF files are stored in the consuming project's configured directory and can subsequently be downloaded through the client API.
13
+
14
+ ---
15
+
16
+ ## Table of Contents
17
+
18
+ - [Features](#features)
19
+ - [Requirements](#requirements)
20
+ - [Installation](#installation)
21
+ - [Project Configuration](#project-configuration)
22
+ - [Project Structure](#project-structure)
23
+ - [Importing the Module](#importing-the-module)
24
+ - [API Reference](#api-reference)
25
+ - [generatePDFTable](#1-generatepdftable)
26
+ - [generatePDFText](#2-generatepdftext)
27
+ - [generatePDFTextAndTable](#3-generatepdftextandtable)
28
+ - [generatePDFTextAndTableWithPagination](#4-generatepdftextandtablewithpagination)
29
+ - [downloadPDF](#5-downloadpdf)
30
+ - [Header Configuration](#header-configuration)
31
+ - [Footer Configuration](#footer-configuration)
32
+ - [Logo Requirements](#logo-requirements)
33
+ - [PDF Generation Examples](#pdf-generation-examples)
34
+ - [Server-Side Usage](#server-side-usage)
35
+ - [Client-Side Usage with Next.js](#client-side-usage-with-nextjs)
36
+ - [PDF Storage](#pdf-storage)
37
+ - [Return Values and Error Handling](#return-values-and-error-handling)
38
+ - [Important Notes](#important-notes)
39
+ - [License](#license)
40
+
41
+ ---
42
+
43
+ ## Features
44
+
45
+ - Generate PDF documents using `pdfmake-rtl`.
46
+ - Support for Persian (Farsi) text and right-to-left (RTL) layouts.
47
+ - Embedded Vazirmatn fonts; no separate font installation is required in the consuming application.
48
+ - Customizable PDF headers and titles.
49
+ - Optional Base64 image/logo in the header.
50
+ - Customizable footer information.
51
+ - Automatic footer page numbering.
52
+ - Four reusable PDF templates.
53
+ - Automatic portrait/landscape orientation selection for table-based templates.
54
+ - Configurable PDF filenames.
55
+ - Support for externally paginated data.
56
+ - Server-side PDF generation and file storage.
57
+ - Client-side PDF downloads in Next.js applications.
58
+ - Integration with `@speresps/config-module` and `@speresps/report-module`.
59
+ - ES Module support.
60
+
61
+ ---
62
+
63
+ ## Requirements
64
+
65
+ - Node.js 20 or newer.
66
+ - JavaScript ES Modules (`"type": "module"`).
67
+ - For the browser download API: Next.js with React and support for Server Actions.
68
+ - A root-level `config/` directory in the consuming project.
69
+ - A `config/pdf.conf` configuration file.
70
+
71
+ ### Dependencies
72
+
73
+ The module declares the following runtime dependencies:
74
+
75
+ | Package | Purpose |
76
+ |---|---|
77
+ | `@speresps/config-module` | Loads the consuming project's PDF configuration. |
78
+ | `@speresps/report-module` | Provides logging functionality. |
79
+ | `pdfmake-rtl` | Generates PDF documents with RTL support. |
80
+
81
+ These dependencies are declared in the module's `package.json` and are installed automatically when the module is installed through npm.
82
+
83
+ **Important:** The consuming application must also provide its own `config/pdf.conf` file. Installing the module does not automatically create this configuration file.
84
+
85
+ ---
86
+
87
+ ## Installation
88
+
89
+ Install the package using npm:
90
+
91
+ ```bash
92
+ npm install @speresps/pdf-module
93
+ ```
94
+
95
+ The module supports separate entry points for server-side and client-side usage.
96
+
97
+ ---
98
+
99
+ ## Project Configuration
100
+
101
+ The module uses `@speresps/config-module` to load its configuration from the consuming project's root-level `config/` directory.
102
+
103
+ Create the following directory and file:
104
+
105
+ ```text
106
+ your-project/
107
+ └── config/
108
+ └── pdf.conf
109
+ ```
110
+
111
+ ### config/pdf.conf
112
+
113
+ Use the following configuration:
114
+
115
+ ```ini
116
+ ################# Table ################
117
+ FILENAME_TABLE = table.pdf
118
+
119
+ ################# Text #################
120
+ FILENAME_TEXT = text.pdf
121
+
122
+ ############### Text + Table ############
123
+ FILENAME_TEXT_TABLE = text-table.pdf
124
+
125
+ ########## Text + Table Pagination ######
126
+ FILENAME_TEXT_TABLE_PAGINATION = text-table-pagination.pdf
127
+
128
+ ############ Auto Download Status #######
129
+ AUTO_DOWNLOAD = false
130
+
131
+ ################ Files Route ############
132
+ MAIN_FOLDER_NAME = files
133
+ PDF_FOLDER_NAME = pdf
134
+ ```
135
+
136
+ ### Configuration Properties
137
+
138
+ | Property | Default | Description |
139
+ |---|---|---|
140
+ | `FILENAME_TABLE` | `table.pdf` | Default filename for table PDFs. |
141
+ | `FILENAME_TEXT` | `text.pdf` | Default filename for text PDFs. |
142
+ | `FILENAME_TEXT_TABLE` | `text-table.pdf` | Default filename for text-and-table PDFs. |
143
+ | `FILENAME_TEXT_TABLE_PAGINATION` | `text-table-pagination.pdf` | Default filename for paginated PDFs. |
144
+ | `AUTO_DOWNLOAD` | `false` | Configured automatic-download setting. |
145
+ | `MAIN_FOLDER_NAME` | `files` | Main directory for generated files. |
146
+ | `PDF_FOLDER_NAME` | `pdf` | PDF storage subdirectory. |
147
+
148
+ The generated PDFs are stored under:
149
+
150
+ ```text
151
+ your-project/
152
+ └── files/
153
+ └── pdf/
154
+ ├── table.pdf
155
+ ├── text.pdf
156
+ ├── text-table.pdf
157
+ └── text-table-pagination.pdf
158
+ ```
159
+
160
+ The `files/` and `pdf/` directories are created automatically when a PDF is saved.
161
+
162
+ ### Logger Configuration
163
+
164
+ The module uses `@speresps/report-module` internally:
165
+
166
+ ```javascript
167
+ import { reportLogger } from "@speresps/report-module";
168
+
169
+ const logger = reportLogger({
170
+ directory: "./report/logs",
171
+ level: "debug",
172
+ console: false,
173
+ service: "PDF",
174
+ });
175
+ ```
176
+
177
+ You do not need to create a logger or pass one to the PDF methods. Logging is initialized internally by the module.
178
+
179
+ ---
180
+
181
+ ## Project Structure
182
+
183
+ A typical consuming project can use the following structure:
184
+
185
+ ```text
186
+ your-project/
187
+ │
188
+ ├── config/
189
+ │ └── pdf.conf
190
+ │
191
+ ├── files/
192
+ │ └── pdf/
193
+ │
194
+ ├── report/
195
+ │ └── logs/
196
+ │
197
+ ├── src/
198
+ │ └── app/
199
+ │ └── ...
200
+ │
201
+ ├── package.json
202
+ └── ...
203
+ ```
204
+
205
+ The `config/` directory is required. The PDF and log directories are created by their respective modules when needed.
206
+
207
+ ---
208
+
209
+ ## Importing the Module
210
+
211
+ The package provides three entry points.
212
+
213
+ ### 1. Main Entry Point — Server API
214
+
215
+ Use the main package entry point for Node.js server-side applications:
216
+
217
+ ```javascript
218
+ import {
219
+ generatePDFTable,
220
+ generatePDFText,
221
+ generatePDFTextAndTable,
222
+ generatePDFTextAndTableWithPagination,
223
+ downloadPDF,
224
+ } from "@speresps/pdf-module";
225
+ ```
226
+
227
+ Equivalent explicit server import:
228
+
229
+ ```javascript
230
+ import {
231
+ generatePDFTable,
232
+ generatePDFText,
233
+ generatePDFTextAndTable,
234
+ generatePDFTextAndTableWithPagination,
235
+ downloadPDF,
236
+ } from "@speresps/pdf-module/server";
237
+ ```
238
+
239
+ ### 2. Client Entry Point
240
+
241
+ For Next.js client components:
242
+
243
+ ```javascript
244
+ import {
245
+ generatePDFTable,
246
+ generatePDFText,
247
+ generatePDFTextAndTable,
248
+ generatePDFTextAndTableWithPagination,
249
+ downloadPDF,
250
+ } from "@speresps/pdf-module/client";
251
+ ```
252
+
253
+ The client entry point provides Server Action wrappers for PDF generation and a browser download helper.
254
+
255
+ **Important:** Client-side generation methods invoke Next.js Server Actions. They are not standalone browser-only PDF generators and require a compatible Next.js application.
256
+
257
+ ---
258
+
259
+ # API Reference
260
+
261
+ All four generation methods receive a single JavaScript object containing the PDF data and optional presentation settings.
262
+
263
+ Common properties:
264
+
265
+ | Property | Type | Required | Description |
266
+ |---|---|---|---|
267
+ | `headerTitle` | `string` | No | Text displayed in the PDF header. |
268
+ | `headerLogoBase64` | `string` | No | Base64 image data for the header logo. |
269
+ | `footerInfo` | `object` | No | Website and contact information displayed in the footer. |
270
+ | `fileName` | `string` | No | Name used when saving the generated PDF. |
271
+ | `autoDownload` | `boolean` | No | Passed through by the generation service, but does not currently trigger automatic downloading through the public API. |
272
+
273
+ The required content properties differ depending on the selected PDF method.
274
+
275
+ ---
276
+
277
+ ## 1. generatePDFTable()
278
+
279
+ Generates a PDF containing a table, including the configured header and footer.
280
+
281
+ ### Method Signature
282
+
283
+ ```javascript
284
+ generatePDFTable({
285
+ columns,
286
+ tableData,
287
+ headerTitle,
288
+ headerLogoBase64,
289
+ footerInfo,
290
+ fileName,
291
+ });
292
+ ```
293
+
294
+ ### Required Properties
295
+
296
+ | Property | Type | Required | Description |
297
+ |---|---|---|---|
298
+ | `columns` | `string[]` | Yes | Array of column names. |
299
+ | `tableData` | `object[]` | Yes | Array of row objects. |
300
+
301
+ Each column name must correspond to a property in the table row objects.
302
+
303
+ ### Example
304
+
305
+ ```javascript
306
+ import { generatePDFTable } from "@speresps/pdf-module/client";
307
+
308
+ const columns = [
309
+ "نام",
310
+ "سن",
311
+ "شغل",
312
+ "آدرس",
313
+ "تلفن",
314
+ "جنسیت",
315
+ ];
316
+
317
+ const tableData = [
318
+ {
319
+ نام: "سارا",
320
+ سن: 28,
321
+ شغل: "طراح گرافیک",
322
+ آدرس: "خیابان انقلاب، تهران",
323
+ تلفن: "09123456789",
324
+ جنسیت: "زن",
325
+ },
326
+ {
327
+ نام: "علی",
328
+ سن: 30,
329
+ شغل: "برنامه‌نویس",
330
+ آدرس: "خیابان آزادی، تهران",
331
+ تلفن: "09123456789",
332
+ جنسیت: "مرد",
333
+ },
334
+ ];
335
+
336
+ const footerInfo = {
337
+ siteName: "سایت من",
338
+ address: "خیابان انقلاب، تهران",
339
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
340
+ email: "info@mysite.com",
341
+ website: "www.mysite.com",
342
+ };
343
+
344
+ const result = await generatePDFTable({
345
+ columns,
346
+ tableData,
347
+
348
+ headerTitle: "لیست اعضای تیم",
349
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
350
+
351
+ footerInfo,
352
+
353
+ fileName: "team-members.pdf",
354
+ });
355
+
356
+ if (result.success) {
357
+ console.log("PDF generated successfully.");
358
+ } else {
359
+ console.error(result.message);
360
+ }
361
+ ```
362
+
363
+ ### Table Data Rules
364
+
365
+ - `columns` must be a non-empty array of non-empty strings.
366
+ - `tableData` must be an array.
367
+ - Every row must be a JavaScript object.
368
+ - Column names must match the keys in the row objects.
369
+ - Missing row values are rendered as empty strings.
370
+
371
+ The table template calculates column widths and selects portrait or landscape orientation based on the estimated table width.
372
+
373
+ ---
374
+
375
+ ## 2. generatePDFText()
376
+
377
+ Generates a PDF containing text with a customizable header and footer.
378
+
379
+ ### Method Signature
380
+
381
+ ```javascript
382
+ generatePDFText({
383
+ text,
384
+ headerTitle,
385
+ headerLogoBase64,
386
+ footerInfo,
387
+ fileName,
388
+ });
389
+ ```
390
+
391
+ ### Required Properties
392
+
393
+ | Property | Type | Required | Description |
394
+ |---|---|---|---|
395
+ | `text` | `string` | Yes | Main PDF content. |
396
+
397
+ ### Example
398
+
399
+ ```javascript
400
+ import { generatePDFText } from "@speresps/pdf-module/client";
401
+
402
+ const text = `
403
+ این یک متن نمونه فارسی است.
404
+
405
+ این متن در فایل PDF نمایش داده می‌شود.
406
+ فونت Vazirmatn برای نمایش صحیح متن فارسی استفاده می‌شود.
407
+ `;
408
+
409
+ const footerInfo = {
410
+ siteName: "سایت من",
411
+ address: "خیابان آزادی، تهران",
412
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
413
+ email: "info@mysite.com",
414
+ website: "www.mysite.com",
415
+ };
416
+
417
+ const result = await generatePDFText({
418
+ text,
419
+
420
+ headerTitle: "آموزش برنامه نویسی",
421
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
422
+
423
+ footerInfo,
424
+
425
+ fileName: "programming-report.pdf",
426
+ });
427
+
428
+ if (result.success) {
429
+ console.log("PDF generated successfully.");
430
+ } else {
431
+ console.error(result.message);
432
+ }
433
+ ```
434
+
435
+ ### Text Data Rules
436
+
437
+ - `text` must be a non-empty string.
438
+ - Persian and RTL text are supported.
439
+ - The text is displayed with right alignment and the embedded Vazirmatn font.
440
+
441
+ ---
442
+
443
+ ## 3. generatePDFTextAndTable()
444
+
445
+ Generates a PDF containing a text section followed by a table.
446
+
447
+ This template is suitable for reports that require an introduction, description, or summary above tabular information.
448
+
449
+ ### Method Signature
450
+
451
+ ```javascript
452
+ generatePDFTextAndTable({
453
+ text,
454
+ columns,
455
+ tableData,
456
+ headerTitle,
457
+ headerLogoBase64,
458
+ footerInfo,
459
+ fileName,
460
+ });
461
+ ```
462
+
463
+ ### Required Properties
464
+
465
+ | Property | Type | Required | Description |
466
+ |---|---|---|---|
467
+ | `text` | `string` | Yes | Text displayed above the table. |
468
+ | `columns` | `string[]` | Yes | Table column names. |
469
+ | `tableData` | `object[]` | Yes | Table rows. |
470
+
471
+ ### Example
472
+
473
+ ```javascript
474
+ import { generatePDFTextAndTable } from "@speresps/pdf-module/client";
475
+
476
+ const text = "این گزارش شامل اطلاعات اعضای تیم است.";
477
+
478
+ const columns = [
479
+ "نام",
480
+ "سن",
481
+ "شغل",
482
+ ];
483
+
484
+ const tableData = [
485
+ {
486
+ نام: "علی",
487
+ سن: 30,
488
+ شغل: "برنامه‌نویس",
489
+ },
490
+ {
491
+ نام: "سارا",
492
+ سن: 28,
493
+ شغل: "طراح گرافیک",
494
+ },
495
+ {
496
+ نام: "رضا",
497
+ سن: 30,
498
+ شغل: "مدیر پروژه",
499
+ },
500
+ ];
501
+
502
+ const footerInfo = {
503
+ siteName: "سایت من",
504
+ address: "خیابان آزادی، تهران",
505
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
506
+ email: "info@mysite.com",
507
+ website: "www.mysite.com",
508
+ };
509
+
510
+ const result = await generatePDFTextAndTable({
511
+ text,
512
+ columns,
513
+ tableData,
514
+
515
+ headerTitle: "گزارش اعضای تیم",
516
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
517
+
518
+ footerInfo,
519
+
520
+ fileName: "team-report.pdf",
521
+ });
522
+
523
+ if (result.success) {
524
+ console.log("PDF generated successfully.");
525
+ } else {
526
+ console.error(result.message);
527
+ }
528
+ ```
529
+
530
+ ### Content Layout
531
+
532
+ The generated document contains:
533
+
534
+ 1. Header with title and optional logo.
535
+ 2. Main text section.
536
+ 3. Table with column headings and data rows.
537
+ 4. Footer with website/contact information and page numbering.
538
+
539
+ ---
540
+
541
+ ## 4. generatePDFTextAndTableWithPagination()
542
+
543
+ Generates a PDF using externally paginated table data.
544
+
545
+ This method is designed for data retrieved from APIs or database queries that already return records grouped into pages.
546
+
547
+ Each item in `paginatedData` represents one table section in the PDF. The method creates a new PDF page before each subsequent item and repeats the supplied text above each table.
548
+
549
+ ### Method Signature
550
+
551
+ ```javascript
552
+ generatePDFTextAndTableWithPagination({
553
+ text,
554
+ columns,
555
+ paginatedData,
556
+ headerTitle,
557
+ headerLogoBase64,
558
+ footerInfo,
559
+ fileName,
560
+ });
561
+ ```
562
+
563
+ ### Required Properties
564
+
565
+ | Property | Type | Required | Description |
566
+ |---|---|---|---|
567
+ | `text` | `string` | Yes | Text displayed above each page's table. |
568
+ | `columns` | `string[]` | Yes | Table column names. |
569
+ | `paginatedData` | `object[]` | Yes | Array of page objects, each containing a `data` array. |
570
+
571
+ ### paginatedData Structure
572
+
573
+ The expected structure is:
574
+
575
+ ```javascript
576
+ const paginatedData = [
577
+ {
578
+ page: 1,
579
+ per_page: 10,
580
+ total: 28,
581
+ total_pages: 3,
582
+ data: [
583
+ {
584
+ id: 1,
585
+ email: "michael@example.com",
586
+ first_name: "Michael",
587
+ last_name: "Lawson",
588
+ address: "My home",
589
+ },
590
+ {
591
+ id: 2,
592
+ email: "lindsay@example.com",
593
+ first_name: "Lindsay",
594
+ last_name: "Ferguson",
595
+ address: "My home",
596
+ },
597
+ ],
598
+ },
599
+
600
+ {
601
+ page: 2,
602
+ per_page: 10,
603
+ total: 28,
604
+ total_pages: 3,
605
+ data: [
606
+ {
607
+ id: 11,
608
+ email: "user11@example.com",
609
+ first_name: "John",
610
+ last_name: "Smith",
611
+ address: "My home",
612
+ },
613
+ ],
614
+ },
615
+
616
+ {
617
+ page: 3,
618
+ per_page: 10,
619
+ total: 28,
620
+ total_pages: 3,
621
+ data: [
622
+ {
623
+ id: 21,
624
+ email: "user21@example.com",
625
+ first_name: "Jane",
626
+ last_name: "Doe",
627
+ address: "My home",
628
+ },
629
+ ],
630
+ },
631
+ ];
632
+ ```
633
+
634
+ The `page`, `per_page`, `total`, and `total_pages` properties are useful for preserving the structure of API pagination responses. The PDF template itself uses each page object's `data` array to construct its table.
635
+
636
+ ### Example
637
+
638
+ ```javascript
639
+ import {
640
+ generatePDFTextAndTableWithPagination,
641
+ } from "@speresps/pdf-module/client";
642
+
643
+ const text = "این متن در بالای هر صفحه PDF نمایش داده می‌شود.";
644
+
645
+ const columns = [
646
+ "id",
647
+ "email",
648
+ "first_name",
649
+ "last_name",
650
+ "address",
651
+ ];
652
+
653
+ const footerInfo = {
654
+ siteName: "سایت من",
655
+ address: "خیابان آزادی، تهران",
656
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
657
+ email: "info@mysite.com",
658
+ website: "www.mysite.com",
659
+ };
660
+
661
+ const result = await generatePDFTextAndTableWithPagination({
662
+ text,
663
+ columns,
664
+ paginatedData,
665
+
666
+ headerTitle: "گزارش کاربران",
667
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
668
+
669
+ footerInfo,
670
+
671
+ fileName: "users-report.pdf",
672
+ });
673
+
674
+ if (result.success) {
675
+ console.log("Paginated PDF generated successfully.");
676
+ } else {
677
+ console.error(result.message);
678
+ }
679
+ ```
680
+
681
+ ### Pagination Rules
682
+
683
+ - `text` must be a non-empty string.
684
+ - `columns` must be a non-empty array of strings.
685
+ - `paginatedData` must be a non-empty array.
686
+ - Every pagination item must be an object.
687
+ - Every pagination item must contain a `data` array.
688
+ - Every row in each `data` array must be an object.
689
+ - Column names must correspond to row object keys.
690
+
691
+ **Important:** This method handles data that is already paginated. It does not automatically request additional pages from an API or divide an arbitrary dataset into fixed-size groups. Each supplied pagination item starts a new PDF page.
692
+
693
+ ---
694
+
695
+ ## 5. downloadPDF()
696
+
697
+ Downloads an existing PDF file from the configured PDF storage directory.
698
+
699
+ The method is available through both the server and client entry points, but their behavior differs.
700
+
701
+ ### Client-Side Download
702
+
703
+ Use the client API in a Next.js client component:
704
+
705
+ ```javascript
706
+ import { downloadPDF } from "@speresps/pdf-module/client";
707
+
708
+ const handleDownload = async () => {
709
+ try {
710
+ const result = await downloadPDF("team-report.pdf");
711
+
712
+ if (result.success) {
713
+ console.log("Download started:", result.fileName);
714
+ }
715
+ } catch (error) {
716
+ console.error("PDF download failed:", error.message);
717
+ }
718
+ };
719
+ ```
720
+
721
+ Example button:
722
+
723
+ ```jsx
724
+ <button onClick={handleDownload}>
725
+ Download PDF
726
+ </button>
727
+ ```
728
+
729
+ The client download process:
730
+
731
+ 1. Calls the server-side `getPDFFile()` Server Action.
732
+ 2. Reads the PDF file from the configured storage directory.
733
+ 3. Converts the file buffer into Base64.
734
+ 4. Returns the Base64 data and filename to the browser.
735
+ 5. Converts the Base64 data into a `Blob`.
736
+ 6. Creates a temporary browser download URL.
737
+ 7. Starts the browser download.
738
+ 8. Revokes the temporary URL after the download is initiated.
739
+
740
+ ### Server-Side Download / Read
741
+
742
+ Use the server API when you need to access the saved file as a Node.js Buffer:
743
+
744
+ ```javascript
745
+ import { downloadPDF } from "@speresps/pdf-module/server";
746
+
747
+ const result = await downloadPDF("team-report.pdf");
748
+
749
+ if (result.success) {
750
+ console.log("File name:", result.fileName);
751
+ console.log("PDF buffer:", result.buffer);
752
+ }
753
+ ```
754
+
755
+ The server method returns an object containing:
756
+
757
+ ```javascript
758
+ {
759
+ success: true,
760
+ fileName: "team-report.pdf",
761
+ filePath: "/your-project/files/pdf/team-report.pdf",
762
+ buffer: Buffer
763
+ }
764
+ ```
765
+
766
+ This is a server-side file-reading operation. It does not initiate a browser download.
767
+
768
+ ---
769
+
770
+ # Header Configuration
771
+
772
+ Every PDF template supports a customizable header.
773
+
774
+ The header is configured using:
775
+
776
+ ```javascript
777
+ headerTitle
778
+ headerLogoBase64
779
+ ```
780
+
781
+ ### headerTitle
782
+
783
+ A string displayed as the header title.
784
+
785
+ Example:
786
+
787
+ ```javascript
788
+ headerTitle: "گزارش اطلاعات کاربران"
789
+ ```
790
+
791
+ If omitted, the module uses its default Persian header title.
792
+
793
+ ### headerLogoBase64
794
+
795
+ An optional Base64-encoded image.
796
+
797
+ Example:
798
+
799
+ ```javascript
800
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE"
801
+ ```
802
+
803
+ If omitted, the header is generated without a logo.
804
+
805
+ The header is rendered on PDF pages using the module's shared header template.
806
+
807
+ ---
808
+
809
+ # Footer Configuration
810
+
811
+ All PDF templates support a customizable footer through the `footerInfo` object.
812
+
813
+ ### Expected Structure
814
+
815
+ ```javascript
816
+ const footerInfo = {
817
+ siteName: "سایت من",
818
+ address: "خیابان آزادی، تهران",
819
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
820
+ email: "info@mysite.com",
821
+ website: "www.mysite.com",
822
+ };
823
+ ```
824
+
825
+ ### Footer Properties
826
+
827
+ | Property | Type | Description |
828
+ |---|---|---|
829
+ | `siteName` | `string` | Website or organization name. |
830
+ | `address` | `string` | Organization address. |
831
+ | `phone` | `string` | Contact phone number. |
832
+ | `email` | `string` | Contact email address. |
833
+ | `website` | `string` | Website URL or domain. |
834
+
835
+ All footer properties are optional.
836
+
837
+ If `footerInfo` is omitted, default Persian placeholder values are used.
838
+
839
+ The footer automatically displays the current PDF page and total page count:
840
+
841
+ ```text
842
+ صفحه 1 از 5
843
+ ```
844
+
845
+ The footer is rendered on each PDF page.
846
+
847
+ ---
848
+
849
+ # Logo Requirements
850
+
851
+ The `headerLogoBase64` property expects a Base64 image string that can be used directly by `pdfmake-rtl`.
852
+
853
+ A typical PNG data URL looks like:
854
+
855
+ ```javascript
856
+ const logoBase64 = "data:image/png;base64,BASE64_IMAGE_CONTENT";
857
+ ```
858
+
859
+ You can convert an image into a Base64 data URL using an image-to-Base64 utility.
860
+
861
+ Pass the complete Base64 string to the generation method:
862
+
863
+ ```javascript
864
+ await generatePDFText({
865
+ text: "متن نمونه",
866
+ headerTitle: "عنوان گزارش",
867
+ headerLogoBase64: logoBase64,
868
+ });
869
+ ```
870
+
871
+ The image is optional. When it is not supplied, the PDF header displays the title without an image.
872
+
873
+ ---
874
+
875
+ # PDF Generation Examples
876
+
877
+ The following examples show how to use the four methods in a Next.js client component.
878
+
879
+ ### Example 1: Generate and Download a Table PDF
880
+
881
+ ```javascript
882
+ "use client";
883
+
884
+ import {
885
+ generatePDFTable,
886
+ downloadPDF,
887
+ } from "@speresps/pdf-module/client";
888
+
889
+ export default function TablePage() {
890
+
891
+ const fileName = "team-members.pdf";
892
+
893
+ const columns = ["نام", "سن", "شغل"];
894
+
895
+ const tableData = [
896
+ { نام: "علی", سن: 30, شغل: "برنامه‌نویس" },
897
+ { نام: "سارا", سن: 28, شغل: "طراح گرافیک" },
898
+ ];
899
+
900
+ const handleGenerate = async () => {
901
+
902
+ const result = await generatePDFTable({
903
+ columns,
904
+ tableData,
905
+ headerTitle: "لیست اعضای تیم",
906
+ fileName,
907
+ });
908
+
909
+ if (!result.success) {
910
+ console.error(result.message);
911
+ return;
912
+ }
913
+
914
+ console.log("PDF generated successfully.");
915
+ };
916
+
917
+ const handleDownload = async () => {
918
+ await downloadPDF(fileName);
919
+ };
920
+
921
+ return (
922
+ <div>
923
+ <button onClick={handleGenerate}>
924
+ Generate PDF
925
+ </button>
926
+
927
+ <button onClick={handleDownload}>
928
+ Download PDF
929
+ </button>
930
+ </div>
931
+ );
932
+ }
933
+ ```
934
+
935
+ ### Example 2: Generate and Download a Text PDF
936
+
937
+ ```javascript
938
+ "use client";
939
+
940
+ import {
941
+ generatePDFText,
942
+ downloadPDF,
943
+ } from "@speresps/pdf-module/client";
944
+
945
+ export default function TextPage() {
946
+
947
+ const fileName = "text-report.pdf";
948
+
949
+ const handleGenerate = async () => {
950
+
951
+ const result = await generatePDFText({
952
+ text: "این یک متن نمونه فارسی است.",
953
+ headerTitle: "گزارش متنی",
954
+ fileName,
955
+ });
956
+
957
+ if (!result.success) {
958
+ console.error(result.message);
959
+ }
960
+ };
961
+
962
+ const handleDownload = async () => {
963
+ await downloadPDF(fileName);
964
+ };
965
+
966
+ return (
967
+ <div>
968
+ <button onClick={handleGenerate}>
969
+ Generate PDF
970
+ </button>
971
+
972
+ <button onClick={handleDownload}>
973
+ Download PDF
974
+ </button>
975
+ </div>
976
+ );
977
+ }
978
+ ```
979
+
980
+ ---
981
+
982
+ # Server-Side Usage
983
+
984
+ The module can also be used directly in Node.js server-side code and Next.js server-side modules.
985
+
986
+ Import the server API:
987
+
988
+ ```javascript
989
+ import {
990
+ generatePDFTable,
991
+ generatePDFText,
992
+ generatePDFTextAndTable,
993
+ generatePDFTextAndTableWithPagination,
994
+ downloadPDF,
995
+ } from "@speresps/pdf-module";
996
+ ```
997
+
998
+ Example:
999
+
1000
+ ```javascript
1001
+ const result = await generatePDFText({
1002
+ text: "Server-side PDF generation example.",
1003
+ headerTitle: "Server Report",
1004
+ fileName: "server-report.pdf",
1005
+ });
1006
+
1007
+ if (result.success) {
1008
+ console.log("PDF saved:", result.result.fileName);
1009
+ } else {
1010
+ console.error("PDF generation failed:", result.message);
1011
+ }
1012
+ ```
1013
+
1014
+ The server API generates the PDF and saves it to the configured PDF directory. It does not provide a browser download automatically.
1015
+
1016
+ ---
1017
+
1018
+ # PDF Storage
1019
+
1020
+ All generated PDFs are saved to the directory configured through:
1021
+
1022
+ ```ini
1023
+ MAIN_FOLDER_NAME = files
1024
+ PDF_FOLDER_NAME = pdf
1025
+ ```
1026
+
1027
+ Default storage location:
1028
+
1029
+ ```text
1030
+ your-project/
1031
+ └── files/
1032
+ └── pdf/
1033
+ └── generated-report.pdf
1034
+ ```
1035
+
1036
+ You can change the directory names through `pdf.conf`.
1037
+
1038
+ For example:
1039
+
1040
+ ```ini
1041
+ MAIN_FOLDER_NAME = documents
1042
+ PDF_FOLDER_NAME = reports
1043
+ ```
1044
+
1045
+ The resulting directory becomes:
1046
+
1047
+ ```text
1048
+ your-project/
1049
+ └── documents/
1050
+ └── reports/
1051
+ └── generated-report.pdf
1052
+ ```
1053
+
1054
+ ### Custom File Names
1055
+
1056
+ You can supply a custom filename to every generation method:
1057
+
1058
+ ```javascript
1059
+ fileName: "monthly-report.pdf"
1060
+ ```
1061
+
1062
+ If `fileName` is omitted, the module uses the corresponding default filename from `pdf.conf`.
1063
+
1064
+ PDF filenames must have the `.pdf` extension.
1065
+
1066
+ ### Important: File Access
1067
+
1068
+ The module provides file storage and reading functionality, but it does not implement application-level user authentication or authorization.
1069
+
1070
+ Applications that expose PDF downloads must verify that the requesting user is authorized to access the requested file. Do not allow untrusted users to download arbitrary files by supplying filenames.
1071
+
1072
+ ---
1073
+
1074
+ # Return Values and Error Handling
1075
+
1076
+ The four PDF generation methods return a Promise resolving to an object.
1077
+
1078
+ ### Successful Generation
1079
+
1080
+ ```javascript
1081
+ {
1082
+ success: true,
1083
+ result: {
1084
+ success: true,
1085
+ fileName: "report.pdf",
1086
+ filePath: "/your-project/files/pdf/report.pdf"
1087
+ }
1088
+ }
1089
+ ```
1090
+
1091
+ ### Failed Generation
1092
+
1093
+ ```javascript
1094
+ {
1095
+ success: false,
1096
+ message: "Error description"
1097
+ }
1098
+ ```
1099
+
1100
+ The service catches errors during validation, PDF creation, buffer generation, and file storage, and returns an error object.
1101
+
1102
+ ### Recommended Usage
1103
+
1104
+ ```javascript
1105
+ const result = await generatePDFText({
1106
+ text: "Sample PDF content",
1107
+ headerTitle: "Sample Report",
1108
+ fileName: "sample.pdf",
1109
+ });
1110
+
1111
+ if (result.success) {
1112
+ console.log("PDF created:", result.result.fileName);
1113
+ } else {
1114
+ console.error("PDF generation failed:", result.message);
1115
+ }
1116
+ ```
1117
+
1118
+ For file-reading operations, errors such as missing files or invalid filenames are thrown and should be handled with `try/catch`.
1119
+
1120
+ ```javascript
1121
+ try {
1122
+ const result = await downloadPDF("sample.pdf");
1123
+
1124
+ console.log(result.buffer);
1125
+ } catch (error) {
1126
+ console.error(error.message);
1127
+ }
1128
+ ```
1129
+
1130
+ ---
1131
+
1132
+ # Important Notes
1133
+
1134
+ 1. **Configuration is required:** The consuming application must provide `config/pdf.conf` in its project root. The module loads it during initialization.
1135
+
1136
+ 2. **Dependencies:** The module uses `@speresps/config-module`, `@speresps/report-module`, and `pdfmake-rtl`. These are declared runtime dependencies and are installed through npm.
1137
+
1138
+ 3. **Node.js environment:** PDF generation and file storage are server-side operations. Do not import the server entry point into browser-only code.
1139
+
1140
+ 4. **Next.js client usage:** Use `@speresps/pdf-module/client` from client components. Its generation methods communicate with the server through Next.js Server Actions.
1141
+
1142
+ 5. **Browser downloads:** Generate the PDF first and then call `downloadPDF(fileName)` to download it through the client API.
1143
+
1144
+ 6. **Unique filenames:** When generating multiple reports, use unique filenames to avoid overwriting existing PDFs.
1145
+
1146
+ 7. **Pagination:** `generatePDFTextAndTableWithPagination()` expects already-paginated data. Every supplied page object creates a separate PDF page.
1147
+
1148
+ 8. **Fonts:** Vazirmatn font data is embedded in the module. The consuming project does not need to install or register these fonts separately.
1149
+
1150
+ 9. **Header and footer:** All four templates support the shared header and footer configuration.
1151
+
1152
+ 10. **Large PDFs:** The client download implementation transfers PDF content as Base64 through a Server Action. This is convenient for ordinary reports, but very large PDFs may require a streaming or dedicated HTTP download approach.
1153
+
1154
+ 11. **File authorization:** Protect file-download operations in the consuming application. The module does not provide user-level access control.
1155
+
1156
+ 12. **Filename configuration:** The default filenames are configured in `pdf.conf`, but each generation method can override its filename using the `fileName` property.
1157
+
1158
+ ---
1159
+
1160
+ # License
1161
+
1162
+ MIT
1163
+
1164
+ ---
1165
+
1166
+ ## Author
1167
+
1168
+ **speresps**