@shad0wz7/nestjs-pdf 4.0.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 +96 -5
- package/dist/index.cjs +519 -176
- package/dist/index.d.cts +142 -88
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +142 -88
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +509 -167
- package/dist/index.mjs.map +1 -1
- package/package.json +35 -25
package/dist/index.mjs
CHANGED
|
@@ -3,13 +3,11 @@ import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep }
|
|
|
3
3
|
import { Inject, Injectable, Logger, Module, Optional } from "@nestjs/common";
|
|
4
4
|
import { PDFArray, PDFDict, PDFDocument, PDFName, PDFNumber, PDFString, StandardFonts, degrees, rgb } from "pdf-lib";
|
|
5
5
|
import { deepmerge } from "deepmerge-ts";
|
|
6
|
-
import { lookup } from "node:dns/promises";
|
|
7
6
|
import { existsSync, promises, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { lookup } from "node:dns/promises";
|
|
8
8
|
import { BlockList, isIP } from "node:net";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
|
-
|
|
11
|
-
import { Browser as Browser$1, BrowserPlatform, canDownload, detectBrowserPlatform, getInstalledBrowsers, install, resolveBuildId } from "@puppeteer/browsers";
|
|
12
|
-
//#region src/exceptions/nestjs-pdf.exception.ts
|
|
10
|
+
// src/exceptions/nestjs-pdf.exception.ts
|
|
13
11
|
let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
|
|
14
12
|
NestjsPdfErrorCode["ENGINE_NOT_AVAILABLE"] = "ENGINE_NOT_AVAILABLE";
|
|
15
13
|
NestjsPdfErrorCode["TEMPLATE_CONFIGURATION_ERROR"] = "TEMPLATE_CONFIGURATION_ERROR";
|
|
@@ -20,6 +18,7 @@ let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
|
|
|
20
18
|
NestjsPdfErrorCode["SIGNATURE_DEPENDENCY_ERROR"] = "SIGNATURE_DEPENDENCY_ERROR";
|
|
21
19
|
NestjsPdfErrorCode["SIGNATURE_PLACEMENT_ERROR"] = "SIGNATURE_PLACEMENT_ERROR";
|
|
22
20
|
NestjsPdfErrorCode["WATERMARK_ERROR"] = "WATERMARK_ERROR";
|
|
21
|
+
NestjsPdfErrorCode["RENDERER_CONFIGURATION_ERROR"] = "RENDERER_CONFIGURATION_ERROR";
|
|
23
22
|
return NestjsPdfErrorCode;
|
|
24
23
|
}({});
|
|
25
24
|
var NestjsPdfException = class extends Error {
|
|
@@ -28,46 +27,43 @@ var NestjsPdfException = class extends Error {
|
|
|
28
27
|
this.name = this.constructor.name;
|
|
29
28
|
}
|
|
30
29
|
};
|
|
31
|
-
|
|
32
|
-
//#region src/exceptions/browser-installation.exception.ts
|
|
30
|
+
// src/exceptions/browser-installation.exception.ts
|
|
33
31
|
var BrowserInstallationException = class extends NestjsPdfException {
|
|
34
32
|
code = "BROWSER_INSTALLATION_ERROR";
|
|
35
33
|
};
|
|
36
|
-
|
|
37
|
-
//#region src/exceptions/browser-unavailable.exception.ts
|
|
34
|
+
// src/exceptions/browser-unavailable.exception.ts
|
|
38
35
|
var BrowserUnavailableException = class extends NestjsPdfException {
|
|
39
36
|
code = "BROWSER_UNAVAILABLE";
|
|
40
37
|
};
|
|
41
|
-
|
|
42
|
-
//#region src/exceptions/engine-not-available.exception.ts
|
|
38
|
+
// src/exceptions/engine-not-available.exception.ts
|
|
43
39
|
var EngineNotAvailableException = class extends NestjsPdfException {
|
|
44
40
|
code = "ENGINE_NOT_AVAILABLE";
|
|
45
41
|
constructor(engineName, packageName, options) {
|
|
46
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);
|
|
47
43
|
}
|
|
48
44
|
};
|
|
49
|
-
|
|
50
|
-
//#region src/exceptions/pdf-generation.exception.ts
|
|
45
|
+
// src/exceptions/pdf-generation.exception.ts
|
|
51
46
|
var PdfGenerationException = class extends NestjsPdfException {
|
|
52
47
|
code = "PDF_GENERATION_ERROR";
|
|
53
48
|
};
|
|
54
|
-
|
|
55
|
-
|
|
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
|
|
56
55
|
var SignatureDependencyException = class extends NestjsPdfException {
|
|
57
56
|
code = "SIGNATURE_DEPENDENCY_ERROR";
|
|
58
57
|
};
|
|
59
|
-
|
|
60
|
-
//#region src/exceptions/signature-placement.exception.ts
|
|
58
|
+
// src/exceptions/signature-placement.exception.ts
|
|
61
59
|
var SignaturePlacementException = class extends NestjsPdfException {
|
|
62
60
|
code = "SIGNATURE_PLACEMENT_ERROR";
|
|
63
61
|
};
|
|
64
|
-
|
|
65
|
-
//#region src/exceptions/template-configuration.exception.ts
|
|
62
|
+
// src/exceptions/template-configuration.exception.ts
|
|
66
63
|
var TemplateConfigurationException = class extends NestjsPdfException {
|
|
67
64
|
code = "TEMPLATE_CONFIGURATION_ERROR";
|
|
68
65
|
};
|
|
69
|
-
|
|
70
|
-
//#region src/exceptions/template-render.exception.ts
|
|
66
|
+
// src/exceptions/template-render.exception.ts
|
|
71
67
|
var TemplateRenderException = class extends NestjsPdfException {
|
|
72
68
|
engine;
|
|
73
69
|
code = "TEMPLATE_RENDER_ERROR";
|
|
@@ -76,13 +72,11 @@ var TemplateRenderException = class extends NestjsPdfException {
|
|
|
76
72
|
this.engine = engine;
|
|
77
73
|
}
|
|
78
74
|
};
|
|
79
|
-
|
|
80
|
-
//#region src/exceptions/watermark.exception.ts
|
|
75
|
+
// src/exceptions/watermark.exception.ts
|
|
81
76
|
var WatermarkException = class extends NestjsPdfException {
|
|
82
77
|
code = "WATERMARK_ERROR";
|
|
83
78
|
};
|
|
84
|
-
|
|
85
|
-
//#region src/helpers/getRelativePath.helper.ts
|
|
79
|
+
// src/helpers/getRelativePath.helper.ts
|
|
86
80
|
/**
|
|
87
81
|
* Get the relative path to a value from the module directory.
|
|
88
82
|
* @param moduleDir the path of the module, typically __dirname
|
|
@@ -96,8 +90,7 @@ function getRelativePathToValue(moduleDir, relativeToModule) {
|
|
|
96
90
|
const fullTemplatePath = resolve(moduleDir, relativeToModule);
|
|
97
91
|
return relative(process.cwd(), fullTemplatePath);
|
|
98
92
|
}
|
|
99
|
-
|
|
100
|
-
//#region src/helpers/signature.helper.ts
|
|
93
|
+
// src/helpers/signature.helper.ts
|
|
101
94
|
let pdfjsPromise;
|
|
102
95
|
async function loadPdfjs() {
|
|
103
96
|
if (!pdfjsPromise) try {
|
|
@@ -240,8 +233,7 @@ async function addSignatureFieldUsingAnchor(pdf, fieldName = "SignatureDebtor",
|
|
|
240
233
|
}
|
|
241
234
|
return await pdfDoc.save();
|
|
242
235
|
}
|
|
243
|
-
|
|
244
|
-
//#region src/helpers/watermark.helper.ts
|
|
236
|
+
// src/helpers/watermark.helper.ts
|
|
245
237
|
const DEFAULT_OPACITY = .15;
|
|
246
238
|
const DEFAULT_ROTATION = 45;
|
|
247
239
|
const DEFAULT_FONT_SIZE = 60;
|
|
@@ -384,8 +376,7 @@ async function addWatermark(pdf, options) {
|
|
|
384
376
|
throw new WatermarkException(`Failed to add watermark: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
385
377
|
}
|
|
386
378
|
}
|
|
387
|
-
|
|
388
|
-
//#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
|
|
389
380
|
var Node = class {
|
|
390
381
|
value;
|
|
391
382
|
next;
|
|
@@ -442,8 +433,7 @@ var Queue = class {
|
|
|
442
433
|
while (this.#head) yield this.dequeue();
|
|
443
434
|
}
|
|
444
435
|
};
|
|
445
|
-
|
|
446
|
-
//#region node_modules/.pnpm/p-limit@7.3.3/node_modules/p-limit/index.js
|
|
436
|
+
// node_modules/.pnpm/p-limit@7.3.3/node_modules/p-limit/index.js
|
|
447
437
|
function pLimit(concurrency) {
|
|
448
438
|
let rejectOnClear = false;
|
|
449
439
|
if (typeof concurrency === "object") ({concurrency, rejectOnClear = false} = concurrency);
|
|
@@ -521,14 +511,296 @@ function pLimit(concurrency) {
|
|
|
521
511
|
function validateConcurrency(concurrency) {
|
|
522
512
|
if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
|
|
523
513
|
}
|
|
524
|
-
|
|
525
|
-
//#region src/helpers/deepMergePdfparams.ts
|
|
514
|
+
// src/helpers/deepMergePdfparams.ts
|
|
526
515
|
function mergePuppeteerParameters(defaults, overrides) {
|
|
527
516
|
if (!overrides) return { ...defaults };
|
|
528
517
|
return deepmerge(defaults, overrides);
|
|
529
518
|
}
|
|
530
|
-
|
|
531
|
-
|
|
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
|
|
532
804
|
const blockedRanges = new BlockList();
|
|
533
805
|
for (const [address, prefix] of [
|
|
534
806
|
["0.0.0.0", 8],
|
|
@@ -656,6 +928,7 @@ function describe(rawUrl) {
|
|
|
656
928
|
* and closes the pop-ups a script could open to escape the filter.
|
|
657
929
|
*/
|
|
658
930
|
async function installRequestGuard(context, page, options) {
|
|
931
|
+
const { TargetType } = await loadPuppeteer();
|
|
659
932
|
context.on("targetcreated", (target) => {
|
|
660
933
|
if (target.type() === TargetType.PAGE && target.opener()) target.page().then((popup) => popup?.close()).catch(() => void 0);
|
|
661
934
|
});
|
|
@@ -675,31 +948,162 @@ async function installRequestGuard(context, page, options) {
|
|
|
675
948
|
})().catch(() => void 0);
|
|
676
949
|
});
|
|
677
950
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
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
|
|
683
1089
|
function __decorateMetadata(k, v) {
|
|
684
1090
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
685
1091
|
}
|
|
686
|
-
|
|
687
|
-
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateParam.js
|
|
1092
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/decorateParam.js
|
|
688
1093
|
function __decorateParam(paramIndex, decorator) {
|
|
689
1094
|
return function(target, key) {
|
|
690
1095
|
decorator(target, key, paramIndex);
|
|
691
1096
|
};
|
|
692
1097
|
}
|
|
693
|
-
|
|
694
|
-
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorate.js
|
|
1098
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/decorate.js
|
|
695
1099
|
function __decorate(decorators, target, key, desc) {
|
|
696
1100
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
697
1101
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
698
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;
|
|
699
1103
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
700
1104
|
}
|
|
701
|
-
|
|
702
|
-
|
|
1105
|
+
// src/puppeteer/browser/browser.service.ts
|
|
1106
|
+
const DEFAULT_BROWSER = "chromium";
|
|
703
1107
|
async function sleep(ms) {
|
|
704
1108
|
await new Promise((r) => setTimeout(r, ms));
|
|
705
1109
|
}
|
|
@@ -751,7 +1155,7 @@ let BrowserService = class BrowserService {
|
|
|
751
1155
|
} catch (error) {
|
|
752
1156
|
Logger.warn(`Failed to close browser on module destroy: ${error instanceof Error ? error.message : String(error)}`);
|
|
753
1157
|
}
|
|
754
|
-
if (this.#options
|
|
1158
|
+
if (this.#options !== void 0 && usesPuppeteer(this.#options) && this.#options.cleanupBrowserCacheOnExit !== false) await this.#cleanupCacheBestEffort();
|
|
755
1159
|
}
|
|
756
1160
|
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
757
1161
|
async #waitForIdle(timeoutMs) {
|
|
@@ -833,7 +1237,8 @@ let BrowserService = class BrowserService {
|
|
|
833
1237
|
}
|
|
834
1238
|
}
|
|
835
1239
|
async #doInstall(lock) {
|
|
836
|
-
const
|
|
1240
|
+
const { Browser: BrowserEnum, BrowserPlatform, canDownload, detectBrowserPlatform, install, resolveBuildId } = await loadPuppeteerBrowsers();
|
|
1241
|
+
const browser = toEnumMember(BrowserEnum, this.#browser, "browser");
|
|
837
1242
|
const versionTag = this.#browserTag;
|
|
838
1243
|
const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
|
|
839
1244
|
let buildId;
|
|
@@ -865,10 +1270,7 @@ let BrowserService = class BrowserService {
|
|
|
865
1270
|
return null;
|
|
866
1271
|
}
|
|
867
1272
|
#loadBrowser() {
|
|
868
|
-
|
|
869
|
-
if (this.#options?.browser === void 0) browser = Browser$1.CHROMIUM;
|
|
870
|
-
else browser = this.#options.browser;
|
|
871
|
-
this.#browser = browser;
|
|
1273
|
+
this.#browser = this.#options?.browser ?? DEFAULT_BROWSER;
|
|
872
1274
|
}
|
|
873
1275
|
getBrowser() {
|
|
874
1276
|
return this.#browser;
|
|
@@ -876,7 +1278,7 @@ let BrowserService = class BrowserService {
|
|
|
876
1278
|
#loadBrowserTag() {
|
|
877
1279
|
let versionTag;
|
|
878
1280
|
if (this.#options?.browserTag === void 0) {
|
|
879
|
-
if (this.#browser ===
|
|
1281
|
+
if (this.#browser === DEFAULT_BROWSER) versionTag = "latest";
|
|
880
1282
|
else versionTag = "stable";
|
|
881
1283
|
} else versionTag = this.#options.browserTag;
|
|
882
1284
|
this.#browserTag = versionTag;
|
|
@@ -903,12 +1305,15 @@ let BrowserService = class BrowserService {
|
|
|
903
1305
|
this.#useLockedBrowser = useLockedBrowser;
|
|
904
1306
|
}
|
|
905
1307
|
async hasBrowserInstalled(browser, buildId) {
|
|
1308
|
+
const { Browser: BrowserEnum, getInstalledBrowsers } = await loadPuppeteerBrowsers();
|
|
1309
|
+
const expected = toEnumMember(BrowserEnum, browser, "browser");
|
|
906
1310
|
return (await getInstalledBrowsers({ cacheDir: this.#cacheDir })).find((insBrowser) => {
|
|
907
|
-
return insBrowser.browser ===
|
|
1311
|
+
return insBrowser.browser === expected && insBrowser.buildId === buildId;
|
|
908
1312
|
}) !== void 0;
|
|
909
1313
|
}
|
|
910
1314
|
async getExecutablePath() {
|
|
911
|
-
const
|
|
1315
|
+
const { Browser: BrowserEnum, BrowserPlatform, detectBrowserPlatform, getInstalledBrowsers, resolveBuildId } = await loadPuppeteerBrowsers();
|
|
1316
|
+
const browser = toEnumMember(BrowserEnum, this.#browser, "browser");
|
|
912
1317
|
const versionTag = this.#browserTag;
|
|
913
1318
|
const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
|
|
914
1319
|
let buildId = null;
|
|
@@ -929,6 +1334,7 @@ let BrowserService = class BrowserService {
|
|
|
929
1334
|
}
|
|
930
1335
|
async #launchBrowser(args, headless, executablePathBin) {
|
|
931
1336
|
const executablePath = executablePathBin ?? await this.getExecutablePath();
|
|
1337
|
+
const { launch } = await loadPuppeteer();
|
|
932
1338
|
const browser = await launch({
|
|
933
1339
|
executablePath,
|
|
934
1340
|
headless,
|
|
@@ -965,8 +1371,7 @@ BrowserService = __decorate([
|
|
|
965
1371
|
__decorateParam(0, Inject("PDF_PARAMETERS")),
|
|
966
1372
|
__decorateMetadata("design:paramtypes", [Object])
|
|
967
1373
|
], BrowserService);
|
|
968
|
-
|
|
969
|
-
//#region src/puppeteer/libs/loadEngine.utils.ts
|
|
1374
|
+
// src/puppeteer/libs/loadEngine.utils.ts
|
|
970
1375
|
const requireEngine = createRequire(import.meta.url);
|
|
971
1376
|
/**
|
|
972
1377
|
* Load an optional template engine on first use, so the library can be imported
|
|
@@ -983,8 +1388,7 @@ function loadEngine(packageName, engineName) {
|
|
|
983
1388
|
}
|
|
984
1389
|
return mod.__esModule && "default" in mod ? mod.default : mod;
|
|
985
1390
|
}
|
|
986
|
-
|
|
987
|
-
//#region src/puppeteer/engines/ejs/ejs.service.ts
|
|
1391
|
+
// src/puppeteer/engines/ejs/ejs.service.ts
|
|
988
1392
|
let EjsService = class EjsService {
|
|
989
1393
|
#ejs;
|
|
990
1394
|
get #engine() {
|
|
@@ -1014,8 +1418,7 @@ let EjsService = class EjsService {
|
|
|
1014
1418
|
}
|
|
1015
1419
|
};
|
|
1016
1420
|
EjsService = __decorate([Injectable()], EjsService);
|
|
1017
|
-
|
|
1018
|
-
//#region src/puppeteer/engines/eta/eta.service.ts
|
|
1421
|
+
// src/puppeteer/engines/eta/eta.service.ts
|
|
1019
1422
|
let EtaService = class EtaService {
|
|
1020
1423
|
#etaModule;
|
|
1021
1424
|
#eta;
|
|
@@ -1086,8 +1489,7 @@ let EtaService = class EtaService {
|
|
|
1086
1489
|
}
|
|
1087
1490
|
};
|
|
1088
1491
|
EtaService = __decorate([Injectable()], EtaService);
|
|
1089
|
-
|
|
1090
|
-
//#region src/puppeteer/engines/handlebars/handlebars.service.ts
|
|
1492
|
+
// src/puppeteer/engines/handlebars/handlebars.service.ts
|
|
1091
1493
|
let HandlebarsService = class HandlebarsService {
|
|
1092
1494
|
#handlebars;
|
|
1093
1495
|
#cachedOptions;
|
|
@@ -1142,8 +1544,7 @@ let HandlebarsService = class HandlebarsService {
|
|
|
1142
1544
|
}
|
|
1143
1545
|
};
|
|
1144
1546
|
HandlebarsService = __decorate([Injectable()], HandlebarsService);
|
|
1145
|
-
|
|
1146
|
-
//#region src/puppeteer/engines/liquid/liquid.service.ts
|
|
1547
|
+
// src/puppeteer/engines/liquid/liquid.service.ts
|
|
1147
1548
|
let LiquidService = class LiquidService {
|
|
1148
1549
|
#liquidModule;
|
|
1149
1550
|
#liquid;
|
|
@@ -1204,8 +1605,7 @@ let LiquidService = class LiquidService {
|
|
|
1204
1605
|
}
|
|
1205
1606
|
};
|
|
1206
1607
|
LiquidService = __decorate([Injectable()], LiquidService);
|
|
1207
|
-
|
|
1208
|
-
//#region src/puppeteer/engines/mjml/mjml.service.ts
|
|
1608
|
+
// src/puppeteer/engines/mjml/mjml.service.ts
|
|
1209
1609
|
let MjmlService = class MjmlService {
|
|
1210
1610
|
#mjml;
|
|
1211
1611
|
get #engine() {
|
|
@@ -1231,8 +1631,7 @@ let MjmlService = class MjmlService {
|
|
|
1231
1631
|
}
|
|
1232
1632
|
};
|
|
1233
1633
|
MjmlService = __decorate([Injectable()], MjmlService);
|
|
1234
|
-
|
|
1235
|
-
//#region src/puppeteer/engines/mustache/mustache.service.ts
|
|
1634
|
+
// src/puppeteer/engines/mustache/mustache.service.ts
|
|
1236
1635
|
let MustacheService = class MustacheService {
|
|
1237
1636
|
#mustache;
|
|
1238
1637
|
#templateCache = /* @__PURE__ */ new Map();
|
|
@@ -1295,8 +1694,7 @@ let MustacheService = class MustacheService {
|
|
|
1295
1694
|
}
|
|
1296
1695
|
};
|
|
1297
1696
|
MustacheService = __decorate([Injectable()], MustacheService);
|
|
1298
|
-
|
|
1299
|
-
//#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
1697
|
+
// src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
1300
1698
|
let NunjucksService = class NunjucksService {
|
|
1301
1699
|
#nunjucks;
|
|
1302
1700
|
get #engine() {
|
|
@@ -1348,8 +1746,7 @@ let NunjucksService = class NunjucksService {
|
|
|
1348
1746
|
}
|
|
1349
1747
|
};
|
|
1350
1748
|
NunjucksService = __decorate([Injectable()], NunjucksService);
|
|
1351
|
-
|
|
1352
|
-
//#region src/puppeteer/engines/pug/pug.service.ts
|
|
1749
|
+
// src/puppeteer/engines/pug/pug.service.ts
|
|
1353
1750
|
let PugService = class PugService {
|
|
1354
1751
|
#pug;
|
|
1355
1752
|
get #engine() {
|
|
@@ -1374,16 +1771,15 @@ let PugService = class PugService {
|
|
|
1374
1771
|
}
|
|
1375
1772
|
};
|
|
1376
1773
|
PugService = __decorate([Injectable()], PugService);
|
|
1377
|
-
|
|
1378
|
-
//#region src/puppeteer/libs/requireService.utils.ts
|
|
1774
|
+
// src/puppeteer/libs/requireService.utils.ts
|
|
1379
1775
|
function requireService(service, name) {
|
|
1380
1776
|
if (!service) throw new EngineNotAvailableException(name);
|
|
1381
1777
|
return service;
|
|
1382
1778
|
}
|
|
1383
|
-
|
|
1384
|
-
//#region src/puppeteer/puppeteer.service.ts
|
|
1779
|
+
// src/puppeteer/puppeteer.service.ts
|
|
1385
1780
|
let PuppeteerService = class PuppeteerService {
|
|
1386
|
-
#
|
|
1781
|
+
#renderer;
|
|
1782
|
+
#jobs;
|
|
1387
1783
|
#options;
|
|
1388
1784
|
#hbsService;
|
|
1389
1785
|
#mjmlService;
|
|
@@ -1393,8 +1789,9 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1393
1789
|
#etaService;
|
|
1394
1790
|
#mustacheService;
|
|
1395
1791
|
#liquidService;
|
|
1396
|
-
constructor(
|
|
1397
|
-
this.#
|
|
1792
|
+
constructor(renderer, jobs, options, hbsService, mjmlService, pugService, ejsService, nunjucksService, etaService, mustacheService, liquidService) {
|
|
1793
|
+
this.#renderer = renderer;
|
|
1794
|
+
this.#jobs = jobs;
|
|
1398
1795
|
this.#options = options;
|
|
1399
1796
|
this.#hbsService = hbsService;
|
|
1400
1797
|
this.#mjmlService = mjmlService;
|
|
@@ -1413,87 +1810,19 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1413
1810
|
const job = this.#limit(async () => {
|
|
1414
1811
|
signal?.throwIfAborted();
|
|
1415
1812
|
started = true;
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1418
|
-
const headless = mergePuppeteerOptions.headless ?? true;
|
|
1419
|
-
const executablePath = mergePuppeteerOptions.executablePath || void 0;
|
|
1420
|
-
const args = mergePuppeteerOptions.extraPuppeteerArgs || [
|
|
1421
|
-
"--autoplay-policy=user-gesture-required",
|
|
1422
|
-
"--disable-background-networking",
|
|
1423
|
-
"--disable-background-timer-throttling",
|
|
1424
|
-
"--disable-backgrounding-occluded-windows",
|
|
1425
|
-
"--disable-breakpad",
|
|
1426
|
-
"--disable-client-side-phishing-detection",
|
|
1427
|
-
"--disable-component-update",
|
|
1428
|
-
"--disable-default-apps",
|
|
1429
|
-
"--disable-dev-shm-usage",
|
|
1430
|
-
"--disable-domain-reliability",
|
|
1431
|
-
"--disable-extensions",
|
|
1432
|
-
"--disable-features=AudioServiceOutOfProcess",
|
|
1433
|
-
"--disable-hang-monitor",
|
|
1434
|
-
"--disable-ipc-flooding-protection",
|
|
1435
|
-
"--disable-notifications",
|
|
1436
|
-
"--disable-offer-store-unmasked-wallet-cards",
|
|
1437
|
-
"--disable-print-preview",
|
|
1438
|
-
"--disable-prompt-on-repost",
|
|
1439
|
-
"--disable-renderer-backgrounding",
|
|
1440
|
-
"--disable-setuid-sandbox",
|
|
1441
|
-
"--disable-speech-api",
|
|
1442
|
-
"--disable-sync",
|
|
1443
|
-
"--hide-scrollbars",
|
|
1444
|
-
"--ignore-gpu-blacklist",
|
|
1445
|
-
"--metrics-recording-only",
|
|
1446
|
-
"--mute-audio",
|
|
1447
|
-
"--no-default-browser-check",
|
|
1448
|
-
"--no-first-run",
|
|
1449
|
-
"--no-pings",
|
|
1450
|
-
"--password-store=basic",
|
|
1451
|
-
"--use-gl=swiftshader",
|
|
1452
|
-
"--use-mock-keychain",
|
|
1453
|
-
"--disable-accelerated-2d-canvas",
|
|
1454
|
-
"--no-zygote",
|
|
1455
|
-
"--disable-gpu"
|
|
1456
|
-
];
|
|
1457
|
-
this.#browserService.markJobStarted();
|
|
1458
|
-
let context = null;
|
|
1459
|
-
let closing;
|
|
1460
|
-
const onAbort = () => {
|
|
1461
|
-
if (!context) return;
|
|
1462
|
-
closing = context.close();
|
|
1463
|
-
closing.catch(() => void 0);
|
|
1464
|
-
};
|
|
1465
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1813
|
+
const mergedOptions = mergePuppeteerParameters(this.#options, options);
|
|
1814
|
+
this.#jobs.markJobStarted();
|
|
1466
1815
|
try {
|
|
1467
|
-
|
|
1468
|
-
signal?.throwIfAborted();
|
|
1469
|
-
const page = await context.newPage();
|
|
1470
|
-
if (mergePuppeteerOptions.security) await installRequestGuard(context, page, mergePuppeteerOptions.security);
|
|
1471
|
-
const pdfOptions = mergePuppeteerOptions.pdfOptions ?? { format: "A4" };
|
|
1472
|
-
await page.setContent(html, { waitUntil: "domcontentloaded" });
|
|
1473
|
-
await page.emulateMediaType("screen");
|
|
1474
|
-
await page.waitForNetworkIdle({
|
|
1475
|
-
idleTime: 500,
|
|
1476
|
-
timeout: 3e4
|
|
1477
|
-
});
|
|
1478
|
-
/* v8 ignore next */
|
|
1479
|
-
await page.evaluate(() => document.fonts.ready);
|
|
1480
|
-
const pdf = await page.pdf(pdfOptions);
|
|
1816
|
+
const pdf = await this.#renderer.render(html, mergedOptions, signal);
|
|
1481
1817
|
signal?.throwIfAborted();
|
|
1482
|
-
return
|
|
1818
|
+
return mergedOptions.watermark ? await addWatermark(pdf, mergedOptions.watermark) : pdf;
|
|
1483
1819
|
} catch (e) {
|
|
1484
1820
|
if (signal?.aborted) throw signal.reason;
|
|
1485
1821
|
Logger.error(e);
|
|
1486
1822
|
if (e instanceof NestjsPdfException) throw e;
|
|
1487
1823
|
throw new PdfGenerationException(`PDF generation failed: ${String(e)}`, { cause: e });
|
|
1488
1824
|
} finally {
|
|
1489
|
-
|
|
1490
|
-
if (context) try {
|
|
1491
|
-
if (closing) await closing;
|
|
1492
|
-
else await context.close();
|
|
1493
|
-
} catch (error) {
|
|
1494
|
-
Logger.error(error);
|
|
1495
|
-
}
|
|
1496
|
-
await this.#browserService.markJobFinished();
|
|
1825
|
+
await this.#jobs.markJobFinished();
|
|
1497
1826
|
}
|
|
1498
1827
|
});
|
|
1499
1828
|
if (!signal) return job;
|
|
@@ -1577,8 +1906,9 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1577
1906
|
};
|
|
1578
1907
|
PuppeteerService = __decorate([
|
|
1579
1908
|
Injectable(),
|
|
1580
|
-
__decorateParam(
|
|
1581
|
-
__decorateParam(
|
|
1909
|
+
__decorateParam(0, Inject(PDF_RENDERER)),
|
|
1910
|
+
__decorateParam(1, Inject(BrowserService)),
|
|
1911
|
+
__decorateParam(2, Inject(PDF_PARAMETERS)),
|
|
1582
1912
|
__decorateParam(3, Optional()),
|
|
1583
1913
|
__decorateParam(4, Optional()),
|
|
1584
1914
|
__decorateParam(5, Optional()),
|
|
@@ -1586,8 +1916,10 @@ PuppeteerService = __decorate([
|
|
|
1586
1916
|
__decorateParam(7, Optional()),
|
|
1587
1917
|
__decorateParam(8, Optional()),
|
|
1588
1918
|
__decorateParam(9, Optional()),
|
|
1919
|
+
__decorateParam(10, Optional()),
|
|
1589
1920
|
__decorateMetadata("design:paramtypes", [
|
|
1590
|
-
|
|
1921
|
+
Object,
|
|
1922
|
+
Object,
|
|
1591
1923
|
Object,
|
|
1592
1924
|
typeof HandlebarsService === "undefined" ? Object : HandlebarsService,
|
|
1593
1925
|
typeof MjmlService === "undefined" ? Object : MjmlService,
|
|
@@ -1599,8 +1931,7 @@ PuppeteerService = __decorate([
|
|
|
1599
1931
|
typeof LiquidService === "undefined" ? Object : LiquidService
|
|
1600
1932
|
])
|
|
1601
1933
|
], PuppeteerService);
|
|
1602
|
-
|
|
1603
|
-
//#region src/nestjs-pdf.service.ts
|
|
1934
|
+
// src/nestjs-pdf.service.ts
|
|
1604
1935
|
let NestjsPdfService = class NestjsPdfService {
|
|
1605
1936
|
#puppeteerService;
|
|
1606
1937
|
constructor(puppeteerService) {
|
|
@@ -1820,9 +2151,14 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1820
2151
|
}
|
|
1821
2152
|
};
|
|
1822
2153
|
NestjsPdfService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof PuppeteerService === "undefined" ? Object : PuppeteerService])], NestjsPdfService);
|
|
1823
|
-
|
|
1824
|
-
//#region src/puppeteer/puppeteer.module.ts
|
|
2154
|
+
// src/puppeteer/puppeteer.module.ts
|
|
1825
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
|
+
};
|
|
1826
2162
|
let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
1827
2163
|
#browserService;
|
|
1828
2164
|
#pdfParams;
|
|
@@ -1831,7 +2167,12 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1831
2167
|
this.#pdfParams = pdfParams;
|
|
1832
2168
|
}
|
|
1833
2169
|
async onModuleInit() {
|
|
1834
|
-
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
|
+
}
|
|
1835
2176
|
}
|
|
1836
2177
|
static forRoot(pdfParameters) {
|
|
1837
2178
|
return {
|
|
@@ -1875,6 +2216,7 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1875
2216
|
pdfParamsProvider,
|
|
1876
2217
|
PuppeteerService,
|
|
1877
2218
|
BrowserService,
|
|
2219
|
+
pdfRendererProvider,
|
|
1878
2220
|
HandlebarsService,
|
|
1879
2221
|
MjmlService,
|
|
1880
2222
|
PugService,
|
|
@@ -1902,6 +2244,7 @@ PuppeteerModule = _PuppeteerModule = __decorate([
|
|
|
1902
2244
|
providers: [
|
|
1903
2245
|
PuppeteerService,
|
|
1904
2246
|
BrowserService,
|
|
2247
|
+
pdfRendererProvider,
|
|
1905
2248
|
MjmlService,
|
|
1906
2249
|
PugService,
|
|
1907
2250
|
EjsService,
|
|
@@ -1921,11 +2264,11 @@ PuppeteerModule = _PuppeteerModule = __decorate([
|
|
|
1921
2264
|
LiquidService
|
|
1922
2265
|
]
|
|
1923
2266
|
}),
|
|
2267
|
+
__decorateParam(0, Inject(BrowserService)),
|
|
1924
2268
|
__decorateParam(1, Inject(PDF_PARAMETERS)),
|
|
1925
|
-
__decorateMetadata("design:paramtypes", [
|
|
2269
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
1926
2270
|
], PuppeteerModule);
|
|
1927
|
-
|
|
1928
|
-
//#region src/nestjs-pdf.module.ts
|
|
2271
|
+
// src/nestjs-pdf.module.ts
|
|
1929
2272
|
var _NestjsPdfModule;
|
|
1930
2273
|
let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
|
|
1931
2274
|
static forRoot(options) {
|
|
@@ -1946,7 +2289,6 @@ let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
|
|
|
1946
2289
|
}
|
|
1947
2290
|
};
|
|
1948
2291
|
NestjsPdfModule = _NestjsPdfModule = __decorate([Module({})], NestjsPdfModule);
|
|
1949
|
-
|
|
1950
|
-
export { BrowserInstallationException, BrowserUnavailableException, EjsService, EngineNotAvailableException, EtaService, HandlebarsService, LiquidService, 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 };
|
|
1951
2293
|
|
|
1952
2294
|
//# sourceMappingURL=index.mjs.map
|