@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.
@@ -0,0 +1,45 @@
1
+ "use server";
2
+
3
+ import generatePdfService from "../../service/generatePdfService.js";
4
+ import pdfFileService from "../../service/pdfFileService.js";
5
+
6
+
7
+
8
+ export async function generatePDFTable(data) {
9
+ return await generatePdfService.PDFTable(data);
10
+ }
11
+
12
+ export async function generatePDFText(data) {
13
+ return await generatePdfService.PDFText(data);
14
+ }
15
+
16
+ export async function generatePDFTextAndTable(data) {
17
+ return await generatePdfService.PDFTextAndTable(data);
18
+ }
19
+
20
+ export async function generatePDFTextAndTableWithPagination(data) {
21
+ return await generatePdfService.PDFTextAndTableWithPagination(data);
22
+ }
23
+
24
+ export async function existsPDF(fileName) {
25
+ return await pdfFileService.exists(fileName);
26
+ }
27
+
28
+ export async function getPDFFile (fileName) {
29
+
30
+ if (typeof fileName !== "string" || !fileName.trim()) {
31
+ throw new Error("A valid PDF file name is required.");
32
+ }
33
+
34
+ const result = await pdfFileService.read(fileName);
35
+
36
+ if (!result?.success || !result.buffer?.length) {
37
+ throw new Error("PDF file could not be read.");
38
+ }
39
+ return {
40
+ success: true,
41
+ fileName: result.fileName,
42
+ mimeType: "application/pdf",
43
+ data: result.buffer.toString("base64")
44
+ };
45
+ }
@@ -0,0 +1,26 @@
1
+ import generatePdfService from "../../service/generatePdfService.js";
2
+ import pdfFileService from "../../service/pdfFileService.js";
3
+
4
+ export async function generatePDFTable(data) {
5
+ return await generatePdfService.PDFTable(data);
6
+ }
7
+
8
+ export async function generatePDFText(data) {
9
+ return await generatePdfService.PDFText(data);
10
+ }
11
+
12
+ export async function generatePDFTextAndTable(data) {
13
+ return await generatePdfService.PDFTextAndTable(data);
14
+ }
15
+
16
+ export async function generatePDFTextAndTableWithPagination(data) {
17
+ return await generatePdfService.PDFTextAndTableWithPagination(data);
18
+ }
19
+
20
+ export async function downloadPDF(fileName) {
21
+ return await pdfFileService.read(fileName);
22
+ }
23
+
24
+ export async function existsPDF(fileName) {
25
+ return await pdfFileService.exists(fileName);
26
+ }
@@ -0,0 +1,29 @@
1
+ import {loadConfig} from "@speresps/config-module";
2
+
3
+ const config = loadConfig({
4
+ fileName: "pdf.conf",
5
+ defaults: {
6
+ // table
7
+ FILENAME_TABLE : "table.pdf",
8
+
9
+ // text
10
+ FILENAME_TEXT : "text.pdf",
11
+
12
+ // text table
13
+ FILENAME_TEXT_TABLE : "text-table.pdf",
14
+
15
+ // text table pagination
16
+ FILENAME_TEXT_TABLE_PAGINATION : "text-table-pagination.pdf",
17
+
18
+ // auto download status
19
+ AUTO_DOWNLOAD : "false",
20
+
21
+ // files route
22
+ MAIN_FOLDER_NAME:"files",
23
+ PDF_FOLDER_NAME:"pdf"
24
+
25
+ },
26
+ required: true
27
+ });
28
+
29
+ export default config;
@@ -0,0 +1,11 @@
1
+ // logManager/logger.js:
2
+ import { reportLogger } from "@speresps/report-module";
3
+
4
+ const logger = reportLogger({
5
+ directory: "./report/logs",
6
+ level: "debug",
7
+ console: false,
8
+ service: "PDF",
9
+ });
10
+
11
+ export default logger;
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@speresps/pdf-module",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.0.1",
4
+ "description": "A reusable PDF generation and document management module for Node.js and Next.js applications, supporting Persian RTL documents, customizable headers and footers, text and table templates, paginated reports, PDF file storage, and browser downloads.",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js",
9
+ "./server": "./src/server/index.js",
10
+ "./client": "./src/client/index.js"
11
+ },
12
+ "files": [
13
+ "src/",
14
+ "api/",
15
+ "configManager/",
16
+ "logManager/",
17
+ "service/",
18
+ "template/",
19
+ "README.md"
20
+ ],
21
+ "keywords": [
22
+ "pdf",
23
+ "pdf-generation",
24
+ "pdfmake",
25
+ "persian-pdf",
26
+ "rtl",
27
+ "vazirmatn",
28
+ "pdf-template",
29
+ "pdf-table",
30
+ "pdf-pagination",
31
+ "pdf-download",
32
+ "nodejs",
33
+ "nextjs"
34
+ ],
35
+ "dependencies": {
36
+ "@speresps/config-module": "^1.0.1",
37
+ "@speresps/report-module": "^1.0.0",
38
+ "pdfmake-rtl": "^2.1.2"
39
+ },
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "author": "speresps",
44
+ "license": "MIT"
6
45
  }
@@ -0,0 +1,251 @@
1
+ import logger from "../logManager/logger.js";
2
+ import config from "../configManager/config.js";
3
+
4
+ import {
5
+ validateTableData,
6
+ validatePDFTextData,
7
+ validatePDFTextAndTableData,
8
+ validatePDFPaginationData
9
+ } from "./validation/validateData.js";
10
+
11
+ import { generatePDFTable } from '../template/generatePDFTable/generatePDFTable.js';
12
+ import { generatePDFText } from '../template/generatePDFText/generatePDFText.js';
13
+ import { generatePDFTextAndTable } from '../template/generatePDFTextAndTable/generatePDFTextAndTable.js';
14
+ import { generatePDFTextAndTableWithPagination } from '../template/generatePDFTextAndTableWithPagination/generatePDFTextAndTableWithPagination.js';
15
+
16
+ import pdfBufferService from './pdfBufferService.js';
17
+ import pdfFileService from './pdfFileService.js';
18
+
19
+ const fileNameTable = config.FILENAME_TABLE;
20
+ const fileNameText = config.FILENAME_TEXT;
21
+ const fileNameTextTable = config.FILENAME_TEXT_TABLE;
22
+ const fileNameTextTablePagination = config.FILENAME_TEXT_TABLE_PAGINATION;
23
+
24
+ const AUTO_DOWNLOAD = config.AUTO_DOWNLOAD;
25
+
26
+
27
+ class generatePdfService {
28
+
29
+ async PDFTable(data){
30
+ try{
31
+
32
+ logger.info(`GeneratePdfService in PDFTable Started.`);
33
+
34
+ if(!data) {
35
+ logger.error(`GeneratePdfService in PDFTable, data is required.`);
36
+ throw new Error("Data in Generate PDF For Table Not Find.")
37
+ }
38
+
39
+ validateTableData(data);
40
+
41
+ // تولید pdf
42
+ let pdfDocument = await generatePDFTable({
43
+ ...data,
44
+ AUTO_DOWNLOAD});
45
+
46
+ if(!pdfDocument ){
47
+ logger.error(`GeneratePdfService in PDFTable, Don't Generate PDF For Table.`);
48
+ throw new Error("Don't Generate PDF For Table")
49
+ }
50
+
51
+ // تبدیل pdf به بافر
52
+ const pdfBuffer = await pdfBufferService.getBuffer(pdfDocument);
53
+
54
+ if (!pdfBuffer) {
55
+ logger.error(`GeneratePdfService in PDFTable, Don't Generate PDF Buffer For Table.`);
56
+ throw new Error("Don't Generate PDF Buffer For Table");
57
+ }
58
+
59
+ // ذخیره ی بافر pdf در پوشه ی files
60
+ const result =
61
+ await pdfFileService.save(
62
+ pdfBuffer,
63
+ data.fileName || fileNameTable
64
+ );
65
+
66
+ if (!result || !result.success) {
67
+ logger.error(`GeneratePdfService in PDFTable, Don't Save PDF File For Table.`);
68
+ throw new Error("Don't Save PDF File For Table");
69
+ }
70
+
71
+ return {
72
+ success : true,
73
+ result
74
+ }
75
+
76
+ }
77
+ catch (err){
78
+ return {
79
+ success: false,
80
+ message: err.message,
81
+ }
82
+ }
83
+ }
84
+
85
+ async PDFText(data){
86
+ try{
87
+ logger.info(`GeneratePdfService in PDFText Started.`);
88
+
89
+ if(!data) {
90
+ logger.error(`GeneratePdfService in PDFText, dats is required.`);
91
+ throw new Error("Data in Generate PDF For Text Not Find.")
92
+ }
93
+
94
+ validatePDFTextData(data);
95
+
96
+ let pdfDocument = await generatePDFText({
97
+ ...data,
98
+ AUTO_DOWNLOAD});
99
+
100
+ if(!pdfDocument ){
101
+ logger.error(`GeneratePdfService in PDFText, Don't Generate PDF For Text.`);
102
+ throw new Error("Don't Generate PDF For Text")
103
+ }
104
+
105
+ const pdfBuffer = await pdfBufferService.getBuffer(pdfDocument);
106
+
107
+ if (!pdfBuffer) {
108
+ logger.error(`GeneratePdfService in PDFText, Don't Generate PDF Buffer For Text.`);
109
+ throw new Error("Don't Generate PDF Buffer For Text");
110
+ }
111
+
112
+ const result = await pdfFileService.save(pdfBuffer, data.fileName || fileNameText);
113
+
114
+ if (!result || !result.success) {
115
+ logger.error(`GeneratePdfService in PDFText, Don't Save PDF File For Text.`);
116
+ throw new Error("Don't Save PDF File For Text");
117
+ }
118
+
119
+ return {
120
+ success : true,
121
+ result
122
+ }
123
+
124
+ }
125
+ catch (err){
126
+ return {
127
+ success: false,
128
+ message: err.message,
129
+ }
130
+ }
131
+ }
132
+
133
+ async PDFTextAndTable(data) {
134
+
135
+ try {
136
+
137
+ logger.info(`GeneratePdfService in PDFTextAndTable Started.`);
138
+
139
+ if (!data) {
140
+ logger.error(`GeneratePdfService in PDFTextAndTable, data is required.`);
141
+ throw new Error("Data in Generate PDF For Text And Table Not Find.");
142
+ }
143
+
144
+ validatePDFTextAndTableData(data);
145
+
146
+ const pdfDocument =
147
+ await generatePDFTextAndTable({
148
+ ...data,
149
+ AUTO_DOWNLOAD
150
+ });
151
+
152
+ if (!pdfDocument) {
153
+ logger.error(`GeneratePdfService in PDFTextAndTable, Don't Generate PDF For Text and Table.`);
154
+ throw new Error("Don't Generate PDF For Text And Table");
155
+ }
156
+
157
+ const pdfBuffer =
158
+ await pdfBufferService.getBuffer(
159
+ pdfDocument
160
+ );
161
+
162
+ if (!pdfBuffer) {
163
+ logger.error(`GeneratePdfService in PDFTextAndTable, Don't Generate PDF Buffer For Text And Table.`);
164
+ throw new Error("Don't Generate PDF Buffer For Text And Table");
165
+ }
166
+
167
+ const result =
168
+ await pdfFileService.save(
169
+ pdfBuffer,
170
+ data.fileName || fileNameTextTable
171
+ );
172
+
173
+ if (!result || !result.success) {
174
+ logger.error(`GeneratePdfService in PDFTextAndTable, Don't Save PDF File For Text And Table.`);
175
+ throw new Error("Don't Save PDF File For Text And Table");
176
+ }
177
+
178
+ return {
179
+ success: true,
180
+ result
181
+ };
182
+
183
+ } catch (err) {
184
+ return {
185
+ success: false,
186
+ message: err.message
187
+ };
188
+ }
189
+ }
190
+
191
+ async PDFTextAndTableWithPagination(data) {
192
+
193
+ try {
194
+
195
+ logger.info(`GeneratePdfService in PDFTextAndTableWithPagination Started.`);
196
+
197
+ if (!data) {
198
+ logger.error(`GeneratePdfService in PDFTextAndTableWithPagination, data is required.`);
199
+ throw new Error("Data in Generate PDF For Text And Table with Pagination Not Find.");
200
+ }
201
+
202
+ validatePDFPaginationData(data);
203
+
204
+ const pdfDocument =
205
+ await generatePDFTextAndTableWithPagination({
206
+ ...data,
207
+ AUTO_DOWNLOAD
208
+ });
209
+
210
+ if (!pdfDocument) {
211
+ logger.error(`GeneratePdfService in PDFTextAndTableWithPagination, Don't Generate PDF For Text And Table with Pagination.`);
212
+ throw new Error("Don't Generate PDF For Text And Table with Pagination");
213
+ }
214
+
215
+ const pdfBuffer =
216
+ await pdfBufferService.getBuffer(
217
+ pdfDocument
218
+ );
219
+
220
+ if (!pdfBuffer) {
221
+ logger.error(`GeneratePdfService in PDFTextAndTableWithPagination, Don't Generate PDF Buffer For Text And Table with Pagination.`);
222
+ throw new Error("Don't Generate PDF Buffer For Text And Table with Pagination");
223
+ }
224
+
225
+ const result =
226
+ await pdfFileService.save(
227
+ pdfBuffer,
228
+ data.fileName ||
229
+ fileNameTextTablePagination
230
+ );
231
+
232
+ if (!result || !result.success) {
233
+ logger.error(`GeneratePdfService in PDFTextAndTableWithPagination, Don't Save PDF File For Text And Table with Pagination.`);
234
+ throw new Error("Don't Save PDF File For Text And Table with Pagination");
235
+ }
236
+
237
+ return {
238
+ success: true,
239
+ result
240
+ };
241
+
242
+ } catch (err) {
243
+ return {
244
+ success: false,
245
+ message: err.message
246
+ };
247
+ }
248
+ }
249
+ }
250
+
251
+ export default new generatePdfService;
@@ -0,0 +1,39 @@
1
+ import logger from "../logManager/logger.js";
2
+
3
+ class PdfBufferService {
4
+
5
+ async getBuffer(pdfDocument) {
6
+
7
+ if (!pdfDocument || typeof pdfDocument.getBuffer !== "function") {
8
+ logger.error("PdfBufferService: A valid PDF Document is required.");
9
+ throw new Error("A valid PDF Document is required.");
10
+ }
11
+
12
+ try {
13
+
14
+ const buffer = await pdfDocument.getBuffer();
15
+
16
+ if (!buffer || buffer.length === 0) {
17
+ logger.error("PdfBufferService: PDF Buffer was not generated.");
18
+ throw new Error("PDF Buffer was not generated.");
19
+ }
20
+
21
+ return buffer;
22
+
23
+ } catch (error) {
24
+
25
+ logger.error(
26
+ `PdfBufferService in getBuffer encountered an error: ${error.message}`
27
+ );
28
+
29
+ throw new Error(
30
+ `Failed to generate PDF Buffer: ${error.message}`,
31
+ { cause: error }
32
+ );
33
+
34
+ }
35
+ }
36
+
37
+ }
38
+
39
+ export default new PdfBufferService();
@@ -0,0 +1,187 @@
1
+ import fs from "fs/promises";
2
+ import path from "path";
3
+
4
+ import logger from "../logManager/logger.js";
5
+ import config from "../configManager/config.js";
6
+
7
+ const mainFolderName = config.MAIN_FOLDER_NAME;
8
+ const pdfFolderName = config.PDF_FOLDER_NAME;
9
+
10
+
11
+ class PdfFileService {
12
+
13
+ // مسیر ذخیره pdf
14
+ getPdfDirectory() {
15
+
16
+ return path.resolve(
17
+ mainFolderName,
18
+ pdfFolderName
19
+ );
20
+
21
+ }
22
+
23
+
24
+ // save PDF :
25
+ // در پوشه ی files در سطح پروژه pdf تولید شده را ذخیره میکند
26
+ async save(buffer, fileName) {
27
+
28
+ if (!buffer) {
29
+ logger.error(`PdfFileService in Save, PDF Buffer is required.`);
30
+ throw new Error("PDF Buffer is required.");
31
+ }
32
+
33
+ if (!fileName) {
34
+ logger.error(`PdfFileService in Save, PDF File Name is required.`);
35
+ throw new Error("PDF File Name is required.");
36
+ }
37
+
38
+ try {
39
+
40
+ const pdfDirectory = this.getPdfDirectory();
41
+
42
+ await fs.mkdir(pdfDirectory, {
43
+ recursive: true
44
+ });
45
+
46
+ if (
47
+ typeof fileName !== "string" ||
48
+ !fileName.trim() ||
49
+ path.extname(fileName).toLowerCase() !== ".pdf"
50
+ ) {
51
+ throw new Error("A valid PDF filename is required.");
52
+ }
53
+
54
+ const safeFileName = path.basename(fileName);
55
+
56
+ const filePath = path.join(
57
+ pdfDirectory,
58
+ safeFileName
59
+ );
60
+
61
+ await fs.writeFile(
62
+ filePath,
63
+ buffer
64
+ );
65
+
66
+ return {
67
+ success: true,
68
+ fileName: safeFileName,
69
+ filePath
70
+ };
71
+
72
+ } catch (error) {
73
+ logger.error(`PdfFileService in Save Have a Error: ${error.message}.`);
74
+ throw new Error(`Save PDF File Have a Error: ${error.message}`);
75
+ }
76
+ }
77
+
78
+
79
+ // read PDF :
80
+ // برای خواندن pdf ذخیره شده از پوشه ی files موقع استفاده برای download
81
+ async read(fileName) {
82
+
83
+ if (!fileName) {
84
+ logger.error(`PdfFileService in Read, PDF File Name is required.`);
85
+ throw new Error("PDF File Name is required.");
86
+ }
87
+
88
+ try {
89
+
90
+ const pdfDirectory = this.getPdfDirectory();
91
+
92
+ if (
93
+ typeof fileName !== "string" ||
94
+ !fileName.trim() ||
95
+ path.extname(fileName).toLowerCase() !== ".pdf"
96
+ ) {
97
+ throw new Error("A valid PDF filename is required.");
98
+ }
99
+
100
+ const safeFileName = path.basename(fileName);
101
+
102
+ const filePath = path.join(
103
+ pdfDirectory,
104
+ safeFileName
105
+ );
106
+
107
+ const buffer = await fs.readFile(
108
+ filePath
109
+ );
110
+
111
+ return {
112
+ success: true,
113
+ fileName: safeFileName,
114
+ filePath,
115
+ buffer
116
+ };
117
+
118
+ } catch (error) {
119
+
120
+ if (error.code === "ENOENT") {
121
+ logger.error(`PdfFileService in Read, PDF File Not Found.`);
122
+ throw new Error("PDF File Not Found.");
123
+ }
124
+
125
+ logger.error(`PdfFileService in Read Have a Error: ${error.message}.`);
126
+
127
+ throw new Error(`Read PDF File Have a Error: ${error.message}`);
128
+
129
+ }
130
+ }
131
+
132
+
133
+ // exist PDF :
134
+ // این متد وجود PDF را بررسی میکند در صورت وجود pdf ، یعنی مراحل ساخت pdf کامل شده
135
+ async exists(fileName) {
136
+
137
+ if (!fileName) {
138
+ logger.error(`PdfFileService in Exists, PDF File Name is required.`);
139
+ throw new Error("PDF File Name is required.");
140
+ }
141
+
142
+ try {
143
+
144
+ const pdfDirectory = this.getPdfDirectory();
145
+
146
+ if (
147
+ typeof fileName !== "string" ||
148
+ !fileName.trim() ||
149
+ path.extname(fileName).toLowerCase() !== ".pdf"
150
+ ) {
151
+ throw new Error("A valid PDF filename is required.");
152
+ }
153
+
154
+ const safeFileName = path.basename(fileName);
155
+
156
+ const filePath = path.join(pdfDirectory, safeFileName);
157
+
158
+ await fs.access(filePath);
159
+
160
+ return {
161
+ exist: true,
162
+ fileName: safeFileName,
163
+ filePath
164
+ };
165
+
166
+ } catch (error) {
167
+
168
+ if (error.code === "ENOENT") {
169
+ logger.error(`PdfFileService in Exists, PDF File Not Found.`);
170
+
171
+ return {
172
+ exist: false,
173
+ fileName,
174
+ filePath: null
175
+ };
176
+ }
177
+
178
+ logger.error(`PdfFileService in Exists Have a Error: ${error.message}.`);
179
+
180
+ throw new Error(`Check PDF File Have a Error: ${error.message}`);
181
+ }
182
+ }
183
+
184
+
185
+ }
186
+
187
+ export default new PdfFileService();