@shad0wz7/nestjs-pdf 3.2.0 → 5.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 +129 -30
- package/dist/index.cjs +723 -243
- package/dist/index.d.cts +320 -88
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +320 -88
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +702 -201
- package/dist/index.mjs.map +1 -1
- package/package.json +100 -50
package/dist/index.mjs
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
1
2
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
2
3
|
import { Inject, Injectable, Logger, Module, Optional } from "@nestjs/common";
|
|
3
4
|
import { PDFArray, PDFDict, PDFDocument, PDFName, PDFNumber, PDFString, StandardFonts, degrees, rgb } from "pdf-lib";
|
|
4
5
|
import { deepmerge } from "deepmerge-ts";
|
|
5
|
-
import { lookup } from "node:dns/promises";
|
|
6
6
|
import { existsSync, promises, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { lookup } from "node:dns/promises";
|
|
7
8
|
import { BlockList, isIP } from "node:net";
|
|
8
9
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
|
|
10
|
-
import { Browser as Browser$1, BrowserPlatform, canDownload, detectBrowserPlatform, getInstalledBrowsers, install, resolveBuildId } from "@puppeteer/browsers";
|
|
11
|
-
import ejs from "ejs";
|
|
12
|
-
import { Eta } from "eta";
|
|
13
|
-
import Handlebars from "handlebars";
|
|
14
|
-
import mjml from "mjml";
|
|
15
|
-
import mustache from "mustache";
|
|
16
|
-
import nunjucks from "nunjucks";
|
|
17
|
-
import pug from "pug";
|
|
18
|
-
//#region src/exceptions/nestjs-pdf.exception.ts
|
|
10
|
+
// src/exceptions/nestjs-pdf.exception.ts
|
|
19
11
|
let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
|
|
20
12
|
NestjsPdfErrorCode["ENGINE_NOT_AVAILABLE"] = "ENGINE_NOT_AVAILABLE";
|
|
21
13
|
NestjsPdfErrorCode["TEMPLATE_CONFIGURATION_ERROR"] = "TEMPLATE_CONFIGURATION_ERROR";
|
|
@@ -26,6 +18,7 @@ let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
|
|
|
26
18
|
NestjsPdfErrorCode["SIGNATURE_DEPENDENCY_ERROR"] = "SIGNATURE_DEPENDENCY_ERROR";
|
|
27
19
|
NestjsPdfErrorCode["SIGNATURE_PLACEMENT_ERROR"] = "SIGNATURE_PLACEMENT_ERROR";
|
|
28
20
|
NestjsPdfErrorCode["WATERMARK_ERROR"] = "WATERMARK_ERROR";
|
|
21
|
+
NestjsPdfErrorCode["RENDERER_CONFIGURATION_ERROR"] = "RENDERER_CONFIGURATION_ERROR";
|
|
29
22
|
return NestjsPdfErrorCode;
|
|
30
23
|
}({});
|
|
31
24
|
var NestjsPdfException = class extends Error {
|
|
@@ -34,46 +27,43 @@ var NestjsPdfException = class extends Error {
|
|
|
34
27
|
this.name = this.constructor.name;
|
|
35
28
|
}
|
|
36
29
|
};
|
|
37
|
-
|
|
38
|
-
//#region src/exceptions/browser-installation.exception.ts
|
|
30
|
+
// src/exceptions/browser-installation.exception.ts
|
|
39
31
|
var BrowserInstallationException = class extends NestjsPdfException {
|
|
40
32
|
code = "BROWSER_INSTALLATION_ERROR";
|
|
41
33
|
};
|
|
42
|
-
|
|
43
|
-
//#region src/exceptions/browser-unavailable.exception.ts
|
|
34
|
+
// src/exceptions/browser-unavailable.exception.ts
|
|
44
35
|
var BrowserUnavailableException = class extends NestjsPdfException {
|
|
45
36
|
code = "BROWSER_UNAVAILABLE";
|
|
46
37
|
};
|
|
47
|
-
|
|
48
|
-
//#region src/exceptions/engine-not-available.exception.ts
|
|
38
|
+
// src/exceptions/engine-not-available.exception.ts
|
|
49
39
|
var EngineNotAvailableException = class extends NestjsPdfException {
|
|
50
40
|
code = "ENGINE_NOT_AVAILABLE";
|
|
51
|
-
constructor(engineName) {
|
|
52
|
-
super(`${engineName} service is not available. If the problem persists, open an issue in the repo
|
|
41
|
+
constructor(engineName, packageName, options) {
|
|
42
|
+
super(packageName ? `${engineName} engine is not available: the '${packageName}' package is not installed. Run \`npm install ${packageName}\` to use it.` : `${engineName} service is not available. If the problem persists, open an issue in the repo.`, options);
|
|
53
43
|
}
|
|
54
44
|
};
|
|
55
|
-
|
|
56
|
-
//#region src/exceptions/pdf-generation.exception.ts
|
|
45
|
+
// src/exceptions/pdf-generation.exception.ts
|
|
57
46
|
var PdfGenerationException = class extends NestjsPdfException {
|
|
58
47
|
code = "PDF_GENERATION_ERROR";
|
|
59
48
|
};
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
// src/exceptions/renderer-configuration.exception.ts
|
|
50
|
+
/** The PDF provider is misconfigured, or asked for an option it does not support. */
|
|
51
|
+
var RendererConfigurationException = class extends NestjsPdfException {
|
|
52
|
+
code = "RENDERER_CONFIGURATION_ERROR";
|
|
53
|
+
};
|
|
54
|
+
// src/exceptions/signature-dependency.exception.ts
|
|
62
55
|
var SignatureDependencyException = class extends NestjsPdfException {
|
|
63
56
|
code = "SIGNATURE_DEPENDENCY_ERROR";
|
|
64
57
|
};
|
|
65
|
-
|
|
66
|
-
//#region src/exceptions/signature-placement.exception.ts
|
|
58
|
+
// src/exceptions/signature-placement.exception.ts
|
|
67
59
|
var SignaturePlacementException = class extends NestjsPdfException {
|
|
68
60
|
code = "SIGNATURE_PLACEMENT_ERROR";
|
|
69
61
|
};
|
|
70
|
-
|
|
71
|
-
//#region src/exceptions/template-configuration.exception.ts
|
|
62
|
+
// src/exceptions/template-configuration.exception.ts
|
|
72
63
|
var TemplateConfigurationException = class extends NestjsPdfException {
|
|
73
64
|
code = "TEMPLATE_CONFIGURATION_ERROR";
|
|
74
65
|
};
|
|
75
|
-
|
|
76
|
-
//#region src/exceptions/template-render.exception.ts
|
|
66
|
+
// src/exceptions/template-render.exception.ts
|
|
77
67
|
var TemplateRenderException = class extends NestjsPdfException {
|
|
78
68
|
engine;
|
|
79
69
|
code = "TEMPLATE_RENDER_ERROR";
|
|
@@ -82,13 +72,11 @@ var TemplateRenderException = class extends NestjsPdfException {
|
|
|
82
72
|
this.engine = engine;
|
|
83
73
|
}
|
|
84
74
|
};
|
|
85
|
-
|
|
86
|
-
//#region src/exceptions/watermark.exception.ts
|
|
75
|
+
// src/exceptions/watermark.exception.ts
|
|
87
76
|
var WatermarkException = class extends NestjsPdfException {
|
|
88
77
|
code = "WATERMARK_ERROR";
|
|
89
78
|
};
|
|
90
|
-
|
|
91
|
-
//#region src/helpers/getRelativePath.helper.ts
|
|
79
|
+
// src/helpers/getRelativePath.helper.ts
|
|
92
80
|
/**
|
|
93
81
|
* Get the relative path to a value from the module directory.
|
|
94
82
|
* @param moduleDir the path of the module, typically __dirname
|
|
@@ -102,8 +90,7 @@ function getRelativePathToValue(moduleDir, relativeToModule) {
|
|
|
102
90
|
const fullTemplatePath = resolve(moduleDir, relativeToModule);
|
|
103
91
|
return relative(process.cwd(), fullTemplatePath);
|
|
104
92
|
}
|
|
105
|
-
|
|
106
|
-
//#region src/helpers/signature.helper.ts
|
|
93
|
+
// src/helpers/signature.helper.ts
|
|
107
94
|
let pdfjsPromise;
|
|
108
95
|
async function loadPdfjs() {
|
|
109
96
|
if (!pdfjsPromise) try {
|
|
@@ -246,8 +233,7 @@ async function addSignatureFieldUsingAnchor(pdf, fieldName = "SignatureDebtor",
|
|
|
246
233
|
}
|
|
247
234
|
return await pdfDoc.save();
|
|
248
235
|
}
|
|
249
|
-
|
|
250
|
-
//#region src/helpers/watermark.helper.ts
|
|
236
|
+
// src/helpers/watermark.helper.ts
|
|
251
237
|
const DEFAULT_OPACITY = .15;
|
|
252
238
|
const DEFAULT_ROTATION = 45;
|
|
253
239
|
const DEFAULT_FONT_SIZE = 60;
|
|
@@ -390,8 +376,7 @@ async function addWatermark(pdf, options) {
|
|
|
390
376
|
throw new WatermarkException(`Failed to add watermark: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
391
377
|
}
|
|
392
378
|
}
|
|
393
|
-
|
|
394
|
-
//#region node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
|
|
379
|
+
// node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
|
|
395
380
|
var Node = class {
|
|
396
381
|
value;
|
|
397
382
|
next;
|
|
@@ -448,8 +433,7 @@ var Queue = class {
|
|
|
448
433
|
while (this.#head) yield this.dequeue();
|
|
449
434
|
}
|
|
450
435
|
};
|
|
451
|
-
|
|
452
|
-
//#region node_modules/.pnpm/p-limit@7.3.2/node_modules/p-limit/index.js
|
|
436
|
+
// node_modules/.pnpm/p-limit@7.3.3/node_modules/p-limit/index.js
|
|
453
437
|
function pLimit(concurrency) {
|
|
454
438
|
let rejectOnClear = false;
|
|
455
439
|
if (typeof concurrency === "object") ({concurrency, rejectOnClear = false} = concurrency);
|
|
@@ -508,7 +492,17 @@ function pLimit(concurrency) {
|
|
|
508
492
|
}
|
|
509
493
|
},
|
|
510
494
|
map: { async value(iterable, function_) {
|
|
511
|
-
const promises =
|
|
495
|
+
const promises = [];
|
|
496
|
+
try {
|
|
497
|
+
Array.from(iterable, (value, index) => {
|
|
498
|
+
const promise = generator(function_, value, index);
|
|
499
|
+
promises.push(promise);
|
|
500
|
+
return promise;
|
|
501
|
+
});
|
|
502
|
+
} catch (error) {
|
|
503
|
+
for (const promise of promises) promise.catch(() => {});
|
|
504
|
+
throw error;
|
|
505
|
+
}
|
|
512
506
|
return Promise.all(promises);
|
|
513
507
|
} }
|
|
514
508
|
});
|
|
@@ -517,14 +511,296 @@ function pLimit(concurrency) {
|
|
|
517
511
|
function validateConcurrency(concurrency) {
|
|
518
512
|
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
|
519
513
|
}
|
|
520
|
-
|
|
521
|
-
//#region src/helpers/deepMergePdfparams.ts
|
|
514
|
+
// src/helpers/deepMergePdfparams.ts
|
|
522
515
|
function mergePuppeteerParameters(defaults, overrides) {
|
|
523
516
|
if (!overrides) return { ...defaults };
|
|
524
517
|
return deepmerge(defaults, overrides);
|
|
525
518
|
}
|
|
526
|
-
|
|
527
|
-
|
|
519
|
+
// src/helpers/tokens.ts
|
|
520
|
+
const PDF_PARAMETERS = "PDF_PARAMETERS";
|
|
521
|
+
// src/renderers/pdf-renderer.interface.ts
|
|
522
|
+
const PDF_RENDERER = "PDF_RENDERER";
|
|
523
|
+
// src/renderers/http.utils.ts
|
|
524
|
+
const MAX_ERROR_BODY_LENGTH = 500;
|
|
525
|
+
/** Builds a `PdfGenerationException` from a failed HTTP response, body included. */
|
|
526
|
+
async function httpError(provider, response) {
|
|
527
|
+
let body = "";
|
|
528
|
+
try {
|
|
529
|
+
body = (await response.text()).trim().slice(0, MAX_ERROR_BODY_LENGTH);
|
|
530
|
+
} catch {}
|
|
531
|
+
return new PdfGenerationException(`${provider} responded with HTTP ${response.status}${body ? `: ${body}` : ""}`);
|
|
532
|
+
}
|
|
533
|
+
/** Remote providers render on another machine: the local request guard cannot run there. */
|
|
534
|
+
function assertNoRequestGuard(provider, options, hint) {
|
|
535
|
+
if (options.security) throw new RendererConfigurationException(`The 'security' option is only supported by the puppeteer provider, not by ${provider}. ${hint}`);
|
|
536
|
+
}
|
|
537
|
+
function requireNonEmpty(value, name, provider) {
|
|
538
|
+
if (!value?.trim()) throw new RendererConfigurationException(`The ${provider} provider requires a non-empty '${name}'`);
|
|
539
|
+
return value;
|
|
540
|
+
}
|
|
541
|
+
// src/renderers/pdf-options.mapper.ts
|
|
542
|
+
/** Paper sizes in inches, as Puppeteer defines them. */
|
|
543
|
+
const PAPER_FORMATS = {
|
|
544
|
+
letter: {
|
|
545
|
+
width: 8.5,
|
|
546
|
+
height: 11
|
|
547
|
+
},
|
|
548
|
+
legal: {
|
|
549
|
+
width: 8.5,
|
|
550
|
+
height: 14
|
|
551
|
+
},
|
|
552
|
+
tabloid: {
|
|
553
|
+
width: 11,
|
|
554
|
+
height: 17
|
|
555
|
+
},
|
|
556
|
+
ledger: {
|
|
557
|
+
width: 17,
|
|
558
|
+
height: 11
|
|
559
|
+
},
|
|
560
|
+
a0: {
|
|
561
|
+
width: 33.1102,
|
|
562
|
+
height: 46.811
|
|
563
|
+
},
|
|
564
|
+
a1: {
|
|
565
|
+
width: 23.3858,
|
|
566
|
+
height: 33.1102
|
|
567
|
+
},
|
|
568
|
+
a2: {
|
|
569
|
+
width: 16.5354,
|
|
570
|
+
height: 23.3858
|
|
571
|
+
},
|
|
572
|
+
a3: {
|
|
573
|
+
width: 11.6929,
|
|
574
|
+
height: 16.5354
|
|
575
|
+
},
|
|
576
|
+
a4: {
|
|
577
|
+
width: 8.2677,
|
|
578
|
+
height: 11.6929
|
|
579
|
+
},
|
|
580
|
+
a5: {
|
|
581
|
+
width: 5.8268,
|
|
582
|
+
height: 8.2677
|
|
583
|
+
},
|
|
584
|
+
a6: {
|
|
585
|
+
width: 4.1339,
|
|
586
|
+
height: 5.8268
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
const INCHES_PER_UNIT = {
|
|
590
|
+
px: 1 / 96,
|
|
591
|
+
in: 1,
|
|
592
|
+
cm: 1 / 2.54,
|
|
593
|
+
mm: 1 / 25.4
|
|
594
|
+
};
|
|
595
|
+
/**
|
|
596
|
+
* Converts a Puppeteer length (a number of pixels, or a string with a
|
|
597
|
+
* `px`/`in`/`cm`/`mm` unit) to inches.
|
|
598
|
+
*/
|
|
599
|
+
function toInches(value) {
|
|
600
|
+
if (typeof value === "number") return value * INCHES_PER_UNIT.px;
|
|
601
|
+
const match = /^\s*(-?\d*\.?\d+)\s*(px|in|cm|mm)?\s*$/i.exec(value);
|
|
602
|
+
if (!match) throw new RendererConfigurationException(`Invalid length '${value}': expected a number of pixels or a value in px, in, cm or mm`);
|
|
603
|
+
const unit = (match[2] ?? "px").toLowerCase();
|
|
604
|
+
return Number(match[1]) * INCHES_PER_UNIT[unit];
|
|
605
|
+
}
|
|
606
|
+
function formatInches(inches) {
|
|
607
|
+
return String(Math.round(inches * 1e4) / 1e4);
|
|
608
|
+
}
|
|
609
|
+
function resolvePrintLayout(pdfOptions) {
|
|
610
|
+
let width;
|
|
611
|
+
let height;
|
|
612
|
+
if (pdfOptions.width !== void 0 || pdfOptions.height !== void 0) {
|
|
613
|
+
const fallback = PAPER_FORMATS.letter;
|
|
614
|
+
width = pdfOptions.width === void 0 ? fallback.width : toInches(pdfOptions.width);
|
|
615
|
+
height = pdfOptions.height === void 0 ? fallback.height : toInches(pdfOptions.height);
|
|
616
|
+
} else {
|
|
617
|
+
const formatName = (pdfOptions.format ?? "letter").toLowerCase();
|
|
618
|
+
const format = PAPER_FORMATS[formatName];
|
|
619
|
+
if (!format) throw new RendererConfigurationException(`Unknown paper format '${pdfOptions.format}'`);
|
|
620
|
+
({width, height} = format);
|
|
621
|
+
}
|
|
622
|
+
const margin = {};
|
|
623
|
+
for (const side of [
|
|
624
|
+
"top",
|
|
625
|
+
"right",
|
|
626
|
+
"bottom",
|
|
627
|
+
"left"
|
|
628
|
+
]) {
|
|
629
|
+
const value = pdfOptions.margin?.[side];
|
|
630
|
+
if (value !== void 0) margin[side] = toInches(value);
|
|
631
|
+
}
|
|
632
|
+
return {
|
|
633
|
+
width,
|
|
634
|
+
height,
|
|
635
|
+
margin
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function toHtmlDocument(template) {
|
|
639
|
+
return /<html[\s>]/i.test(template) ? template : `<!DOCTYPE html><html><head></head><body>${template}</body></html>`;
|
|
640
|
+
}
|
|
641
|
+
function toGotenbergForm(pdfOptions) {
|
|
642
|
+
const { width, height, margin } = resolvePrintLayout(pdfOptions);
|
|
643
|
+
const fields = {
|
|
644
|
+
paperWidth: formatInches(width),
|
|
645
|
+
paperHeight: formatInches(height),
|
|
646
|
+
marginTop: formatInches(margin.top ?? 0),
|
|
647
|
+
marginRight: formatInches(margin.right ?? 0),
|
|
648
|
+
marginBottom: formatInches(margin.bottom ?? 0),
|
|
649
|
+
marginLeft: formatInches(margin.left ?? 0),
|
|
650
|
+
emulatedMediaType: "screen",
|
|
651
|
+
skipNetworkIdleEvent: "false"
|
|
652
|
+
};
|
|
653
|
+
if (pdfOptions.landscape !== void 0) fields.landscape = String(pdfOptions.landscape);
|
|
654
|
+
if (pdfOptions.printBackground !== void 0) fields.printBackground = String(pdfOptions.printBackground);
|
|
655
|
+
if (pdfOptions.omitBackground !== void 0) fields.omitBackground = String(pdfOptions.omitBackground);
|
|
656
|
+
if (pdfOptions.scale !== void 0) fields.scale = String(pdfOptions.scale);
|
|
657
|
+
if (pdfOptions.pageRanges) fields.nativePageRanges = pdfOptions.pageRanges;
|
|
658
|
+
if (pdfOptions.preferCSSPageSize !== void 0) fields.preferCssPageSize = String(pdfOptions.preferCSSPageSize);
|
|
659
|
+
if (pdfOptions.tagged !== void 0) fields.generateTaggedPdf = String(pdfOptions.tagged);
|
|
660
|
+
if (pdfOptions.outline !== void 0) fields.generateDocumentOutline = String(pdfOptions.outline);
|
|
661
|
+
const files = {};
|
|
662
|
+
if (pdfOptions.displayHeaderFooter) {
|
|
663
|
+
if (pdfOptions.headerTemplate) files["header.html"] = toHtmlDocument(pdfOptions.headerTemplate);
|
|
664
|
+
if (pdfOptions.footerTemplate) files["footer.html"] = toHtmlDocument(pdfOptions.footerTemplate);
|
|
665
|
+
}
|
|
666
|
+
return {
|
|
667
|
+
fields,
|
|
668
|
+
files
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
function toApi2PdfOptions(pdfOptions) {
|
|
672
|
+
const { width, height, margin } = resolvePrintLayout(pdfOptions);
|
|
673
|
+
const options = {
|
|
674
|
+
width: `${formatInches(width)}in`,
|
|
675
|
+
height: `${formatInches(height)}in`,
|
|
676
|
+
marginTop: `${formatInches(margin.top ?? 0)}in`,
|
|
677
|
+
marginRight: `${formatInches(margin.right ?? 0)}in`,
|
|
678
|
+
marginBottom: `${formatInches(margin.bottom ?? 0)}in`,
|
|
679
|
+
marginLeft: `${formatInches(margin.left ?? 0)}in`,
|
|
680
|
+
usePrintCss: false
|
|
681
|
+
};
|
|
682
|
+
for (const key of [
|
|
683
|
+
"landscape",
|
|
684
|
+
"printBackground",
|
|
685
|
+
"omitBackground",
|
|
686
|
+
"scale",
|
|
687
|
+
"pageRanges",
|
|
688
|
+
"displayHeaderFooter",
|
|
689
|
+
"headerTemplate",
|
|
690
|
+
"footerTemplate"
|
|
691
|
+
]) if (pdfOptions[key] !== void 0) options[key] = pdfOptions[key];
|
|
692
|
+
return options;
|
|
693
|
+
}
|
|
694
|
+
// src/renderers/api2pdf.renderer.ts
|
|
695
|
+
const PROVIDER$1 = "Api2Pdf";
|
|
696
|
+
const DEFAULT_BASE_URL = "https://v2.api2pdf.com";
|
|
697
|
+
const ROUTE$1 = "/chrome/pdf/html";
|
|
698
|
+
function isApi2Pdf(data) {
|
|
699
|
+
return typeof data === "object" && data !== null && ("Success" in data || "Error" in data || "FileUrl" in data);
|
|
700
|
+
}
|
|
701
|
+
var Api2PdfRenderer = class {
|
|
702
|
+
#endpoint;
|
|
703
|
+
#headers;
|
|
704
|
+
constructor(provider) {
|
|
705
|
+
const apiKey = requireNonEmpty(provider.apiKey, "apiKey", PROVIDER$1);
|
|
706
|
+
const baseUrl = requireNonEmpty(provider.baseUrl ?? DEFAULT_BASE_URL, "baseUrl", PROVIDER$1).replace(/\/+$/, "");
|
|
707
|
+
this.#endpoint = `${baseUrl}${ROUTE$1}?outputBinary=true`;
|
|
708
|
+
this.#headers = {
|
|
709
|
+
...provider.headers,
|
|
710
|
+
Authorization: apiKey,
|
|
711
|
+
"Content-Type": "application/json",
|
|
712
|
+
Accept: "application/pdf, application/json"
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
async render(html, options, signal) {
|
|
716
|
+
assertNoRequestGuard(PROVIDER$1, options, "Only render trusted HTML with a remote provider.");
|
|
717
|
+
const body = {
|
|
718
|
+
html,
|
|
719
|
+
inline: false,
|
|
720
|
+
options: {
|
|
721
|
+
...toApi2PdfOptions(options.pdfOptions ?? { format: "A4" }),
|
|
722
|
+
...options.api2pdfOptions?.options
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
if (options.api2pdfOptions?.fileName) body.fileName = options.api2pdfOptions.fileName;
|
|
726
|
+
const response = await fetch(this.#endpoint, {
|
|
727
|
+
method: "POST",
|
|
728
|
+
headers: this.#headers,
|
|
729
|
+
body: JSON.stringify(body),
|
|
730
|
+
signal
|
|
731
|
+
});
|
|
732
|
+
if (!response.ok) throw await httpError(PROVIDER$1, response);
|
|
733
|
+
if (!response.headers.get("content-type")?.includes("application/json")) return new Uint8Array(await response.arrayBuffer());
|
|
734
|
+
const result = await response.json();
|
|
735
|
+
if (!isApi2Pdf(result)) throw new PdfGenerationException(`${PROVIDER$1} returned an unexpected response: ${JSON.stringify(result)}`);
|
|
736
|
+
if (result.Success === false || !result.FileUrl) throw new PdfGenerationException(`${PROVIDER$1} could not generate the PDF: ${result.Error ?? "no file returned"}`);
|
|
737
|
+
const file = await fetch(result.FileUrl, { signal });
|
|
738
|
+
if (!file.ok) throw await httpError(PROVIDER$1, file);
|
|
739
|
+
return new Uint8Array(await file.arrayBuffer());
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
// src/renderers/gotenberg.renderer.ts
|
|
743
|
+
const PROVIDER = "Gotenberg";
|
|
744
|
+
const ROUTE = "/forms/chromium/convert/html";
|
|
745
|
+
var GotenbergRenderer = class {
|
|
746
|
+
#endpoint;
|
|
747
|
+
#headers;
|
|
748
|
+
constructor(provider) {
|
|
749
|
+
const url = requireNonEmpty(provider.url, "url", PROVIDER);
|
|
750
|
+
this.#endpoint = `${url.replace(/\/+$/, "")}${ROUTE}`;
|
|
751
|
+
this.#headers = { ...provider.headers };
|
|
752
|
+
if (provider.basicAuth) {
|
|
753
|
+
const { username, password } = provider.basicAuth;
|
|
754
|
+
this.#headers.Authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
async render(html, options, signal) {
|
|
758
|
+
assertNoRequestGuard(PROVIDER, options, "Restrict outbound requests on the Gotenberg server instead, with '--chromium-allow-list' / '--chromium-deny-list'.");
|
|
759
|
+
const { fields, files } = toGotenbergForm(options.pdfOptions ?? { format: "A4" });
|
|
760
|
+
const form = new FormData();
|
|
761
|
+
form.append("files", new Blob([html], { type: "text/html" }), "index.html");
|
|
762
|
+
for (const [name, content] of Object.entries(files)) form.append("files", new Blob([content], { type: "text/html" }), name);
|
|
763
|
+
for (const asset of options.gotenbergOptions?.assets ?? []) form.append("files", new Blob([asset.content], { type: asset.contentType ?? "application/octet-stream" }), asset.filename);
|
|
764
|
+
const allFields = {
|
|
765
|
+
...fields,
|
|
766
|
+
...options.gotenbergOptions?.formFields
|
|
767
|
+
};
|
|
768
|
+
for (const [name, value] of Object.entries(allFields)) form.append(name, value);
|
|
769
|
+
const response = await fetch(this.#endpoint, {
|
|
770
|
+
method: "POST",
|
|
771
|
+
headers: this.#headers,
|
|
772
|
+
body: form,
|
|
773
|
+
signal
|
|
774
|
+
});
|
|
775
|
+
if (!response.ok) throw await httpError(PROVIDER, response);
|
|
776
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
// src/puppeteer/libs/loadPuppeteer.utils.ts
|
|
780
|
+
function isMissingPackage(error, packageName) {
|
|
781
|
+
const { code, message } = error;
|
|
782
|
+
return (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") && typeof message === "string" && message.includes(`'${packageName}'`);
|
|
783
|
+
}
|
|
784
|
+
/** Imports an optional peer dependency, turning "not installed" into a clear exception. */
|
|
785
|
+
async function loadOptional(packageName, importer) {
|
|
786
|
+
try {
|
|
787
|
+
return await importer();
|
|
788
|
+
} catch (error) {
|
|
789
|
+
if (isMissingPackage(error, packageName)) throw new EngineNotAvailableException("Puppeteer", packageName, { cause: error });
|
|
790
|
+
throw error;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Puppeteer is an optional peer dependency, only needed by the `puppeteer`
|
|
795
|
+
* provider: it is imported on first use, never when the library loads.
|
|
796
|
+
*/
|
|
797
|
+
function loadPuppeteer() {
|
|
798
|
+
return loadOptional("puppeteer", () => import("puppeteer"));
|
|
799
|
+
}
|
|
800
|
+
function loadPuppeteerBrowsers() {
|
|
801
|
+
return loadOptional("@puppeteer/browsers", () => import("@puppeteer/browsers"));
|
|
802
|
+
}
|
|
803
|
+
// src/helpers/request-guard.helper.ts
|
|
528
804
|
const blockedRanges = new BlockList();
|
|
529
805
|
for (const [address, prefix] of [
|
|
530
806
|
["0.0.0.0", 8],
|
|
@@ -652,6 +928,7 @@ function describe(rawUrl) {
|
|
|
652
928
|
* and closes the pop-ups a script could open to escape the filter.
|
|
653
929
|
*/
|
|
654
930
|
async function installRequestGuard(context, page, options) {
|
|
931
|
+
const { TargetType } = await loadPuppeteer();
|
|
655
932
|
context.on("targetcreated", (target) => {
|
|
656
933
|
if (target.type() === TargetType.PAGE && target.opener()) target.page().then((popup) => popup?.close()).catch(() => void 0);
|
|
657
934
|
});
|
|
@@ -671,31 +948,162 @@ async function installRequestGuard(context, page, options) {
|
|
|
671
948
|
})().catch(() => void 0);
|
|
672
949
|
});
|
|
673
950
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
951
|
+
// src/renderers/puppeteer.renderer.ts
|
|
952
|
+
const DEFAULT_ARGS = [
|
|
953
|
+
"--autoplay-policy=user-gesture-required",
|
|
954
|
+
"--disable-background-networking",
|
|
955
|
+
"--disable-background-timer-throttling",
|
|
956
|
+
"--disable-backgrounding-occluded-windows",
|
|
957
|
+
"--disable-breakpad",
|
|
958
|
+
"--disable-client-side-phishing-detection",
|
|
959
|
+
"--disable-component-update",
|
|
960
|
+
"--disable-default-apps",
|
|
961
|
+
"--disable-dev-shm-usage",
|
|
962
|
+
"--disable-domain-reliability",
|
|
963
|
+
"--disable-extensions",
|
|
964
|
+
"--disable-features=AudioServiceOutOfProcess",
|
|
965
|
+
"--disable-hang-monitor",
|
|
966
|
+
"--disable-ipc-flooding-protection",
|
|
967
|
+
"--disable-notifications",
|
|
968
|
+
"--disable-offer-store-unmasked-wallet-cards",
|
|
969
|
+
"--disable-print-preview",
|
|
970
|
+
"--disable-prompt-on-repost",
|
|
971
|
+
"--disable-renderer-backgrounding",
|
|
972
|
+
"--disable-setuid-sandbox",
|
|
973
|
+
"--disable-speech-api",
|
|
974
|
+
"--disable-sync",
|
|
975
|
+
"--hide-scrollbars",
|
|
976
|
+
"--ignore-gpu-blacklist",
|
|
977
|
+
"--metrics-recording-only",
|
|
978
|
+
"--mute-audio",
|
|
979
|
+
"--no-default-browser-check",
|
|
980
|
+
"--no-first-run",
|
|
981
|
+
"--no-pings",
|
|
982
|
+
"--password-store=basic",
|
|
983
|
+
"--use-gl=swiftshader",
|
|
984
|
+
"--use-mock-keychain",
|
|
985
|
+
"--disable-accelerated-2d-canvas",
|
|
986
|
+
"--no-zygote",
|
|
987
|
+
"--disable-gpu"
|
|
988
|
+
];
|
|
989
|
+
const PDF_OPTION_KEYS = {
|
|
990
|
+
scale: true,
|
|
991
|
+
displayHeaderFooter: true,
|
|
992
|
+
headerTemplate: true,
|
|
993
|
+
footerTemplate: true,
|
|
994
|
+
printBackground: true,
|
|
995
|
+
landscape: true,
|
|
996
|
+
pageRanges: true,
|
|
997
|
+
format: true,
|
|
998
|
+
width: true,
|
|
999
|
+
height: true,
|
|
1000
|
+
preferCSSPageSize: true,
|
|
1001
|
+
margin: true,
|
|
1002
|
+
path: true,
|
|
1003
|
+
omitBackground: true,
|
|
1004
|
+
tagged: true,
|
|
1005
|
+
outline: true,
|
|
1006
|
+
timeout: true,
|
|
1007
|
+
waitForFonts: true
|
|
1008
|
+
};
|
|
1009
|
+
function toPuppeteerPdfOptions(options) {
|
|
1010
|
+
if (!options) return { format: "A4" };
|
|
1011
|
+
const invalidKeys = Object.keys(options).filter((key) => !Object.hasOwn(PDF_OPTION_KEYS, key));
|
|
1012
|
+
if (invalidKeys.length > 0) throw new RendererConfigurationException(`Invalid PDF options: ${invalidKeys.join(", ")}. Please check the documentation for valid options.`);
|
|
1013
|
+
return options;
|
|
1014
|
+
}
|
|
1015
|
+
var PuppeteerRenderer = class {
|
|
1016
|
+
#browserService;
|
|
1017
|
+
constructor(browserService) {
|
|
1018
|
+
this.#browserService = browserService;
|
|
1019
|
+
}
|
|
1020
|
+
async render(html, options, signal) {
|
|
1021
|
+
if (options.chromiumRevision !== void 0) Logger.warn("Using `chromiumRevision` is no longer supported since the puppeteer update.");
|
|
1022
|
+
const pdfOptions = toPuppeteerPdfOptions(options.pdfOptions);
|
|
1023
|
+
const headless = options.headless ?? true;
|
|
1024
|
+
const executablePath = options.executablePath || void 0;
|
|
1025
|
+
const args = options.extraPuppeteerArgs || DEFAULT_ARGS;
|
|
1026
|
+
let context = null;
|
|
1027
|
+
let closing;
|
|
1028
|
+
const onAbort = () => {
|
|
1029
|
+
if (!context) return;
|
|
1030
|
+
closing = context.close();
|
|
1031
|
+
closing.catch(() => void 0);
|
|
1032
|
+
};
|
|
1033
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1034
|
+
try {
|
|
1035
|
+
context = await this.#browserService.createContext(args, headless, executablePath);
|
|
1036
|
+
signal?.throwIfAborted();
|
|
1037
|
+
const page = await context.newPage();
|
|
1038
|
+
if (options.security) await installRequestGuard(context, page, options.security);
|
|
1039
|
+
await page.setContent(html, { waitUntil: "domcontentloaded" });
|
|
1040
|
+
await page.emulateMediaType("screen");
|
|
1041
|
+
await page.waitForNetworkIdle({
|
|
1042
|
+
idleTime: 500,
|
|
1043
|
+
timeout: 3e4
|
|
1044
|
+
});
|
|
1045
|
+
/* v8 ignore next */
|
|
1046
|
+
await page.evaluate(() => document.fonts.ready);
|
|
1047
|
+
return await page.pdf(pdfOptions);
|
|
1048
|
+
} finally {
|
|
1049
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1050
|
+
if (context) try {
|
|
1051
|
+
if (closing) await closing;
|
|
1052
|
+
else await context.close();
|
|
1053
|
+
} catch (error) {
|
|
1054
|
+
Logger.error(error);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
};
|
|
1059
|
+
// src/renderers/create-renderer.ts
|
|
1060
|
+
/** True when the PDFs are printed by the local Chromium (the default). */
|
|
1061
|
+
function usesPuppeteer(params) {
|
|
1062
|
+
return (params.provider?.type ?? "puppeteer") === "puppeteer";
|
|
1063
|
+
}
|
|
1064
|
+
function createPdfRenderer(params, browserService) {
|
|
1065
|
+
const provider = params.provider ?? { type: "puppeteer" };
|
|
1066
|
+
switch (provider.type) {
|
|
1067
|
+
case "puppeteer": return new PuppeteerRenderer(browserService);
|
|
1068
|
+
case "gotenberg": return new GotenbergRenderer(provider);
|
|
1069
|
+
case "api2pdf": return new Api2PdfRenderer(provider);
|
|
1070
|
+
default: throw new RendererConfigurationException(`Unknown PDF provider '${String(provider.type)}': expected 'puppeteer', 'gotenberg' or 'api2pdf'`);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
// src/puppeteer/libs/enum.utils.ts
|
|
1074
|
+
/**
|
|
1075
|
+
* Converts a string value to an enum member, throwing a RendererConfigurationException if the value is not a valid member of the enum.
|
|
1076
|
+
* @param enumObject
|
|
1077
|
+
* @param value
|
|
1078
|
+
* @param label
|
|
1079
|
+
* @throws RendererConfigurationException
|
|
1080
|
+
*/
|
|
1081
|
+
function toEnumMember(enumObject, value, label) {
|
|
1082
|
+
const members = Object.values(enumObject);
|
|
1083
|
+
const isMember = (candidate) => candidate === value;
|
|
1084
|
+
const member = members.find(isMember);
|
|
1085
|
+
if (member === void 0) throw new RendererConfigurationException(`Unsupported ${label} '${value}': expected one of ${members.map((m) => `'${m}'`).join(", ")}`);
|
|
1086
|
+
return member;
|
|
1087
|
+
}
|
|
1088
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/decorateMetadata.js
|
|
679
1089
|
function __decorateMetadata(k, v) {
|
|
680
1090
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
681
1091
|
}
|
|
682
|
-
|
|
683
|
-
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
|
|
1092
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/decorateParam.js
|
|
684
1093
|
function __decorateParam(paramIndex, decorator) {
|
|
685
1094
|
return function(target, key) {
|
|
686
1095
|
decorator(target, key, paramIndex);
|
|
687
1096
|
};
|
|
688
1097
|
}
|
|
689
|
-
|
|
690
|
-
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
|
|
1098
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/decorate.js
|
|
691
1099
|
function __decorate(decorators, target, key, desc) {
|
|
692
1100
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
693
1101
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
694
1102
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
695
1103
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
696
1104
|
}
|
|
697
|
-
|
|
698
|
-
|
|
1105
|
+
// src/puppeteer/browser/browser.service.ts
|
|
1106
|
+
const DEFAULT_BROWSER = "chromium";
|
|
699
1107
|
async function sleep(ms) {
|
|
700
1108
|
await new Promise((r) => setTimeout(r, ms));
|
|
701
1109
|
}
|
|
@@ -747,7 +1155,7 @@ let BrowserService = class BrowserService {
|
|
|
747
1155
|
} catch (error) {
|
|
748
1156
|
Logger.warn(`Failed to close browser on module destroy: ${error instanceof Error ? error.message : String(error)}`);
|
|
749
1157
|
}
|
|
750
|
-
if (this.#options
|
|
1158
|
+
if (this.#options !== void 0 && usesPuppeteer(this.#options) && this.#options.cleanupBrowserCacheOnExit !== false) await this.#cleanupCacheBestEffort();
|
|
751
1159
|
}
|
|
752
1160
|
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
753
1161
|
async #waitForIdle(timeoutMs) {
|
|
@@ -829,7 +1237,8 @@ let BrowserService = class BrowserService {
|
|
|
829
1237
|
}
|
|
830
1238
|
}
|
|
831
1239
|
async #doInstall(lock) {
|
|
832
|
-
const
|
|
1240
|
+
const { Browser: BrowserEnum, BrowserPlatform, canDownload, detectBrowserPlatform, install, resolveBuildId } = await loadPuppeteerBrowsers();
|
|
1241
|
+
const browser = toEnumMember(BrowserEnum, this.#browser, "browser");
|
|
833
1242
|
const versionTag = this.#browserTag;
|
|
834
1243
|
const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
|
|
835
1244
|
let buildId;
|
|
@@ -861,10 +1270,7 @@ let BrowserService = class BrowserService {
|
|
|
861
1270
|
return null;
|
|
862
1271
|
}
|
|
863
1272
|
#loadBrowser() {
|
|
864
|
-
|
|
865
|
-
if (this.#options?.browser === void 0) browser = Browser$1.CHROMIUM;
|
|
866
|
-
else browser = this.#options.browser;
|
|
867
|
-
this.#browser = browser;
|
|
1273
|
+
this.#browser = this.#options?.browser ?? DEFAULT_BROWSER;
|
|
868
1274
|
}
|
|
869
1275
|
getBrowser() {
|
|
870
1276
|
return this.#browser;
|
|
@@ -872,7 +1278,7 @@ let BrowserService = class BrowserService {
|
|
|
872
1278
|
#loadBrowserTag() {
|
|
873
1279
|
let versionTag;
|
|
874
1280
|
if (this.#options?.browserTag === void 0) {
|
|
875
|
-
if (this.#browser ===
|
|
1281
|
+
if (this.#browser === DEFAULT_BROWSER) versionTag = "latest";
|
|
876
1282
|
else versionTag = "stable";
|
|
877
1283
|
} else versionTag = this.#options.browserTag;
|
|
878
1284
|
this.#browserTag = versionTag;
|
|
@@ -899,12 +1305,15 @@ let BrowserService = class BrowserService {
|
|
|
899
1305
|
this.#useLockedBrowser = useLockedBrowser;
|
|
900
1306
|
}
|
|
901
1307
|
async hasBrowserInstalled(browser, buildId) {
|
|
1308
|
+
const { Browser: BrowserEnum, getInstalledBrowsers } = await loadPuppeteerBrowsers();
|
|
1309
|
+
const expected = toEnumMember(BrowserEnum, browser, "browser");
|
|
902
1310
|
return (await getInstalledBrowsers({ cacheDir: this.#cacheDir })).find((insBrowser) => {
|
|
903
|
-
return insBrowser.browser ===
|
|
1311
|
+
return insBrowser.browser === expected && insBrowser.buildId === buildId;
|
|
904
1312
|
}) !== void 0;
|
|
905
1313
|
}
|
|
906
1314
|
async getExecutablePath() {
|
|
907
|
-
const
|
|
1315
|
+
const { Browser: BrowserEnum, BrowserPlatform, detectBrowserPlatform, getInstalledBrowsers, resolveBuildId } = await loadPuppeteerBrowsers();
|
|
1316
|
+
const browser = toEnumMember(BrowserEnum, this.#browser, "browser");
|
|
908
1317
|
const versionTag = this.#browserTag;
|
|
909
1318
|
const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
|
|
910
1319
|
let buildId = null;
|
|
@@ -925,6 +1334,7 @@ let BrowserService = class BrowserService {
|
|
|
925
1334
|
}
|
|
926
1335
|
async #launchBrowser(args, headless, executablePathBin) {
|
|
927
1336
|
const executablePath = executablePathBin ?? await this.getExecutablePath();
|
|
1337
|
+
const { launch } = await loadPuppeteer();
|
|
928
1338
|
const browser = await launch({
|
|
929
1339
|
executablePath,
|
|
930
1340
|
headless,
|
|
@@ -961,12 +1371,33 @@ BrowserService = __decorate([
|
|
|
961
1371
|
__decorateParam(0, Inject("PDF_PARAMETERS")),
|
|
962
1372
|
__decorateMetadata("design:paramtypes", [Object])
|
|
963
1373
|
], BrowserService);
|
|
964
|
-
|
|
965
|
-
|
|
1374
|
+
// src/puppeteer/libs/loadEngine.utils.ts
|
|
1375
|
+
const requireEngine = createRequire(import.meta.url);
|
|
1376
|
+
/**
|
|
1377
|
+
* Load an optional template engine on first use, so the library can be imported
|
|
1378
|
+
* without every engine installed. `require` (not `import()`) is used on purpose:
|
|
1379
|
+
* most engines expose a synchronous render API.
|
|
1380
|
+
*/
|
|
1381
|
+
function loadEngine(packageName, engineName) {
|
|
1382
|
+
let mod;
|
|
1383
|
+
try {
|
|
1384
|
+
mod = requireEngine(packageName);
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
if (error.code === "MODULE_NOT_FOUND") throw new EngineNotAvailableException(engineName, packageName, { cause: error });
|
|
1387
|
+
throw error;
|
|
1388
|
+
}
|
|
1389
|
+
return mod.__esModule && "default" in mod ? mod.default : mod;
|
|
1390
|
+
}
|
|
1391
|
+
// src/puppeteer/engines/ejs/ejs.service.ts
|
|
966
1392
|
let EjsService = class EjsService {
|
|
1393
|
+
#ejs;
|
|
1394
|
+
get #engine() {
|
|
1395
|
+
return this.#ejs ??= loadEngine("ejs", "EJS");
|
|
1396
|
+
}
|
|
967
1397
|
async render(template, data = {}, options) {
|
|
1398
|
+
const engine = this.#engine;
|
|
968
1399
|
try {
|
|
969
|
-
return await
|
|
1400
|
+
return await engine.render(template, data, {
|
|
970
1401
|
async: true,
|
|
971
1402
|
...options
|
|
972
1403
|
});
|
|
@@ -975,8 +1406,9 @@ let EjsService = class EjsService {
|
|
|
975
1406
|
}
|
|
976
1407
|
}
|
|
977
1408
|
async renderFile(filePath, data = {}, options) {
|
|
1409
|
+
const engine = this.#engine;
|
|
978
1410
|
try {
|
|
979
|
-
return await
|
|
1411
|
+
return await engine.renderFile(filePath, data, {
|
|
980
1412
|
async: true,
|
|
981
1413
|
...options
|
|
982
1414
|
});
|
|
@@ -986,18 +1418,14 @@ let EjsService = class EjsService {
|
|
|
986
1418
|
}
|
|
987
1419
|
};
|
|
988
1420
|
EjsService = __decorate([Injectable()], EjsService);
|
|
989
|
-
|
|
990
|
-
//#region src/puppeteer/engines/eta/eta.service.ts
|
|
1421
|
+
// src/puppeteer/engines/eta/eta.service.ts
|
|
991
1422
|
let EtaService = class EtaService {
|
|
1423
|
+
#etaModule;
|
|
992
1424
|
#eta;
|
|
993
1425
|
#templateCache = /* @__PURE__ */ new Map();
|
|
994
1426
|
#maxCacheSize = 100;
|
|
995
|
-
|
|
996
|
-
this.#
|
|
997
|
-
cache: true,
|
|
998
|
-
autoEscape: true,
|
|
999
|
-
useWith: true
|
|
1000
|
-
});
|
|
1427
|
+
get #engine() {
|
|
1428
|
+
return this.#etaModule ??= loadEngine("eta", "Eta");
|
|
1001
1429
|
}
|
|
1002
1430
|
/**
|
|
1003
1431
|
* Render an Eta template from a string
|
|
@@ -1007,6 +1435,7 @@ let EtaService = class EtaService {
|
|
|
1007
1435
|
* @returns The rendered HTML string
|
|
1008
1436
|
*/
|
|
1009
1437
|
render(template, data = {}, options) {
|
|
1438
|
+
const { Eta } = this.#engine;
|
|
1010
1439
|
try {
|
|
1011
1440
|
return (options && Object.keys(options).length > 0 ? new Eta({
|
|
1012
1441
|
cache: true,
|
|
@@ -1014,7 +1443,11 @@ let EtaService = class EtaService {
|
|
|
1014
1443
|
useWith: true,
|
|
1015
1444
|
...options,
|
|
1016
1445
|
varName: options.varName ?? "it"
|
|
1017
|
-
}) : this.#eta
|
|
1446
|
+
}) : this.#eta ??= new Eta({
|
|
1447
|
+
cache: true,
|
|
1448
|
+
autoEscape: true,
|
|
1449
|
+
useWith: true
|
|
1450
|
+
})).renderString(template, data);
|
|
1018
1451
|
} catch (error) {
|
|
1019
1452
|
throw new TemplateRenderException("Eta", `Eta rendering failed: ${String(error)}`, { cause: error });
|
|
1020
1453
|
}
|
|
@@ -1037,6 +1470,7 @@ let EtaService = class EtaService {
|
|
|
1037
1470
|
}
|
|
1038
1471
|
return this.render(template, data, options);
|
|
1039
1472
|
} catch (error) {
|
|
1473
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1040
1474
|
throw new TemplateRenderException("Eta", `Eta file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
1041
1475
|
}
|
|
1042
1476
|
}
|
|
@@ -1054,12 +1488,15 @@ let EtaService = class EtaService {
|
|
|
1054
1488
|
return this.#templateCache.size;
|
|
1055
1489
|
}
|
|
1056
1490
|
};
|
|
1057
|
-
EtaService = __decorate([Injectable()
|
|
1058
|
-
|
|
1059
|
-
//#region src/puppeteer/engines/handlebars/handlebars.service.ts
|
|
1491
|
+
EtaService = __decorate([Injectable()], EtaService);
|
|
1492
|
+
// src/puppeteer/engines/handlebars/handlebars.service.ts
|
|
1060
1493
|
let HandlebarsService = class HandlebarsService {
|
|
1494
|
+
#handlebars;
|
|
1061
1495
|
#cachedOptions;
|
|
1062
1496
|
#cachedEnv;
|
|
1497
|
+
get #engine() {
|
|
1498
|
+
return this.#handlebars ??= loadEngine("handlebars", "Handlebars");
|
|
1499
|
+
}
|
|
1063
1500
|
render(template, parameters = {}, options = {}) {
|
|
1064
1501
|
try {
|
|
1065
1502
|
return this.#getEnv(options).compile(template, options.compileOptions)(parameters, options.templateOptions);
|
|
@@ -1088,7 +1525,7 @@ let HandlebarsService = class HandlebarsService {
|
|
|
1088
1525
|
*/
|
|
1089
1526
|
#getEnv(options) {
|
|
1090
1527
|
if (this.#cachedEnv && this.#cachedOptions === options) return this.#cachedEnv;
|
|
1091
|
-
const env =
|
|
1528
|
+
const env = this.#engine.create();
|
|
1092
1529
|
for (const helper of options.helpers ?? []) env.registerHelper(helper.name, helper.fn);
|
|
1093
1530
|
this.#registerPartials(env, options.partialDirectory);
|
|
1094
1531
|
this.#cachedOptions = options;
|
|
@@ -1107,12 +1544,77 @@ let HandlebarsService = class HandlebarsService {
|
|
|
1107
1544
|
}
|
|
1108
1545
|
};
|
|
1109
1546
|
HandlebarsService = __decorate([Injectable()], HandlebarsService);
|
|
1110
|
-
|
|
1111
|
-
|
|
1547
|
+
// src/puppeteer/engines/liquid/liquid.service.ts
|
|
1548
|
+
let LiquidService = class LiquidService {
|
|
1549
|
+
#liquidModule;
|
|
1550
|
+
#liquid;
|
|
1551
|
+
#templateCache = /* @__PURE__ */ new Map();
|
|
1552
|
+
#maxCacheSize = 100;
|
|
1553
|
+
get #engine() {
|
|
1554
|
+
return this.#liquidModule ??= loadEngine("liquidjs", "Liquid");
|
|
1555
|
+
}
|
|
1556
|
+
/**
|
|
1557
|
+
* Render a Liquid template from a string
|
|
1558
|
+
* @param template The template string to render
|
|
1559
|
+
* @param data The data object to use for rendering
|
|
1560
|
+
* @param options Optional Liquid engine options
|
|
1561
|
+
* @returns The rendered HTML string
|
|
1562
|
+
*/
|
|
1563
|
+
render(template, data = {}, options) {
|
|
1564
|
+
const { Liquid } = this.#engine;
|
|
1565
|
+
try {
|
|
1566
|
+
return (options && Object.keys(options).length > 0 ? new Liquid(options) : this.#liquid ??= new Liquid()).parseAndRenderSync(template, data);
|
|
1567
|
+
} catch (error) {
|
|
1568
|
+
throw new TemplateRenderException("Liquid", `Liquid rendering failed: ${String(error)}`, { cause: error });
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* Render a Liquid template from a file
|
|
1573
|
+
* @param filePath The path to the template file
|
|
1574
|
+
* @param data The data object to use for rendering
|
|
1575
|
+
* @param options Optional Liquid engine options
|
|
1576
|
+
* @returns The rendered HTML string
|
|
1577
|
+
*/
|
|
1578
|
+
renderFile(filePath, data = {}, options) {
|
|
1579
|
+
try {
|
|
1580
|
+
const resolvedPath = resolve(filePath);
|
|
1581
|
+
const useCache = options?.cache !== false;
|
|
1582
|
+
let template = useCache ? this.#templateCache.get(resolvedPath) : void 0;
|
|
1583
|
+
if (!template) {
|
|
1584
|
+
template = readFileSync(resolvedPath, "utf-8");
|
|
1585
|
+
if (useCache && this.#templateCache.size < this.#maxCacheSize) this.#templateCache.set(resolvedPath, template);
|
|
1586
|
+
}
|
|
1587
|
+
return this.render(template, data, options);
|
|
1588
|
+
} catch (error) {
|
|
1589
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1590
|
+
throw new TemplateRenderException("Liquid", `Liquid file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Clear the template cache
|
|
1595
|
+
*/
|
|
1596
|
+
clearCache() {
|
|
1597
|
+
this.#templateCache.clear();
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Get the current cache size
|
|
1601
|
+
* @returns The number of cached templates
|
|
1602
|
+
*/
|
|
1603
|
+
getCacheSize() {
|
|
1604
|
+
return this.#templateCache.size;
|
|
1605
|
+
}
|
|
1606
|
+
};
|
|
1607
|
+
LiquidService = __decorate([Injectable()], LiquidService);
|
|
1608
|
+
// src/puppeteer/engines/mjml/mjml.service.ts
|
|
1112
1609
|
let MjmlService = class MjmlService {
|
|
1610
|
+
#mjml;
|
|
1611
|
+
get #engine() {
|
|
1612
|
+
return this.#mjml ??= loadEngine("mjml", "MJML");
|
|
1613
|
+
}
|
|
1113
1614
|
async render(template, options) {
|
|
1615
|
+
const engine = this.#engine;
|
|
1114
1616
|
try {
|
|
1115
|
-
const { html } = await
|
|
1617
|
+
const { html } = await engine(template, options);
|
|
1116
1618
|
return html;
|
|
1117
1619
|
} catch (error) {
|
|
1118
1620
|
throw new TemplateRenderException("MJML", `MJML rendering failed: ${String(error)}`, { cause: error });
|
|
@@ -1129,11 +1631,14 @@ let MjmlService = class MjmlService {
|
|
|
1129
1631
|
}
|
|
1130
1632
|
};
|
|
1131
1633
|
MjmlService = __decorate([Injectable()], MjmlService);
|
|
1132
|
-
|
|
1133
|
-
//#region src/puppeteer/engines/mustache/mustache.service.ts
|
|
1634
|
+
// src/puppeteer/engines/mustache/mustache.service.ts
|
|
1134
1635
|
let MustacheService = class MustacheService {
|
|
1636
|
+
#mustache;
|
|
1135
1637
|
#templateCache = /* @__PURE__ */ new Map();
|
|
1136
1638
|
#maxCacheSize = 100;
|
|
1639
|
+
get #engine() {
|
|
1640
|
+
return this.#mustache ??= loadEngine("mustache", "Mustache");
|
|
1641
|
+
}
|
|
1137
1642
|
/**
|
|
1138
1643
|
* Render a Mustache template from a string
|
|
1139
1644
|
* @param template The template string to render
|
|
@@ -1142,9 +1647,10 @@ let MustacheService = class MustacheService {
|
|
|
1142
1647
|
* @returns The rendered HTML string
|
|
1143
1648
|
*/
|
|
1144
1649
|
render(template, data = {}, options) {
|
|
1650
|
+
const engine = this.#engine;
|
|
1145
1651
|
try {
|
|
1146
1652
|
const tags = options?.tags ?? ["{{", "}}"];
|
|
1147
|
-
return
|
|
1653
|
+
return engine.render(template, data, void 0, {
|
|
1148
1654
|
tags,
|
|
1149
1655
|
escape: options?.escape
|
|
1150
1656
|
});
|
|
@@ -1169,6 +1675,7 @@ let MustacheService = class MustacheService {
|
|
|
1169
1675
|
}
|
|
1170
1676
|
return this.render(template, data, options);
|
|
1171
1677
|
} catch (error) {
|
|
1678
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1172
1679
|
throw new TemplateRenderException("Mustache", `Mustache file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
1173
1680
|
}
|
|
1174
1681
|
}
|
|
@@ -1187,17 +1694,22 @@ let MustacheService = class MustacheService {
|
|
|
1187
1694
|
}
|
|
1188
1695
|
};
|
|
1189
1696
|
MustacheService = __decorate([Injectable()], MustacheService);
|
|
1190
|
-
|
|
1191
|
-
//#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
1697
|
+
// src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
1192
1698
|
let NunjucksService = class NunjucksService {
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1699
|
+
#nunjucks;
|
|
1700
|
+
get #engine() {
|
|
1701
|
+
if (!this.#nunjucks) {
|
|
1702
|
+
this.#nunjucks = loadEngine("nunjucks", "Nunjucks");
|
|
1703
|
+
this.#nunjucks.configure({
|
|
1704
|
+
noCache: true,
|
|
1705
|
+
trimBlocks: true,
|
|
1706
|
+
lstripBlocks: true
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
return this.#nunjucks;
|
|
1199
1710
|
}
|
|
1200
1711
|
render(template, data = {}, options) {
|
|
1712
|
+
const nunjucks = this.#engine;
|
|
1201
1713
|
try {
|
|
1202
1714
|
if (options) {
|
|
1203
1715
|
const configOptions = {
|
|
@@ -1215,6 +1727,7 @@ let NunjucksService = class NunjucksService {
|
|
|
1215
1727
|
}
|
|
1216
1728
|
}
|
|
1217
1729
|
renderFile(filePath, data = {}, options) {
|
|
1730
|
+
const nunjucks = this.#engine;
|
|
1218
1731
|
try {
|
|
1219
1732
|
if (options) {
|
|
1220
1733
|
const configOptions = {
|
|
@@ -1232,13 +1745,17 @@ let NunjucksService = class NunjucksService {
|
|
|
1232
1745
|
}
|
|
1233
1746
|
}
|
|
1234
1747
|
};
|
|
1235
|
-
NunjucksService = __decorate([Injectable()
|
|
1236
|
-
|
|
1237
|
-
//#region src/puppeteer/engines/pug/pug.service.ts
|
|
1748
|
+
NunjucksService = __decorate([Injectable()], NunjucksService);
|
|
1749
|
+
// src/puppeteer/engines/pug/pug.service.ts
|
|
1238
1750
|
let PugService = class PugService {
|
|
1751
|
+
#pug;
|
|
1752
|
+
get #engine() {
|
|
1753
|
+
return this.#pug ??= loadEngine("pug", "Pug");
|
|
1754
|
+
}
|
|
1239
1755
|
render(template, data = {}, options) {
|
|
1756
|
+
const engine = this.#engine;
|
|
1240
1757
|
try {
|
|
1241
|
-
return
|
|
1758
|
+
return engine.compile(template, { ...options })(data);
|
|
1242
1759
|
} catch (error) {
|
|
1243
1760
|
throw new TemplateRenderException("Pug", `Pug rendering failed: ${String(error)}`, { cause: error });
|
|
1244
1761
|
}
|
|
@@ -1248,21 +1765,21 @@ let PugService = class PugService {
|
|
|
1248
1765
|
const template = readFileSync(filePath, "utf-8");
|
|
1249
1766
|
return this.render(template, data, options);
|
|
1250
1767
|
} catch (error) {
|
|
1768
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1251
1769
|
throw new TemplateRenderException("Pug", `Pug file rendering failed: ${String(error)}`, { cause: error });
|
|
1252
1770
|
}
|
|
1253
1771
|
}
|
|
1254
1772
|
};
|
|
1255
1773
|
PugService = __decorate([Injectable()], PugService);
|
|
1256
|
-
|
|
1257
|
-
//#region src/puppeteer/libs/requireService.utils.ts
|
|
1774
|
+
// src/puppeteer/libs/requireService.utils.ts
|
|
1258
1775
|
function requireService(service, name) {
|
|
1259
1776
|
if (!service) throw new EngineNotAvailableException(name);
|
|
1260
1777
|
return service;
|
|
1261
1778
|
}
|
|
1262
|
-
|
|
1263
|
-
//#region src/puppeteer/puppeteer.service.ts
|
|
1779
|
+
// src/puppeteer/puppeteer.service.ts
|
|
1264
1780
|
let PuppeteerService = class PuppeteerService {
|
|
1265
|
-
#
|
|
1781
|
+
#renderer;
|
|
1782
|
+
#jobs;
|
|
1266
1783
|
#options;
|
|
1267
1784
|
#hbsService;
|
|
1268
1785
|
#mjmlService;
|
|
@@ -1271,8 +1788,10 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1271
1788
|
#nunjucksService;
|
|
1272
1789
|
#etaService;
|
|
1273
1790
|
#mustacheService;
|
|
1274
|
-
|
|
1275
|
-
|
|
1791
|
+
#liquidService;
|
|
1792
|
+
constructor(renderer, jobs, options, hbsService, mjmlService, pugService, ejsService, nunjucksService, etaService, mustacheService, liquidService) {
|
|
1793
|
+
this.#renderer = renderer;
|
|
1794
|
+
this.#jobs = jobs;
|
|
1276
1795
|
this.#options = options;
|
|
1277
1796
|
this.#hbsService = hbsService;
|
|
1278
1797
|
this.#mjmlService = mjmlService;
|
|
@@ -1281,6 +1800,7 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1281
1800
|
this.#nunjucksService = nunjucksService;
|
|
1282
1801
|
this.#etaService = etaService;
|
|
1283
1802
|
this.#mustacheService = mustacheService;
|
|
1803
|
+
this.#liquidService = liquidService;
|
|
1284
1804
|
}
|
|
1285
1805
|
#limit = pLimit(3);
|
|
1286
1806
|
async generatePdfFromHtml(html, options) {
|
|
@@ -1290,87 +1810,19 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1290
1810
|
const job = this.#limit(async () => {
|
|
1291
1811
|
signal?.throwIfAborted();
|
|
1292
1812
|
started = true;
|
|
1293
|
-
const
|
|
1294
|
-
|
|
1295
|
-
const headless = mergePuppeteerOptions.headless ?? true;
|
|
1296
|
-
const executablePath = mergePuppeteerOptions.executablePath || void 0;
|
|
1297
|
-
const args = mergePuppeteerOptions.extraPuppeteerArgs || [
|
|
1298
|
-
"--autoplay-policy=user-gesture-required",
|
|
1299
|
-
"--disable-background-networking",
|
|
1300
|
-
"--disable-background-timer-throttling",
|
|
1301
|
-
"--disable-backgrounding-occluded-windows",
|
|
1302
|
-
"--disable-breakpad",
|
|
1303
|
-
"--disable-client-side-phishing-detection",
|
|
1304
|
-
"--disable-component-update",
|
|
1305
|
-
"--disable-default-apps",
|
|
1306
|
-
"--disable-dev-shm-usage",
|
|
1307
|
-
"--disable-domain-reliability",
|
|
1308
|
-
"--disable-extensions",
|
|
1309
|
-
"--disable-features=AudioServiceOutOfProcess",
|
|
1310
|
-
"--disable-hang-monitor",
|
|
1311
|
-
"--disable-ipc-flooding-protection",
|
|
1312
|
-
"--disable-notifications",
|
|
1313
|
-
"--disable-offer-store-unmasked-wallet-cards",
|
|
1314
|
-
"--disable-print-preview",
|
|
1315
|
-
"--disable-prompt-on-repost",
|
|
1316
|
-
"--disable-renderer-backgrounding",
|
|
1317
|
-
"--disable-setuid-sandbox",
|
|
1318
|
-
"--disable-speech-api",
|
|
1319
|
-
"--disable-sync",
|
|
1320
|
-
"--hide-scrollbars",
|
|
1321
|
-
"--ignore-gpu-blacklist",
|
|
1322
|
-
"--metrics-recording-only",
|
|
1323
|
-
"--mute-audio",
|
|
1324
|
-
"--no-default-browser-check",
|
|
1325
|
-
"--no-first-run",
|
|
1326
|
-
"--no-pings",
|
|
1327
|
-
"--password-store=basic",
|
|
1328
|
-
"--use-gl=swiftshader",
|
|
1329
|
-
"--use-mock-keychain",
|
|
1330
|
-
"--disable-accelerated-2d-canvas",
|
|
1331
|
-
"--no-zygote",
|
|
1332
|
-
"--disable-gpu"
|
|
1333
|
-
];
|
|
1334
|
-
this.#browserService.markJobStarted();
|
|
1335
|
-
let context = null;
|
|
1336
|
-
let closing;
|
|
1337
|
-
const onAbort = () => {
|
|
1338
|
-
if (!context) return;
|
|
1339
|
-
closing = context.close();
|
|
1340
|
-
closing.catch(() => void 0);
|
|
1341
|
-
};
|
|
1342
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1813
|
+
const mergedOptions = mergePuppeteerParameters(this.#options, options);
|
|
1814
|
+
this.#jobs.markJobStarted();
|
|
1343
1815
|
try {
|
|
1344
|
-
|
|
1816
|
+
const pdf = await this.#renderer.render(html, mergedOptions, signal);
|
|
1345
1817
|
signal?.throwIfAborted();
|
|
1346
|
-
|
|
1347
|
-
if (mergePuppeteerOptions.security) await installRequestGuard(context, page, mergePuppeteerOptions.security);
|
|
1348
|
-
const pdfOptions = mergePuppeteerOptions.pdfOptions ?? { format: "A4" };
|
|
1349
|
-
await page.setContent(html, { waitUntil: "domcontentloaded" });
|
|
1350
|
-
await page.emulateMediaType("screen");
|
|
1351
|
-
await page.waitForNetworkIdle({
|
|
1352
|
-
idleTime: 500,
|
|
1353
|
-
timeout: 3e4
|
|
1354
|
-
});
|
|
1355
|
-
/* v8 ignore next */
|
|
1356
|
-
await page.evaluate(() => document.fonts.ready);
|
|
1357
|
-
const pdf = await page.pdf(pdfOptions);
|
|
1358
|
-
signal?.throwIfAborted();
|
|
1359
|
-
return mergePuppeteerOptions.watermark ? await addWatermark(pdf, mergePuppeteerOptions.watermark) : pdf;
|
|
1818
|
+
return mergedOptions.watermark ? await addWatermark(pdf, mergedOptions.watermark) : pdf;
|
|
1360
1819
|
} catch (e) {
|
|
1361
1820
|
if (signal?.aborted) throw signal.reason;
|
|
1362
1821
|
Logger.error(e);
|
|
1363
1822
|
if (e instanceof NestjsPdfException) throw e;
|
|
1364
1823
|
throw new PdfGenerationException(`PDF generation failed: ${String(e)}`, { cause: e });
|
|
1365
1824
|
} finally {
|
|
1366
|
-
|
|
1367
|
-
if (context) try {
|
|
1368
|
-
if (closing) await closing;
|
|
1369
|
-
else await context.close();
|
|
1370
|
-
} catch (error) {
|
|
1371
|
-
Logger.error(error);
|
|
1372
|
-
}
|
|
1373
|
-
await this.#browserService.markJobFinished();
|
|
1825
|
+
await this.#jobs.markJobFinished();
|
|
1374
1826
|
}
|
|
1375
1827
|
});
|
|
1376
1828
|
if (!signal) return job;
|
|
@@ -1443,19 +1895,31 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1443
1895
|
const html = requireService(this.#mustacheService, "Mustache").renderFile(file, data, options?.mustacheOptions ?? this.#options.mustacheOptions);
|
|
1444
1896
|
return this.generatePdfFromHtml(html, options);
|
|
1445
1897
|
}
|
|
1898
|
+
async generatePdfFromLiquidString(template, data = {}, options) {
|
|
1899
|
+
const html = requireService(this.#liquidService, "Liquid").render(template, data, options?.liquidOptions ?? this.#options.liquidOptions);
|
|
1900
|
+
return this.generatePdfFromHtml(html, options);
|
|
1901
|
+
}
|
|
1902
|
+
async generatePdfFromLiquidFile(file, data = {}, options) {
|
|
1903
|
+
const html = requireService(this.#liquidService, "Liquid").renderFile(file, data, options?.liquidOptions ?? this.#options.liquidOptions);
|
|
1904
|
+
return this.generatePdfFromHtml(html, options);
|
|
1905
|
+
}
|
|
1446
1906
|
};
|
|
1447
1907
|
PuppeteerService = __decorate([
|
|
1448
1908
|
Injectable(),
|
|
1449
|
-
__decorateParam(
|
|
1450
|
-
__decorateParam(
|
|
1909
|
+
__decorateParam(0, Inject(PDF_RENDERER)),
|
|
1910
|
+
__decorateParam(1, Inject(BrowserService)),
|
|
1911
|
+
__decorateParam(2, Inject(PDF_PARAMETERS)),
|
|
1451
1912
|
__decorateParam(3, Optional()),
|
|
1452
1913
|
__decorateParam(4, Optional()),
|
|
1453
1914
|
__decorateParam(5, Optional()),
|
|
1454
1915
|
__decorateParam(6, Optional()),
|
|
1455
1916
|
__decorateParam(7, Optional()),
|
|
1456
1917
|
__decorateParam(8, Optional()),
|
|
1918
|
+
__decorateParam(9, Optional()),
|
|
1919
|
+
__decorateParam(10, Optional()),
|
|
1457
1920
|
__decorateMetadata("design:paramtypes", [
|
|
1458
|
-
|
|
1921
|
+
Object,
|
|
1922
|
+
Object,
|
|
1459
1923
|
Object,
|
|
1460
1924
|
typeof HandlebarsService === "undefined" ? Object : HandlebarsService,
|
|
1461
1925
|
typeof MjmlService === "undefined" ? Object : MjmlService,
|
|
@@ -1463,11 +1927,11 @@ PuppeteerService = __decorate([
|
|
|
1463
1927
|
typeof EjsService === "undefined" ? Object : EjsService,
|
|
1464
1928
|
typeof NunjucksService === "undefined" ? Object : NunjucksService,
|
|
1465
1929
|
typeof EtaService === "undefined" ? Object : EtaService,
|
|
1466
|
-
typeof MustacheService === "undefined" ? Object : MustacheService
|
|
1930
|
+
typeof MustacheService === "undefined" ? Object : MustacheService,
|
|
1931
|
+
typeof LiquidService === "undefined" ? Object : LiquidService
|
|
1467
1932
|
])
|
|
1468
1933
|
], PuppeteerService);
|
|
1469
|
-
|
|
1470
|
-
//#region src/nestjs-pdf.service.ts
|
|
1934
|
+
// src/nestjs-pdf.service.ts
|
|
1471
1935
|
let NestjsPdfService = class NestjsPdfService {
|
|
1472
1936
|
#puppeteerService;
|
|
1473
1937
|
constructor(puppeteerService) {
|
|
@@ -1621,6 +2085,26 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1621
2085
|
return this.#puppeteerService.generatePdfFromMustacheFile(file, data, options);
|
|
1622
2086
|
}
|
|
1623
2087
|
/**
|
|
2088
|
+
* @param template Liquid template string
|
|
2089
|
+
* @param data Data to inject into the template
|
|
2090
|
+
* @param options PDF generation options (optional)
|
|
2091
|
+
* @returns PDF generated from the provided Liquid template with data applied
|
|
2092
|
+
* @description This method generates a PDF from a Liquid template provided as a string. Liquid is a safe, Shopify-compatible template language with filters, tags, partials and layouts. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
2093
|
+
*/
|
|
2094
|
+
generatePdfFromLiquidString(template, data = {}, options) {
|
|
2095
|
+
return this.#puppeteerService.generatePdfFromLiquidString(template, data, options);
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* @param file Path to the Liquid template file
|
|
2099
|
+
* @param data Data to inject into the template
|
|
2100
|
+
* @param options PDF generation options (optional)
|
|
2101
|
+
* @returns PDF generated from the Liquid template at the provided file path with data applied
|
|
2102
|
+
* @description This method generates a PDF from a Liquid template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
2103
|
+
*/
|
|
2104
|
+
generatePdfFromLiquidFile(file, data = {}, options) {
|
|
2105
|
+
return this.#puppeteerService.generatePdfFromLiquidFile(file, data, options);
|
|
2106
|
+
}
|
|
2107
|
+
/**
|
|
1624
2108
|
* @param pdf The PDF bytes to modify
|
|
1625
2109
|
* @param fieldName The name of the signature field to add (default: 'SignatureDebtor')
|
|
1626
2110
|
* @param anchorText The text anchor to locate the signature field position (default: '__SIG_DEBTOR_ANCHOR__')
|
|
@@ -1667,9 +2151,14 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1667
2151
|
}
|
|
1668
2152
|
};
|
|
1669
2153
|
NestjsPdfService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof PuppeteerService === "undefined" ? Object : PuppeteerService])], NestjsPdfService);
|
|
1670
|
-
|
|
1671
|
-
//#region src/puppeteer/puppeteer.module.ts
|
|
2154
|
+
// src/puppeteer/puppeteer.module.ts
|
|
1672
2155
|
var _PuppeteerModule;
|
|
2156
|
+
/** Builds the renderer of the configured provider, once the parameters are known. */
|
|
2157
|
+
const pdfRendererProvider = {
|
|
2158
|
+
provide: PDF_RENDERER,
|
|
2159
|
+
inject: [PDF_PARAMETERS, BrowserService],
|
|
2160
|
+
useFactory: createPdfRenderer
|
|
2161
|
+
};
|
|
1673
2162
|
let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
1674
2163
|
#browserService;
|
|
1675
2164
|
#pdfParams;
|
|
@@ -1678,7 +2167,12 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1678
2167
|
this.#pdfParams = pdfParams;
|
|
1679
2168
|
}
|
|
1680
2169
|
async onModuleInit() {
|
|
1681
|
-
if (!this.#pdfParams
|
|
2170
|
+
if (!usesPuppeteer(this.#pdfParams)) return;
|
|
2171
|
+
await loadPuppeteer();
|
|
2172
|
+
if (!this.#pdfParams.executablePath) {
|
|
2173
|
+
await loadPuppeteerBrowsers();
|
|
2174
|
+
await this.#browserService.install(this.#pdfParams.useLockedBrowser ?? false);
|
|
2175
|
+
}
|
|
1682
2176
|
}
|
|
1683
2177
|
static forRoot(pdfParameters) {
|
|
1684
2178
|
return {
|
|
@@ -1694,7 +2188,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1694
2188
|
EjsService,
|
|
1695
2189
|
NunjucksService,
|
|
1696
2190
|
EtaService,
|
|
1697
|
-
MustacheService
|
|
2191
|
+
MustacheService,
|
|
2192
|
+
LiquidService
|
|
1698
2193
|
],
|
|
1699
2194
|
exports: [
|
|
1700
2195
|
PuppeteerService,
|
|
@@ -1703,7 +2198,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1703
2198
|
EjsService,
|
|
1704
2199
|
NunjucksService,
|
|
1705
2200
|
EtaService,
|
|
1706
|
-
MustacheService
|
|
2201
|
+
MustacheService,
|
|
2202
|
+
LiquidService
|
|
1707
2203
|
]
|
|
1708
2204
|
};
|
|
1709
2205
|
}
|
|
@@ -1720,13 +2216,15 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1720
2216
|
pdfParamsProvider,
|
|
1721
2217
|
PuppeteerService,
|
|
1722
2218
|
BrowserService,
|
|
2219
|
+
pdfRendererProvider,
|
|
1723
2220
|
HandlebarsService,
|
|
1724
2221
|
MjmlService,
|
|
1725
2222
|
PugService,
|
|
1726
2223
|
EjsService,
|
|
1727
2224
|
NunjucksService,
|
|
1728
2225
|
EtaService,
|
|
1729
|
-
MustacheService
|
|
2226
|
+
MustacheService,
|
|
2227
|
+
LiquidService
|
|
1730
2228
|
],
|
|
1731
2229
|
exports: [
|
|
1732
2230
|
PuppeteerService,
|
|
@@ -1735,7 +2233,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1735
2233
|
EjsService,
|
|
1736
2234
|
NunjucksService,
|
|
1737
2235
|
EtaService,
|
|
1738
|
-
MustacheService
|
|
2236
|
+
MustacheService,
|
|
2237
|
+
LiquidService
|
|
1739
2238
|
]
|
|
1740
2239
|
};
|
|
1741
2240
|
}
|
|
@@ -1745,12 +2244,14 @@ PuppeteerModule = _PuppeteerModule = __decorate([
|
|
|
1745
2244
|
providers: [
|
|
1746
2245
|
PuppeteerService,
|
|
1747
2246
|
BrowserService,
|
|
2247
|
+
pdfRendererProvider,
|
|
1748
2248
|
MjmlService,
|
|
1749
2249
|
PugService,
|
|
1750
2250
|
EjsService,
|
|
1751
2251
|
NunjucksService,
|
|
1752
2252
|
EtaService,
|
|
1753
|
-
MustacheService
|
|
2253
|
+
MustacheService,
|
|
2254
|
+
LiquidService
|
|
1754
2255
|
],
|
|
1755
2256
|
exports: [
|
|
1756
2257
|
PuppeteerService,
|
|
@@ -1759,14 +2260,15 @@ PuppeteerModule = _PuppeteerModule = __decorate([
|
|
|
1759
2260
|
EjsService,
|
|
1760
2261
|
NunjucksService,
|
|
1761
2262
|
EtaService,
|
|
1762
|
-
MustacheService
|
|
2263
|
+
MustacheService,
|
|
2264
|
+
LiquidService
|
|
1763
2265
|
]
|
|
1764
2266
|
}),
|
|
2267
|
+
__decorateParam(0, Inject(BrowserService)),
|
|
1765
2268
|
__decorateParam(1, Inject(PDF_PARAMETERS)),
|
|
1766
|
-
__decorateMetadata("design:paramtypes", [
|
|
2269
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
1767
2270
|
], PuppeteerModule);
|
|
1768
|
-
|
|
1769
|
-
//#region src/nestjs-pdf.module.ts
|
|
2271
|
+
// src/nestjs-pdf.module.ts
|
|
1770
2272
|
var _NestjsPdfModule;
|
|
1771
2273
|
let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
|
|
1772
2274
|
static forRoot(options) {
|
|
@@ -1787,7 +2289,6 @@ let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
|
|
|
1787
2289
|
}
|
|
1788
2290
|
};
|
|
1789
2291
|
NestjsPdfModule = _NestjsPdfModule = __decorate([Module({})], NestjsPdfModule);
|
|
1790
|
-
|
|
1791
|
-
export { BrowserInstallationException, BrowserUnavailableException, EjsService, EngineNotAvailableException, EtaService, HandlebarsService, MjmlService, MustacheService, NestjsPdfErrorCode, NestjsPdfException, NestjsPdfModule, NestjsPdfService, NunjucksService, PdfGenerationException, PugService, PuppeteerModule, PuppeteerService, SignatureDependencyException, SignaturePlacementException, TemplateConfigurationException, TemplateRenderException, WatermarkException, getRelativePathToValue };
|
|
2292
|
+
export { BrowserInstallationException, BrowserUnavailableException, EjsService, EngineNotAvailableException, EtaService, HandlebarsService, LiquidService, MjmlService, MustacheService, NestjsPdfErrorCode, NestjsPdfException, NestjsPdfModule, NestjsPdfService, NunjucksService, PdfGenerationException, PugService, PuppeteerModule, PuppeteerService, RendererConfigurationException, SignatureDependencyException, SignaturePlacementException, TemplateConfigurationException, TemplateRenderException, WatermarkException, getRelativePathToValue };
|
|
1792
2293
|
|
|
1793
2294
|
//# sourceMappingURL=index.mjs.map
|