@speresps/pdf-module 0.0.0-stage → 1.0.1

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,1171 @@
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
+ existsPDF,
224
+ downloadPDF,
225
+ } from "@speresps/pdf-module";
226
+ ```
227
+
228
+ Equivalent explicit server import:
229
+
230
+ ```javascript
231
+ import {
232
+ generatePDFTable,
233
+ generatePDFText,
234
+ generatePDFTextAndTable,
235
+ generatePDFTextAndTableWithPagination,
236
+ existsPDF,
237
+ downloadPDF,
238
+ } from "@speresps/pdf-module/server";
239
+ ```
240
+
241
+ ### 2. Client Entry Point
242
+
243
+ For Next.js client components:
244
+
245
+ ```javascript
246
+ import {
247
+ generatePDFTable,
248
+ generatePDFText,
249
+ generatePDFTextAndTable,
250
+ generatePDFTextAndTableWithPagination,
251
+ existsPDF,
252
+ downloadPDF,
253
+ } from "@speresps/pdf-module/client";
254
+ ```
255
+
256
+ The client entry point provides Server Action wrappers for PDF generation and a browser download helper.
257
+
258
+ **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.
259
+
260
+ ---
261
+
262
+ # API Reference
263
+
264
+ All four generation methods receive a single JavaScript object containing the PDF data and optional presentation settings.
265
+
266
+ Common properties:
267
+
268
+ | Property | Type | Required | Description |
269
+ |---|---|---|---|
270
+ | `headerTitle` | `string` | No | Text displayed in the PDF header. |
271
+ | `headerLogoBase64` | `string` | No | Base64 image data for the header logo. |
272
+ | `footerInfo` | `object` | No | Website and contact information displayed in the footer. |
273
+ | `fileName` | `string` | No | Name used when saving the generated PDF. |
274
+ | `autoDownload` | `boolean` | No | Passed through by the generation service, but does not currently trigger automatic downloading through the public API. |
275
+
276
+ The required content properties differ depending on the selected PDF method.
277
+
278
+ ---
279
+
280
+ ## 1. generatePDFTable()
281
+
282
+ Generates a PDF containing a table, including the configured header and footer.
283
+
284
+ ### Method Signature
285
+
286
+ ```javascript
287
+ generatePDFTable({
288
+ columns,
289
+ tableData,
290
+ headerTitle,
291
+ headerLogoBase64,
292
+ footerInfo,
293
+ fileName,
294
+ });
295
+ ```
296
+
297
+ ### Required Properties
298
+
299
+ | Property | Type | Required | Description |
300
+ |---|---|---|---|
301
+ | `columns` | `string[]` | Yes | Array of column names. |
302
+ | `tableData` | `object[]` | Yes | Array of row objects. |
303
+
304
+ Each column name must correspond to a property in the table row objects.
305
+
306
+ ### Example
307
+
308
+ ```javascript
309
+ import { generatePDFTable } from "@speresps/pdf-module/client";
310
+
311
+ const columns = [
312
+ "نام",
313
+ "سن",
314
+ "شغل",
315
+ "آدرس",
316
+ "تلفن",
317
+ "جنسیت",
318
+ ];
319
+
320
+ const tableData = [
321
+ {
322
+ نام: "سارا",
323
+ سن: 28,
324
+ شغل: "طراح گرافیک",
325
+ آدرس: "خیابان انقلاب، تهران",
326
+ تلفن: "09123456789",
327
+ جنسیت: "زن",
328
+ },
329
+ {
330
+ نام: "علی",
331
+ سن: 30,
332
+ شغل: "برنامه‌نویس",
333
+ آدرس: "خیابان آزادی، تهران",
334
+ تلفن: "09123456789",
335
+ جنسیت: "مرد",
336
+ },
337
+ ];
338
+
339
+ const footerInfo = {
340
+ siteName: "سایت من",
341
+ address: "خیابان انقلاب، تهران",
342
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
343
+ email: "info@mysite.com",
344
+ website: "www.mysite.com",
345
+ };
346
+
347
+ const result = await generatePDFTable({
348
+ columns,
349
+ tableData,
350
+
351
+ headerTitle: "لیست اعضای تیم",
352
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
353
+
354
+ footerInfo,
355
+
356
+ fileName: "team-members.pdf",
357
+ });
358
+
359
+ if (result.success) {
360
+ console.log("PDF generated successfully.");
361
+ } else {
362
+ console.error(result.message);
363
+ }
364
+ ```
365
+
366
+ ### Table Data Rules
367
+
368
+ - `columns` must be a non-empty array of non-empty strings.
369
+ - `tableData` must be an array.
370
+ - Every row must be a JavaScript object.
371
+ - Column names must match the keys in the row objects.
372
+ - Missing row values are rendered as empty strings.
373
+
374
+ The table template calculates column widths and selects portrait or landscape orientation based on the estimated table width.
375
+
376
+ ---
377
+
378
+ ## 2. generatePDFText()
379
+
380
+ Generates a PDF containing text with a customizable header and footer.
381
+
382
+ ### Method Signature
383
+
384
+ ```javascript
385
+ generatePDFText({
386
+ text,
387
+ headerTitle,
388
+ headerLogoBase64,
389
+ footerInfo,
390
+ fileName,
391
+ });
392
+ ```
393
+
394
+ ### Required Properties
395
+
396
+ | Property | Type | Required | Description |
397
+ |---|---|---|---|
398
+ | `text` | `string` | Yes | Main PDF content. |
399
+
400
+ ### Example
401
+
402
+ ```javascript
403
+ import { generatePDFText } from "@speresps/pdf-module/client";
404
+
405
+ const text = `
406
+ این یک متن نمونه فارسی است.
407
+
408
+ این متن در فایل PDF نمایش داده می‌شود.
409
+ فونت Vazirmatn برای نمایش صحیح متن فارسی استفاده می‌شود.
410
+ `;
411
+
412
+ const footerInfo = {
413
+ siteName: "سایت من",
414
+ address: "خیابان آزادی، تهران",
415
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
416
+ email: "info@mysite.com",
417
+ website: "www.mysite.com",
418
+ };
419
+
420
+ const result = await generatePDFText({
421
+ text,
422
+
423
+ headerTitle: "آموزش برنامه نویسی",
424
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
425
+
426
+ footerInfo,
427
+
428
+ fileName: "programming-report.pdf",
429
+ });
430
+
431
+ if (result.success) {
432
+ console.log("PDF generated successfully.");
433
+ } else {
434
+ console.error(result.message);
435
+ }
436
+ ```
437
+
438
+ ### Text Data Rules
439
+
440
+ - `text` must be a non-empty string.
441
+ - Persian and RTL text are supported.
442
+ - The text is displayed with right alignment and the embedded Vazirmatn font.
443
+
444
+ ---
445
+
446
+ ## 3. generatePDFTextAndTable()
447
+
448
+ Generates a PDF containing a text section followed by a table.
449
+
450
+ This template is suitable for reports that require an introduction, description, or summary above tabular information.
451
+
452
+ ### Method Signature
453
+
454
+ ```javascript
455
+ generatePDFTextAndTable({
456
+ text,
457
+ columns,
458
+ tableData,
459
+ headerTitle,
460
+ headerLogoBase64,
461
+ footerInfo,
462
+ fileName,
463
+ });
464
+ ```
465
+
466
+ ### Required Properties
467
+
468
+ | Property | Type | Required | Description |
469
+ |---|---|---|---|
470
+ | `text` | `string` | Yes | Text displayed above the table. |
471
+ | `columns` | `string[]` | Yes | Table column names. |
472
+ | `tableData` | `object[]` | Yes | Table rows. |
473
+
474
+ ### Example
475
+
476
+ ```javascript
477
+ import { generatePDFTextAndTable } from "@speresps/pdf-module/client";
478
+
479
+ const text = "این گزارش شامل اطلاعات اعضای تیم است.";
480
+
481
+ const columns = [
482
+ "نام",
483
+ "سن",
484
+ "شغل",
485
+ ];
486
+
487
+ const tableData = [
488
+ {
489
+ نام: "علی",
490
+ سن: 30,
491
+ شغل: "برنامه‌نویس",
492
+ },
493
+ {
494
+ نام: "سارا",
495
+ سن: 28,
496
+ شغل: "طراح گرافیک",
497
+ },
498
+ {
499
+ نام: "رضا",
500
+ سن: 30,
501
+ شغل: "مدیر پروژه",
502
+ },
503
+ ];
504
+
505
+ const footerInfo = {
506
+ siteName: "سایت من",
507
+ address: "خیابان آزادی، تهران",
508
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
509
+ email: "info@mysite.com",
510
+ website: "www.mysite.com",
511
+ };
512
+
513
+ const result = await generatePDFTextAndTable({
514
+ text,
515
+ columns,
516
+ tableData,
517
+
518
+ headerTitle: "گزارش اعضای تیم",
519
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
520
+
521
+ footerInfo,
522
+
523
+ fileName: "team-report.pdf",
524
+ });
525
+
526
+ if (result.success) {
527
+ console.log("PDF generated successfully.");
528
+ } else {
529
+ console.error(result.message);
530
+ }
531
+ ```
532
+
533
+ ### Content Layout
534
+
535
+ The generated document contains:
536
+
537
+ 1. Header with title and optional logo.
538
+ 2. Main text section.
539
+ 3. Table with column headings and data rows.
540
+ 4. Footer with website/contact information and page numbering.
541
+
542
+ ---
543
+
544
+ ## 4. generatePDFTextAndTableWithPagination()
545
+
546
+ Generates a PDF using externally paginated table data.
547
+
548
+ This method is designed for data retrieved from APIs or database queries that already return records grouped into pages.
549
+
550
+ 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.
551
+
552
+ ### Method Signature
553
+
554
+ ```javascript
555
+ generatePDFTextAndTableWithPagination({
556
+ text,
557
+ columns,
558
+ paginatedData,
559
+ headerTitle,
560
+ headerLogoBase64,
561
+ footerInfo,
562
+ fileName,
563
+ });
564
+ ```
565
+
566
+ ### Required Properties
567
+
568
+ | Property | Type | Required | Description |
569
+ |---|---|---|---|
570
+ | `text` | `string` | Yes | Text displayed above each page's table. |
571
+ | `columns` | `string[]` | Yes | Table column names. |
572
+ | `paginatedData` | `object[]` | Yes | Array of page objects, each containing a `data` array. |
573
+
574
+ ### paginatedData Structure
575
+
576
+ The expected structure is:
577
+
578
+ ```javascript
579
+ const paginatedData = [
580
+ {
581
+ page: 1,
582
+ per_page: 10,
583
+ total: 28,
584
+ total_pages: 3,
585
+ data: [
586
+ {
587
+ id: 1,
588
+ email: "michael@example.com",
589
+ first_name: "Michael",
590
+ last_name: "Lawson",
591
+ address: "My home",
592
+ },
593
+ {
594
+ id: 2,
595
+ email: "lindsay@example.com",
596
+ first_name: "Lindsay",
597
+ last_name: "Ferguson",
598
+ address: "My home",
599
+ },
600
+ ],
601
+ },
602
+
603
+ {
604
+ page: 2,
605
+ per_page: 10,
606
+ total: 28,
607
+ total_pages: 3,
608
+ data: [
609
+ {
610
+ id: 11,
611
+ email: "user11@example.com",
612
+ first_name: "John",
613
+ last_name: "Smith",
614
+ address: "My home",
615
+ },
616
+ ],
617
+ },
618
+
619
+ {
620
+ page: 3,
621
+ per_page: 10,
622
+ total: 28,
623
+ total_pages: 3,
624
+ data: [
625
+ {
626
+ id: 21,
627
+ email: "user21@example.com",
628
+ first_name: "Jane",
629
+ last_name: "Doe",
630
+ address: "My home",
631
+ },
632
+ ],
633
+ },
634
+ ];
635
+ ```
636
+
637
+ 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.
638
+
639
+ ### Example
640
+
641
+ ```javascript
642
+ import {
643
+ generatePDFTextAndTableWithPagination,
644
+ } from "@speresps/pdf-module/client";
645
+
646
+ const text = "این متن در بالای هر صفحه PDF نمایش داده می‌شود.";
647
+
648
+ const columns = [
649
+ "id",
650
+ "email",
651
+ "first_name",
652
+ "last_name",
653
+ "address",
654
+ ];
655
+
656
+ const footerInfo = {
657
+ siteName: "سایت من",
658
+ address: "خیابان آزادی، تهران",
659
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
660
+ email: "info@mysite.com",
661
+ website: "www.mysite.com",
662
+ };
663
+
664
+ const result = await generatePDFTextAndTableWithPagination({
665
+ text,
666
+ columns,
667
+ paginatedData,
668
+
669
+ headerTitle: "گزارش کاربران",
670
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE",
671
+
672
+ footerInfo,
673
+
674
+ fileName: "users-report.pdf",
675
+ });
676
+
677
+ if (result.success) {
678
+ console.log("Paginated PDF generated successfully.");
679
+ } else {
680
+ console.error(result.message);
681
+ }
682
+ ```
683
+
684
+ ### Pagination Rules
685
+
686
+ - `text` must be a non-empty string.
687
+ - `columns` must be a non-empty array of strings.
688
+ - `paginatedData` must be a non-empty array.
689
+ - Every pagination item must be an object.
690
+ - Every pagination item must contain a `data` array.
691
+ - Every row in each `data` array must be an object.
692
+ - Column names must correspond to row object keys.
693
+
694
+ **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.
695
+
696
+ ---
697
+
698
+ ## 5. downloadPDF()
699
+
700
+ Downloads an existing PDF file from the configured PDF storage directory.
701
+
702
+ The method is available through both the server and client entry points, but their behavior differs.
703
+
704
+ ### Client-Side Download
705
+
706
+ Use the client API in a Next.js client component:
707
+
708
+ ```javascript
709
+ import { downloadPDF } from "@speresps/pdf-module/client";
710
+
711
+ const handleDownload = async () => {
712
+ try {
713
+ const result = await downloadPDF("team-report.pdf");
714
+
715
+ if (result.success) {
716
+ console.log("Download started:", result.fileName);
717
+ }
718
+ } catch (error) {
719
+ console.error("PDF download failed:", error.message);
720
+ }
721
+ };
722
+ ```
723
+
724
+ Example button:
725
+
726
+ ```jsx
727
+ <button onClick={handleDownload}>
728
+ Download PDF
729
+ </button>
730
+ ```
731
+
732
+ The client download process:
733
+
734
+ 1. Calls the server-side `getPDFFile()` Server Action.
735
+ 2. Reads the PDF file from the configured storage directory.
736
+ 3. Converts the file buffer into Base64.
737
+ 4. Returns the Base64 data and filename to the browser.
738
+ 5. Converts the Base64 data into a `Blob`.
739
+ 6. Creates a temporary browser download URL.
740
+ 7. Starts the browser download.
741
+ 8. Revokes the temporary URL after the download is initiated.
742
+
743
+ ### Server-Side Download / Read / Exists
744
+
745
+ Use the server API when you need to access the saved file as a Node.js Buffer:
746
+
747
+ ```javascript
748
+ import { downloadPDF } from "@speresps/pdf-module/server";
749
+
750
+ const result = await downloadPDF("team-report.pdf");
751
+
752
+ if (result.success) {
753
+ console.log("File name:", result.fileName);
754
+ console.log("PDF buffer:", result.buffer);
755
+ }
756
+ ```
757
+
758
+ The server method returns an object containing:
759
+
760
+ ```javascript
761
+ {
762
+ success: true,
763
+ fileName: "team-report.pdf",
764
+ filePath: "/your-project/files/pdf/team-report.pdf",
765
+ buffer: Buffer
766
+ }
767
+ ```
768
+
769
+ This is a server-side file-reading operation. It does not initiate a browser download.
770
+
771
+ ---
772
+
773
+ # Header Configuration
774
+
775
+ Every PDF template supports a customizable header.
776
+
777
+ The header is configured using:
778
+
779
+ ```javascript
780
+ headerTitle
781
+ headerLogoBase64
782
+ ```
783
+
784
+ ### headerTitle
785
+
786
+ A string displayed as the header title.
787
+
788
+ Example:
789
+
790
+ ```javascript
791
+ headerTitle: "گزارش اطلاعات کاربران"
792
+ ```
793
+
794
+ If omitted, the module uses its default Persian header title.
795
+
796
+ ### headerLogoBase64
797
+
798
+ An optional Base64-encoded image.
799
+
800
+ Example:
801
+
802
+ ```javascript
803
+ headerLogoBase64: "data:image/png;base64,YOUR_COMPLETE_BASE64_IMAGE"
804
+ ```
805
+
806
+ If omitted, the header is generated without a logo.
807
+
808
+ The header is rendered on PDF pages using the module's shared header template.
809
+
810
+ ---
811
+
812
+ # Footer Configuration
813
+
814
+ All PDF templates support a customizable footer through the `footerInfo` object.
815
+
816
+ ### Expected Structure
817
+
818
+ ```javascript
819
+ const footerInfo = {
820
+ siteName: "سایت من",
821
+ address: "خیابان آزادی، تهران",
822
+ phone: "۰۲۱-۱۲۳۴۵۶۷۸",
823
+ email: "info@mysite.com",
824
+ website: "www.mysite.com",
825
+ };
826
+ ```
827
+
828
+ ### Footer Properties
829
+
830
+ | Property | Type | Description |
831
+ |---|---|---|
832
+ | `siteName` | `string` | Website or organization name. |
833
+ | `address` | `string` | Organization address. |
834
+ | `phone` | `string` | Contact phone number. |
835
+ | `email` | `string` | Contact email address. |
836
+ | `website` | `string` | Website URL or domain. |
837
+
838
+ All footer properties are optional.
839
+
840
+ If `footerInfo` is omitted, default Persian placeholder values are used.
841
+
842
+ The footer automatically displays the current PDF page and total page count:
843
+
844
+ ```text
845
+ صفحه 1 از 5
846
+ ```
847
+
848
+ The footer is rendered on each PDF page.
849
+
850
+ ---
851
+
852
+ # Logo Requirements
853
+
854
+ The `headerLogoBase64` property expects a Base64 image string that can be used directly by `pdfmake-rtl`.
855
+
856
+ A typical PNG data URL looks like:
857
+
858
+ ```javascript
859
+ const logoBase64 = "data:image/png;base64,BASE64_IMAGE_CONTENT";
860
+ ```
861
+
862
+ You can convert an image into a Base64 data URL using an image-to-Base64 utility.
863
+
864
+ Pass the complete Base64 string to the generation method:
865
+
866
+ ```javascript
867
+ await generatePDFText({
868
+ text: "متن نمونه",
869
+ headerTitle: "عنوان گزارش",
870
+ headerLogoBase64: logoBase64,
871
+ });
872
+ ```
873
+
874
+ The image is optional. When it is not supplied, the PDF header displays the title without an image.
875
+
876
+ ---
877
+
878
+ # PDF Generation Examples
879
+
880
+ The following examples show how to use the four methods in a Next.js client component.
881
+
882
+ ### Example 1: Generate and Download a Table PDF
883
+
884
+ ```javascript
885
+ "use client";
886
+
887
+ import {
888
+ generatePDFTable,
889
+ downloadPDF,
890
+ } from "@speresps/pdf-module/client";
891
+
892
+ export default function TablePage() {
893
+
894
+ const fileName = "team-members.pdf";
895
+
896
+ const columns = ["نام", "سن", "شغل"];
897
+
898
+ const tableData = [
899
+ { نام: "علی", سن: 30, شغل: "برنامه‌نویس" },
900
+ { نام: "سارا", سن: 28, شغل: "طراح گرافیک" },
901
+ ];
902
+
903
+ const handleGenerate = async () => {
904
+
905
+ const result = await generatePDFTable({
906
+ columns,
907
+ tableData,
908
+ headerTitle: "لیست اعضای تیم",
909
+ fileName,
910
+ });
911
+
912
+ if (!result.success) {
913
+ console.error(result.message);
914
+ return;
915
+ }
916
+
917
+ console.log("PDF generated successfully.");
918
+ };
919
+
920
+ const handleDownload = async () => {
921
+ await downloadPDF(fileName);
922
+ };
923
+
924
+ return (
925
+ <div>
926
+ <button onClick={handleGenerate}>
927
+ Generate PDF
928
+ </button>
929
+
930
+ <button onClick={handleDownload}>
931
+ Download PDF
932
+ </button>
933
+ </div>
934
+ );
935
+ }
936
+ ```
937
+
938
+ ### Example 2: Generate and Download a Text PDF
939
+
940
+ ```javascript
941
+ "use client";
942
+
943
+ import {
944
+ generatePDFText,
945
+ downloadPDF,
946
+ } from "@speresps/pdf-module/client";
947
+
948
+ export default function TextPage() {
949
+
950
+ const fileName = "text-report.pdf";
951
+
952
+ const handleGenerate = async () => {
953
+
954
+ const result = await generatePDFText({
955
+ text: "این یک متن نمونه فارسی است.",
956
+ headerTitle: "گزارش متنی",
957
+ fileName,
958
+ });
959
+
960
+ if (!result.success) {
961
+ console.error(result.message);
962
+ }
963
+ };
964
+
965
+ const handleDownload = async () => {
966
+ await downloadPDF(fileName);
967
+ };
968
+
969
+ return (
970
+ <div>
971
+ <button onClick={handleGenerate}>
972
+ Generate PDF
973
+ </button>
974
+
975
+ <button onClick={handleDownload}>
976
+ Download PDF
977
+ </button>
978
+ </div>
979
+ );
980
+ }
981
+ ```
982
+
983
+ ---
984
+
985
+ # Server-Side Usage
986
+
987
+ The module can also be used directly in Node.js server-side code and Next.js server-side modules.
988
+
989
+ Import the server API:
990
+
991
+ ```javascript
992
+ import {
993
+ generatePDFTable,
994
+ generatePDFText,
995
+ generatePDFTextAndTable,
996
+ generatePDFTextAndTableWithPagination,
997
+ downloadPDF,
998
+ } from "@speresps/pdf-module";
999
+ ```
1000
+
1001
+ Example:
1002
+
1003
+ ```javascript
1004
+ const result = await generatePDFText({
1005
+ text: "Server-side PDF generation example.",
1006
+ headerTitle: "Server Report",
1007
+ fileName: "server-report.pdf",
1008
+ });
1009
+
1010
+ if (result.success) {
1011
+ console.log("PDF saved:", result.result.fileName);
1012
+ } else {
1013
+ console.error("PDF generation failed:", result.message);
1014
+ }
1015
+ ```
1016
+
1017
+ The server API generates the PDF and saves it to the configured PDF directory. It does not provide a browser download automatically.
1018
+
1019
+ ---
1020
+
1021
+ # PDF Storage
1022
+
1023
+ All generated PDFs are saved to the directory configured through:
1024
+
1025
+ ```ini
1026
+ MAIN_FOLDER_NAME = files
1027
+ PDF_FOLDER_NAME = pdf
1028
+ ```
1029
+
1030
+ Default storage location:
1031
+
1032
+ ```text
1033
+ your-project/
1034
+ └── files/
1035
+ └── pdf/
1036
+ └── generated-report.pdf
1037
+ ```
1038
+
1039
+ You can change the directory names through `pdf.conf`.
1040
+
1041
+ For example:
1042
+
1043
+ ```ini
1044
+ MAIN_FOLDER_NAME = documents
1045
+ PDF_FOLDER_NAME = reports
1046
+ ```
1047
+
1048
+ The resulting directory becomes:
1049
+
1050
+ ```text
1051
+ your-project/
1052
+ └── documents/
1053
+ └── reports/
1054
+ └── generated-report.pdf
1055
+ ```
1056
+
1057
+ ### Custom File Names
1058
+
1059
+ You can supply a custom filename to every generation method:
1060
+
1061
+ ```javascript
1062
+ fileName: "monthly-report.pdf"
1063
+ ```
1064
+
1065
+ If `fileName` is omitted, the module uses the corresponding default filename from `pdf.conf`.
1066
+
1067
+ PDF filenames must have the `.pdf` extension.
1068
+
1069
+ ### Important: File Access
1070
+
1071
+ The module provides file storage and reading functionality, but it does not implement application-level user authentication or authorization.
1072
+
1073
+ 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.
1074
+
1075
+ ---
1076
+
1077
+ # Return Values and Error Handling
1078
+
1079
+ The four PDF generation methods return a Promise resolving to an object.
1080
+
1081
+ ### Successful Generation
1082
+
1083
+ ```javascript
1084
+ {
1085
+ success: true,
1086
+ result: {
1087
+ success: true,
1088
+ fileName: "report.pdf",
1089
+ filePath: "/your-project/files/pdf/report.pdf"
1090
+ }
1091
+ }
1092
+ ```
1093
+
1094
+ ### Failed Generation
1095
+
1096
+ ```javascript
1097
+ {
1098
+ success: false,
1099
+ message: "Error description"
1100
+ }
1101
+ ```
1102
+
1103
+ The service catches errors during validation, PDF creation, buffer generation, and file storage, and returns an error object.
1104
+
1105
+ ### Recommended Usage
1106
+
1107
+ ```javascript
1108
+ const result = await generatePDFText({
1109
+ text: "Sample PDF content",
1110
+ headerTitle: "Sample Report",
1111
+ fileName: "sample.pdf",
1112
+ });
1113
+
1114
+ if (result.success) {
1115
+ console.log("PDF created:", result.result.fileName);
1116
+ } else {
1117
+ console.error("PDF generation failed:", result.message);
1118
+ }
1119
+ ```
1120
+
1121
+ For file-reading operations, errors such as missing files or invalid filenames are thrown and should be handled with `try/catch`.
1122
+
1123
+ ```javascript
1124
+ try {
1125
+ const result = await downloadPDF("sample.pdf");
1126
+
1127
+ console.log(result.buffer);
1128
+ } catch (error) {
1129
+ console.error(error.message);
1130
+ }
1131
+ ```
1132
+
1133
+ ---
1134
+
1135
+ # Important Notes
1136
+
1137
+ 1. **Configuration is required:** The consuming application must provide `config/pdf.conf` in its project root. The module loads it during initialization.
1138
+
1139
+ 2. **Dependencies:** The module uses `@speresps/config-module`, `@speresps/report-module`, and `pdfmake-rtl`. These are declared runtime dependencies and are installed through npm.
1140
+
1141
+ 3. **Node.js environment:** PDF generation and file storage are server-side operations. Do not import the server entry point into browser-only code.
1142
+
1143
+ 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.
1144
+
1145
+ 5. **Browser downloads:** Generate the PDF first and then call `downloadPDF(fileName)` to download it through the client API.
1146
+
1147
+ 6. **Unique filenames:** When generating multiple reports, use unique filenames to avoid overwriting existing PDFs.
1148
+
1149
+ 7. **Pagination:** `generatePDFTextAndTableWithPagination()` expects already-paginated data. Every supplied page object creates a separate PDF page.
1150
+
1151
+ 8. **Fonts:** Vazirmatn font data is embedded in the module. The consuming project does not need to install or register these fonts separately.
1152
+
1153
+ 9. **Header and footer:** All four templates support the shared header and footer configuration.
1154
+
1155
+ 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.
1156
+
1157
+ 11. **File authorization:** Protect file-download operations in the consuming application. The module does not provide user-level access control.
1158
+
1159
+ 12. **Filename configuration:** The default filenames are configured in `pdf.conf`, but each generation method can override its filename using the `fileName` property.
1160
+
1161
+ ---
1162
+
1163
+ # License
1164
+
1165
+ MIT
1166
+
1167
+ ---
1168
+
1169
+ ## Author
1170
+
1171
+ **speresps**