@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/dist/index.cjs CHANGED
@@ -3,14 +3,12 @@ let node_path = require("node:path");
3
3
  let _nestjs_common = require("@nestjs/common");
4
4
  let pdf_lib = require("pdf-lib");
5
5
  let deepmerge_ts = require("deepmerge-ts");
6
- let node_dns_promises = require("node:dns/promises");
7
6
  let node_fs = require("node:fs");
7
+ let node_dns_promises = require("node:dns/promises");
8
8
  let node_net = require("node:net");
9
9
  let node_url = require("node:url");
10
- let puppeteer = require("puppeteer");
11
- let _puppeteer_browsers = require("@puppeteer/browsers");
12
10
  let node_module = require("node:module");
13
- //#region src/exceptions/nestjs-pdf.exception.ts
11
+ // src/exceptions/nestjs-pdf.exception.ts
14
12
  let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
15
13
  NestjsPdfErrorCode["ENGINE_NOT_AVAILABLE"] = "ENGINE_NOT_AVAILABLE";
16
14
  NestjsPdfErrorCode["TEMPLATE_CONFIGURATION_ERROR"] = "TEMPLATE_CONFIGURATION_ERROR";
@@ -21,6 +19,7 @@ let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
21
19
  NestjsPdfErrorCode["SIGNATURE_DEPENDENCY_ERROR"] = "SIGNATURE_DEPENDENCY_ERROR";
22
20
  NestjsPdfErrorCode["SIGNATURE_PLACEMENT_ERROR"] = "SIGNATURE_PLACEMENT_ERROR";
23
21
  NestjsPdfErrorCode["WATERMARK_ERROR"] = "WATERMARK_ERROR";
22
+ NestjsPdfErrorCode["RENDERER_CONFIGURATION_ERROR"] = "RENDERER_CONFIGURATION_ERROR";
24
23
  return NestjsPdfErrorCode;
25
24
  }({});
26
25
  var NestjsPdfException = class extends Error {
@@ -29,46 +28,43 @@ var NestjsPdfException = class extends Error {
29
28
  this.name = this.constructor.name;
30
29
  }
31
30
  };
32
- //#endregion
33
- //#region src/exceptions/browser-installation.exception.ts
31
+ // src/exceptions/browser-installation.exception.ts
34
32
  var BrowserInstallationException = class extends NestjsPdfException {
35
33
  code = "BROWSER_INSTALLATION_ERROR";
36
34
  };
37
- //#endregion
38
- //#region src/exceptions/browser-unavailable.exception.ts
35
+ // src/exceptions/browser-unavailable.exception.ts
39
36
  var BrowserUnavailableException = class extends NestjsPdfException {
40
37
  code = "BROWSER_UNAVAILABLE";
41
38
  };
42
- //#endregion
43
- //#region src/exceptions/engine-not-available.exception.ts
39
+ // src/exceptions/engine-not-available.exception.ts
44
40
  var EngineNotAvailableException = class extends NestjsPdfException {
45
41
  code = "ENGINE_NOT_AVAILABLE";
46
42
  constructor(engineName, packageName, options) {
47
43
  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);
48
44
  }
49
45
  };
50
- //#endregion
51
- //#region src/exceptions/pdf-generation.exception.ts
46
+ // src/exceptions/pdf-generation.exception.ts
52
47
  var PdfGenerationException = class extends NestjsPdfException {
53
48
  code = "PDF_GENERATION_ERROR";
54
49
  };
55
- //#endregion
56
- //#region src/exceptions/signature-dependency.exception.ts
50
+ // src/exceptions/renderer-configuration.exception.ts
51
+ /** The PDF provider is misconfigured, or asked for an option it does not support. */
52
+ var RendererConfigurationException = class extends NestjsPdfException {
53
+ code = "RENDERER_CONFIGURATION_ERROR";
54
+ };
55
+ // src/exceptions/signature-dependency.exception.ts
57
56
  var SignatureDependencyException = class extends NestjsPdfException {
58
57
  code = "SIGNATURE_DEPENDENCY_ERROR";
59
58
  };
60
- //#endregion
61
- //#region src/exceptions/signature-placement.exception.ts
59
+ // src/exceptions/signature-placement.exception.ts
62
60
  var SignaturePlacementException = class extends NestjsPdfException {
63
61
  code = "SIGNATURE_PLACEMENT_ERROR";
64
62
  };
65
- //#endregion
66
- //#region src/exceptions/template-configuration.exception.ts
63
+ // src/exceptions/template-configuration.exception.ts
67
64
  var TemplateConfigurationException = class extends NestjsPdfException {
68
65
  code = "TEMPLATE_CONFIGURATION_ERROR";
69
66
  };
70
- //#endregion
71
- //#region src/exceptions/template-render.exception.ts
67
+ // src/exceptions/template-render.exception.ts
72
68
  var TemplateRenderException = class extends NestjsPdfException {
73
69
  engine;
74
70
  code = "TEMPLATE_RENDER_ERROR";
@@ -77,13 +73,11 @@ var TemplateRenderException = class extends NestjsPdfException {
77
73
  this.engine = engine;
78
74
  }
79
75
  };
80
- //#endregion
81
- //#region src/exceptions/watermark.exception.ts
76
+ // src/exceptions/watermark.exception.ts
82
77
  var WatermarkException = class extends NestjsPdfException {
83
78
  code = "WATERMARK_ERROR";
84
79
  };
85
- //#endregion
86
- //#region src/helpers/getRelativePath.helper.ts
80
+ // src/helpers/getRelativePath.helper.ts
87
81
  /**
88
82
  * Get the relative path to a value from the module directory.
89
83
  * @param moduleDir the path of the module, typically __dirname
@@ -97,8 +91,7 @@ function getRelativePathToValue(moduleDir, relativeToModule) {
97
91
  const fullTemplatePath = (0, node_path.resolve)(moduleDir, relativeToModule);
98
92
  return (0, node_path.relative)(process.cwd(), fullTemplatePath);
99
93
  }
100
- //#endregion
101
- //#region src/helpers/signature.helper.ts
94
+ // src/helpers/signature.helper.ts
102
95
  let pdfjsPromise;
103
96
  async function loadPdfjs() {
104
97
  if (!pdfjsPromise) try {
@@ -241,8 +234,7 @@ async function addSignatureFieldUsingAnchor(pdf, fieldName = "SignatureDebtor",
241
234
  }
242
235
  return await pdfDoc.save();
243
236
  }
244
- //#endregion
245
- //#region src/helpers/watermark.helper.ts
237
+ // src/helpers/watermark.helper.ts
246
238
  const DEFAULT_OPACITY = .15;
247
239
  const DEFAULT_ROTATION = 45;
248
240
  const DEFAULT_FONT_SIZE = 60;
@@ -385,8 +377,7 @@ async function addWatermark(pdf, options) {
385
377
  throw new WatermarkException(`Failed to add watermark: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
386
378
  }
387
379
  }
388
- //#endregion
389
- //#region node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
380
+ // node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
390
381
  var Node = class {
391
382
  value;
392
383
  next;
@@ -443,8 +434,7 @@ var Queue = class {
443
434
  while (this.#head) yield this.dequeue();
444
435
  }
445
436
  };
446
- //#endregion
447
- //#region node_modules/.pnpm/p-limit@7.3.3/node_modules/p-limit/index.js
437
+ // node_modules/.pnpm/p-limit@7.3.3/node_modules/p-limit/index.js
448
438
  function pLimit(concurrency) {
449
439
  let rejectOnClear = false;
450
440
  if (typeof concurrency === "object") ({concurrency, rejectOnClear = false} = concurrency);
@@ -522,14 +512,296 @@ function pLimit(concurrency) {
522
512
  function validateConcurrency(concurrency) {
523
513
  if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) throw new TypeError("Expected `concurrency` to be a number from 1 and up");
524
514
  }
525
- //#endregion
526
- //#region src/helpers/deepMergePdfparams.ts
515
+ // src/helpers/deepMergePdfparams.ts
527
516
  function mergePuppeteerParameters(defaults, overrides) {
528
517
  if (!overrides) return { ...defaults };
529
518
  return (0, deepmerge_ts.deepmerge)(defaults, overrides);
530
519
  }
531
- //#endregion
532
- //#region src/helpers/request-guard.helper.ts
520
+ // src/helpers/tokens.ts
521
+ const PDF_PARAMETERS = "PDF_PARAMETERS";
522
+ // src/renderers/pdf-renderer.interface.ts
523
+ const PDF_RENDERER = "PDF_RENDERER";
524
+ // src/renderers/http.utils.ts
525
+ const MAX_ERROR_BODY_LENGTH = 500;
526
+ /** Builds a `PdfGenerationException` from a failed HTTP response, body included. */
527
+ async function httpError(provider, response) {
528
+ let body = "";
529
+ try {
530
+ body = (await response.text()).trim().slice(0, MAX_ERROR_BODY_LENGTH);
531
+ } catch {}
532
+ return new PdfGenerationException(`${provider} responded with HTTP ${response.status}${body ? `: ${body}` : ""}`);
533
+ }
534
+ /** Remote providers render on another machine: the local request guard cannot run there. */
535
+ function assertNoRequestGuard(provider, options, hint) {
536
+ if (options.security) throw new RendererConfigurationException(`The 'security' option is only supported by the puppeteer provider, not by ${provider}. ${hint}`);
537
+ }
538
+ function requireNonEmpty(value, name, provider) {
539
+ if (!value?.trim()) throw new RendererConfigurationException(`The ${provider} provider requires a non-empty '${name}'`);
540
+ return value;
541
+ }
542
+ // src/renderers/pdf-options.mapper.ts
543
+ /** Paper sizes in inches, as Puppeteer defines them. */
544
+ const PAPER_FORMATS = {
545
+ letter: {
546
+ width: 8.5,
547
+ height: 11
548
+ },
549
+ legal: {
550
+ width: 8.5,
551
+ height: 14
552
+ },
553
+ tabloid: {
554
+ width: 11,
555
+ height: 17
556
+ },
557
+ ledger: {
558
+ width: 17,
559
+ height: 11
560
+ },
561
+ a0: {
562
+ width: 33.1102,
563
+ height: 46.811
564
+ },
565
+ a1: {
566
+ width: 23.3858,
567
+ height: 33.1102
568
+ },
569
+ a2: {
570
+ width: 16.5354,
571
+ height: 23.3858
572
+ },
573
+ a3: {
574
+ width: 11.6929,
575
+ height: 16.5354
576
+ },
577
+ a4: {
578
+ width: 8.2677,
579
+ height: 11.6929
580
+ },
581
+ a5: {
582
+ width: 5.8268,
583
+ height: 8.2677
584
+ },
585
+ a6: {
586
+ width: 4.1339,
587
+ height: 5.8268
588
+ }
589
+ };
590
+ const INCHES_PER_UNIT = {
591
+ px: 1 / 96,
592
+ in: 1,
593
+ cm: 1 / 2.54,
594
+ mm: 1 / 25.4
595
+ };
596
+ /**
597
+ * Converts a Puppeteer length (a number of pixels, or a string with a
598
+ * `px`/`in`/`cm`/`mm` unit) to inches.
599
+ */
600
+ function toInches(value) {
601
+ if (typeof value === "number") return value * INCHES_PER_UNIT.px;
602
+ const match = /^\s*(-?\d*\.?\d+)\s*(px|in|cm|mm)?\s*$/i.exec(value);
603
+ if (!match) throw new RendererConfigurationException(`Invalid length '${value}': expected a number of pixels or a value in px, in, cm or mm`);
604
+ const unit = (match[2] ?? "px").toLowerCase();
605
+ return Number(match[1]) * INCHES_PER_UNIT[unit];
606
+ }
607
+ function formatInches(inches) {
608
+ return String(Math.round(inches * 1e4) / 1e4);
609
+ }
610
+ function resolvePrintLayout(pdfOptions) {
611
+ let width;
612
+ let height;
613
+ if (pdfOptions.width !== void 0 || pdfOptions.height !== void 0) {
614
+ const fallback = PAPER_FORMATS.letter;
615
+ width = pdfOptions.width === void 0 ? fallback.width : toInches(pdfOptions.width);
616
+ height = pdfOptions.height === void 0 ? fallback.height : toInches(pdfOptions.height);
617
+ } else {
618
+ const formatName = (pdfOptions.format ?? "letter").toLowerCase();
619
+ const format = PAPER_FORMATS[formatName];
620
+ if (!format) throw new RendererConfigurationException(`Unknown paper format '${pdfOptions.format}'`);
621
+ ({width, height} = format);
622
+ }
623
+ const margin = {};
624
+ for (const side of [
625
+ "top",
626
+ "right",
627
+ "bottom",
628
+ "left"
629
+ ]) {
630
+ const value = pdfOptions.margin?.[side];
631
+ if (value !== void 0) margin[side] = toInches(value);
632
+ }
633
+ return {
634
+ width,
635
+ height,
636
+ margin
637
+ };
638
+ }
639
+ function toHtmlDocument(template) {
640
+ return /<html[\s>]/i.test(template) ? template : `<!DOCTYPE html><html><head></head><body>${template}</body></html>`;
641
+ }
642
+ function toGotenbergForm(pdfOptions) {
643
+ const { width, height, margin } = resolvePrintLayout(pdfOptions);
644
+ const fields = {
645
+ paperWidth: formatInches(width),
646
+ paperHeight: formatInches(height),
647
+ marginTop: formatInches(margin.top ?? 0),
648
+ marginRight: formatInches(margin.right ?? 0),
649
+ marginBottom: formatInches(margin.bottom ?? 0),
650
+ marginLeft: formatInches(margin.left ?? 0),
651
+ emulatedMediaType: "screen",
652
+ skipNetworkIdleEvent: "false"
653
+ };
654
+ if (pdfOptions.landscape !== void 0) fields.landscape = String(pdfOptions.landscape);
655
+ if (pdfOptions.printBackground !== void 0) fields.printBackground = String(pdfOptions.printBackground);
656
+ if (pdfOptions.omitBackground !== void 0) fields.omitBackground = String(pdfOptions.omitBackground);
657
+ if (pdfOptions.scale !== void 0) fields.scale = String(pdfOptions.scale);
658
+ if (pdfOptions.pageRanges) fields.nativePageRanges = pdfOptions.pageRanges;
659
+ if (pdfOptions.preferCSSPageSize !== void 0) fields.preferCssPageSize = String(pdfOptions.preferCSSPageSize);
660
+ if (pdfOptions.tagged !== void 0) fields.generateTaggedPdf = String(pdfOptions.tagged);
661
+ if (pdfOptions.outline !== void 0) fields.generateDocumentOutline = String(pdfOptions.outline);
662
+ const files = {};
663
+ if (pdfOptions.displayHeaderFooter) {
664
+ if (pdfOptions.headerTemplate) files["header.html"] = toHtmlDocument(pdfOptions.headerTemplate);
665
+ if (pdfOptions.footerTemplate) files["footer.html"] = toHtmlDocument(pdfOptions.footerTemplate);
666
+ }
667
+ return {
668
+ fields,
669
+ files
670
+ };
671
+ }
672
+ function toApi2PdfOptions(pdfOptions) {
673
+ const { width, height, margin } = resolvePrintLayout(pdfOptions);
674
+ const options = {
675
+ width: `${formatInches(width)}in`,
676
+ height: `${formatInches(height)}in`,
677
+ marginTop: `${formatInches(margin.top ?? 0)}in`,
678
+ marginRight: `${formatInches(margin.right ?? 0)}in`,
679
+ marginBottom: `${formatInches(margin.bottom ?? 0)}in`,
680
+ marginLeft: `${formatInches(margin.left ?? 0)}in`,
681
+ usePrintCss: false
682
+ };
683
+ for (const key of [
684
+ "landscape",
685
+ "printBackground",
686
+ "omitBackground",
687
+ "scale",
688
+ "pageRanges",
689
+ "displayHeaderFooter",
690
+ "headerTemplate",
691
+ "footerTemplate"
692
+ ]) if (pdfOptions[key] !== void 0) options[key] = pdfOptions[key];
693
+ return options;
694
+ }
695
+ // src/renderers/api2pdf.renderer.ts
696
+ const PROVIDER$1 = "Api2Pdf";
697
+ const DEFAULT_BASE_URL = "https://v2.api2pdf.com";
698
+ const ROUTE$1 = "/chrome/pdf/html";
699
+ function isApi2Pdf(data) {
700
+ return typeof data === "object" && data !== null && ("Success" in data || "Error" in data || "FileUrl" in data);
701
+ }
702
+ var Api2PdfRenderer = class {
703
+ #endpoint;
704
+ #headers;
705
+ constructor(provider) {
706
+ const apiKey = requireNonEmpty(provider.apiKey, "apiKey", PROVIDER$1);
707
+ const baseUrl = requireNonEmpty(provider.baseUrl ?? DEFAULT_BASE_URL, "baseUrl", PROVIDER$1).replace(/\/+$/, "");
708
+ this.#endpoint = `${baseUrl}${ROUTE$1}?outputBinary=true`;
709
+ this.#headers = {
710
+ ...provider.headers,
711
+ Authorization: apiKey,
712
+ "Content-Type": "application/json",
713
+ Accept: "application/pdf, application/json"
714
+ };
715
+ }
716
+ async render(html, options, signal) {
717
+ assertNoRequestGuard(PROVIDER$1, options, "Only render trusted HTML with a remote provider.");
718
+ const body = {
719
+ html,
720
+ inline: false,
721
+ options: {
722
+ ...toApi2PdfOptions(options.pdfOptions ?? { format: "A4" }),
723
+ ...options.api2pdfOptions?.options
724
+ }
725
+ };
726
+ if (options.api2pdfOptions?.fileName) body.fileName = options.api2pdfOptions.fileName;
727
+ const response = await fetch(this.#endpoint, {
728
+ method: "POST",
729
+ headers: this.#headers,
730
+ body: JSON.stringify(body),
731
+ signal
732
+ });
733
+ if (!response.ok) throw await httpError(PROVIDER$1, response);
734
+ if (!response.headers.get("content-type")?.includes("application/json")) return new Uint8Array(await response.arrayBuffer());
735
+ const result = await response.json();
736
+ if (!isApi2Pdf(result)) throw new PdfGenerationException(`${PROVIDER$1} returned an unexpected response: ${JSON.stringify(result)}`);
737
+ if (result.Success === false || !result.FileUrl) throw new PdfGenerationException(`${PROVIDER$1} could not generate the PDF: ${result.Error ?? "no file returned"}`);
738
+ const file = await fetch(result.FileUrl, { signal });
739
+ if (!file.ok) throw await httpError(PROVIDER$1, file);
740
+ return new Uint8Array(await file.arrayBuffer());
741
+ }
742
+ };
743
+ // src/renderers/gotenberg.renderer.ts
744
+ const PROVIDER = "Gotenberg";
745
+ const ROUTE = "/forms/chromium/convert/html";
746
+ var GotenbergRenderer = class {
747
+ #endpoint;
748
+ #headers;
749
+ constructor(provider) {
750
+ const url = requireNonEmpty(provider.url, "url", PROVIDER);
751
+ this.#endpoint = `${url.replace(/\/+$/, "")}${ROUTE}`;
752
+ this.#headers = { ...provider.headers };
753
+ if (provider.basicAuth) {
754
+ const { username, password } = provider.basicAuth;
755
+ this.#headers.Authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`;
756
+ }
757
+ }
758
+ async render(html, options, signal) {
759
+ assertNoRequestGuard(PROVIDER, options, "Restrict outbound requests on the Gotenberg server instead, with '--chromium-allow-list' / '--chromium-deny-list'.");
760
+ const { fields, files } = toGotenbergForm(options.pdfOptions ?? { format: "A4" });
761
+ const form = new FormData();
762
+ form.append("files", new Blob([html], { type: "text/html" }), "index.html");
763
+ for (const [name, content] of Object.entries(files)) form.append("files", new Blob([content], { type: "text/html" }), name);
764
+ for (const asset of options.gotenbergOptions?.assets ?? []) form.append("files", new Blob([asset.content], { type: asset.contentType ?? "application/octet-stream" }), asset.filename);
765
+ const allFields = {
766
+ ...fields,
767
+ ...options.gotenbergOptions?.formFields
768
+ };
769
+ for (const [name, value] of Object.entries(allFields)) form.append(name, value);
770
+ const response = await fetch(this.#endpoint, {
771
+ method: "POST",
772
+ headers: this.#headers,
773
+ body: form,
774
+ signal
775
+ });
776
+ if (!response.ok) throw await httpError(PROVIDER, response);
777
+ return new Uint8Array(await response.arrayBuffer());
778
+ }
779
+ };
780
+ // src/puppeteer/libs/loadPuppeteer.utils.ts
781
+ function isMissingPackage(error, packageName) {
782
+ const { code, message } = error;
783
+ return (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") && typeof message === "string" && message.includes(`'${packageName}'`);
784
+ }
785
+ /** Imports an optional peer dependency, turning "not installed" into a clear exception. */
786
+ async function loadOptional(packageName, importer) {
787
+ try {
788
+ return await importer();
789
+ } catch (error) {
790
+ if (isMissingPackage(error, packageName)) throw new EngineNotAvailableException("Puppeteer", packageName, { cause: error });
791
+ throw error;
792
+ }
793
+ }
794
+ /**
795
+ * Puppeteer is an optional peer dependency, only needed by the `puppeteer`
796
+ * provider: it is imported on first use, never when the library loads.
797
+ */
798
+ function loadPuppeteer() {
799
+ return loadOptional("puppeteer", () => import("puppeteer"));
800
+ }
801
+ function loadPuppeteerBrowsers() {
802
+ return loadOptional("@puppeteer/browsers", () => import("@puppeteer/browsers"));
803
+ }
804
+ // src/helpers/request-guard.helper.ts
533
805
  const blockedRanges = new node_net.BlockList();
534
806
  for (const [address, prefix] of [
535
807
  ["0.0.0.0", 8],
@@ -657,8 +929,9 @@ function describe(rawUrl) {
657
929
  * and closes the pop-ups a script could open to escape the filter.
658
930
  */
659
931
  async function installRequestGuard(context, page, options) {
932
+ const { TargetType } = await loadPuppeteer();
660
933
  context.on("targetcreated", (target) => {
661
- if (target.type() === puppeteer.TargetType.PAGE && target.opener()) target.page().then((popup) => popup?.close()).catch(() => void 0);
934
+ if (target.type() === TargetType.PAGE && target.opener()) target.page().then((popup) => popup?.close()).catch(() => void 0);
662
935
  });
663
936
  if (options.javascriptEnabled === false) await page.setJavaScriptEnabled(false);
664
937
  await page.setRequestInterception(true);
@@ -676,31 +949,162 @@ async function installRequestGuard(context, page, options) {
676
949
  })().catch(() => void 0);
677
950
  });
678
951
  }
679
- //#endregion
680
- //#region src/helpers/tokens.ts
681
- const PDF_PARAMETERS = "PDF_PARAMETERS";
682
- //#endregion
683
- //#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateMetadata.js
952
+ // src/renderers/puppeteer.renderer.ts
953
+ const DEFAULT_ARGS = [
954
+ "--autoplay-policy=user-gesture-required",
955
+ "--disable-background-networking",
956
+ "--disable-background-timer-throttling",
957
+ "--disable-backgrounding-occluded-windows",
958
+ "--disable-breakpad",
959
+ "--disable-client-side-phishing-detection",
960
+ "--disable-component-update",
961
+ "--disable-default-apps",
962
+ "--disable-dev-shm-usage",
963
+ "--disable-domain-reliability",
964
+ "--disable-extensions",
965
+ "--disable-features=AudioServiceOutOfProcess",
966
+ "--disable-hang-monitor",
967
+ "--disable-ipc-flooding-protection",
968
+ "--disable-notifications",
969
+ "--disable-offer-store-unmasked-wallet-cards",
970
+ "--disable-print-preview",
971
+ "--disable-prompt-on-repost",
972
+ "--disable-renderer-backgrounding",
973
+ "--disable-setuid-sandbox",
974
+ "--disable-speech-api",
975
+ "--disable-sync",
976
+ "--hide-scrollbars",
977
+ "--ignore-gpu-blacklist",
978
+ "--metrics-recording-only",
979
+ "--mute-audio",
980
+ "--no-default-browser-check",
981
+ "--no-first-run",
982
+ "--no-pings",
983
+ "--password-store=basic",
984
+ "--use-gl=swiftshader",
985
+ "--use-mock-keychain",
986
+ "--disable-accelerated-2d-canvas",
987
+ "--no-zygote",
988
+ "--disable-gpu"
989
+ ];
990
+ const PDF_OPTION_KEYS = {
991
+ scale: true,
992
+ displayHeaderFooter: true,
993
+ headerTemplate: true,
994
+ footerTemplate: true,
995
+ printBackground: true,
996
+ landscape: true,
997
+ pageRanges: true,
998
+ format: true,
999
+ width: true,
1000
+ height: true,
1001
+ preferCSSPageSize: true,
1002
+ margin: true,
1003
+ path: true,
1004
+ omitBackground: true,
1005
+ tagged: true,
1006
+ outline: true,
1007
+ timeout: true,
1008
+ waitForFonts: true
1009
+ };
1010
+ function toPuppeteerPdfOptions(options) {
1011
+ if (!options) return { format: "A4" };
1012
+ const invalidKeys = Object.keys(options).filter((key) => !Object.hasOwn(PDF_OPTION_KEYS, key));
1013
+ if (invalidKeys.length > 0) throw new RendererConfigurationException(`Invalid PDF options: ${invalidKeys.join(", ")}. Please check the documentation for valid options.`);
1014
+ return options;
1015
+ }
1016
+ var PuppeteerRenderer = class {
1017
+ #browserService;
1018
+ constructor(browserService) {
1019
+ this.#browserService = browserService;
1020
+ }
1021
+ async render(html, options, signal) {
1022
+ if (options.chromiumRevision !== void 0) _nestjs_common.Logger.warn("Using `chromiumRevision` is no longer supported since the puppeteer update.");
1023
+ const pdfOptions = toPuppeteerPdfOptions(options.pdfOptions);
1024
+ const headless = options.headless ?? true;
1025
+ const executablePath = options.executablePath || void 0;
1026
+ const args = options.extraPuppeteerArgs || DEFAULT_ARGS;
1027
+ let context = null;
1028
+ let closing;
1029
+ const onAbort = () => {
1030
+ if (!context) return;
1031
+ closing = context.close();
1032
+ closing.catch(() => void 0);
1033
+ };
1034
+ signal?.addEventListener("abort", onAbort, { once: true });
1035
+ try {
1036
+ context = await this.#browserService.createContext(args, headless, executablePath);
1037
+ signal?.throwIfAborted();
1038
+ const page = await context.newPage();
1039
+ if (options.security) await installRequestGuard(context, page, options.security);
1040
+ await page.setContent(html, { waitUntil: "domcontentloaded" });
1041
+ await page.emulateMediaType("screen");
1042
+ await page.waitForNetworkIdle({
1043
+ idleTime: 500,
1044
+ timeout: 3e4
1045
+ });
1046
+ /* v8 ignore next */
1047
+ await page.evaluate(() => document.fonts.ready);
1048
+ return await page.pdf(pdfOptions);
1049
+ } finally {
1050
+ signal?.removeEventListener("abort", onAbort);
1051
+ if (context) try {
1052
+ if (closing) await closing;
1053
+ else await context.close();
1054
+ } catch (error) {
1055
+ _nestjs_common.Logger.error(error);
1056
+ }
1057
+ }
1058
+ }
1059
+ };
1060
+ // src/renderers/create-renderer.ts
1061
+ /** True when the PDFs are printed by the local Chromium (the default). */
1062
+ function usesPuppeteer(params) {
1063
+ return (params.provider?.type ?? "puppeteer") === "puppeteer";
1064
+ }
1065
+ function createPdfRenderer(params, browserService) {
1066
+ const provider = params.provider ?? { type: "puppeteer" };
1067
+ switch (provider.type) {
1068
+ case "puppeteer": return new PuppeteerRenderer(browserService);
1069
+ case "gotenberg": return new GotenbergRenderer(provider);
1070
+ case "api2pdf": return new Api2PdfRenderer(provider);
1071
+ default: throw new RendererConfigurationException(`Unknown PDF provider '${String(provider.type)}': expected 'puppeteer', 'gotenberg' or 'api2pdf'`);
1072
+ }
1073
+ }
1074
+ // src/puppeteer/libs/enum.utils.ts
1075
+ /**
1076
+ * Converts a string value to an enum member, throwing a RendererConfigurationException if the value is not a valid member of the enum.
1077
+ * @param enumObject
1078
+ * @param value
1079
+ * @param label
1080
+ * @throws RendererConfigurationException
1081
+ */
1082
+ function toEnumMember(enumObject, value, label) {
1083
+ const members = Object.values(enumObject);
1084
+ const isMember = (candidate) => candidate === value;
1085
+ const member = members.find(isMember);
1086
+ if (member === void 0) throw new RendererConfigurationException(`Unsupported ${label} '${value}': expected one of ${members.map((m) => `'${m}'`).join(", ")}`);
1087
+ return member;
1088
+ }
1089
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/decorateMetadata.js
684
1090
  function __decorateMetadata(k, v) {
685
1091
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
686
1092
  }
687
- //#endregion
688
- //#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateParam.js
1093
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/decorateParam.js
689
1094
  function __decorateParam(paramIndex, decorator) {
690
1095
  return function(target, key) {
691
1096
  decorator(target, key, paramIndex);
692
1097
  };
693
1098
  }
694
- //#endregion
695
- //#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorate.js
1099
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/decorate.js
696
1100
  function __decorate(decorators, target, key, desc) {
697
1101
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
698
1102
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
699
1103
  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;
700
1104
  return c > 3 && r && Object.defineProperty(target, key, r), r;
701
1105
  }
702
- //#endregion
703
- //#region src/puppeteer/browser/browser.service.ts
1106
+ // src/puppeteer/browser/browser.service.ts
1107
+ const DEFAULT_BROWSER = "chromium";
704
1108
  async function sleep(ms) {
705
1109
  await new Promise((r) => setTimeout(r, ms));
706
1110
  }
@@ -752,7 +1156,7 @@ let BrowserService = class BrowserService {
752
1156
  } catch (error) {
753
1157
  _nestjs_common.Logger.warn(`Failed to close browser on module destroy: ${error instanceof Error ? error.message : String(error)}`);
754
1158
  }
755
- if (this.#options?.cleanupBrowserCacheOnExit !== false) await this.#cleanupCacheBestEffort();
1159
+ if (this.#options !== void 0 && usesPuppeteer(this.#options) && this.#options.cleanupBrowserCacheOnExit !== false) await this.#cleanupCacheBestEffort();
756
1160
  }
757
1161
  /** Wait until no PDF job is in flight, or until the timeout elapses. */
758
1162
  async #waitForIdle(timeoutMs) {
@@ -834,11 +1238,12 @@ let BrowserService = class BrowserService {
834
1238
  }
835
1239
  }
836
1240
  async #doInstall(lock) {
837
- const browser = this.#browser;
1241
+ const { Browser: BrowserEnum, BrowserPlatform, canDownload, detectBrowserPlatform, install, resolveBuildId } = await loadPuppeteerBrowsers();
1242
+ const browser = toEnumMember(BrowserEnum, this.#browser, "browser");
838
1243
  const versionTag = this.#browserTag;
839
- const browserPlatform = (0, _puppeteer_browsers.detectBrowserPlatform)() ?? _puppeteer_browsers.BrowserPlatform.LINUX;
1244
+ const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
840
1245
  let buildId;
841
- if (this.#buildId === void 0) buildId = await (0, _puppeteer_browsers.resolveBuildId)(browser, browserPlatform, versionTag);
1246
+ if (this.#buildId === void 0) buildId = await resolveBuildId(browser, browserPlatform, versionTag);
842
1247
  else buildId = this.#buildId;
843
1248
  _nestjs_common.Logger.log(`Browser ${browser} ${versionTag} build id: ${buildId}`, "NestJsPdf");
844
1249
  if (await this.hasBrowserInstalled(browser, buildId)) {
@@ -853,9 +1258,9 @@ let BrowserService = class BrowserService {
853
1258
  buildId,
854
1259
  baseUrl: this.#options?.browserInstallBaseUrl ?? void 0
855
1260
  };
856
- if (await (0, _puppeteer_browsers.canDownload)(installOption)) {
1261
+ if (await canDownload(installOption)) {
857
1262
  _nestjs_common.Logger.log(`Installing ${installOption.browser} ${installOption.buildId}`, "NestJsPdf");
858
- const installedBrowser = await (0, _puppeteer_browsers.install)(installOption);
1263
+ const installedBrowser = await install(installOption);
859
1264
  if (await this.hasBrowserInstalled(browser, buildId)) {
860
1265
  _nestjs_common.Logger.log("Browser installed successfully", "NestJsPdf");
861
1266
  if (lock) this.#writeLockFile(browser, buildId);
@@ -866,10 +1271,7 @@ let BrowserService = class BrowserService {
866
1271
  return null;
867
1272
  }
868
1273
  #loadBrowser() {
869
- let browser;
870
- if (this.#options?.browser === void 0) browser = _puppeteer_browsers.Browser.CHROMIUM;
871
- else browser = this.#options.browser;
872
- this.#browser = browser;
1274
+ this.#browser = this.#options?.browser ?? DEFAULT_BROWSER;
873
1275
  }
874
1276
  getBrowser() {
875
1277
  return this.#browser;
@@ -877,7 +1279,7 @@ let BrowserService = class BrowserService {
877
1279
  #loadBrowserTag() {
878
1280
  let versionTag;
879
1281
  if (this.#options?.browserTag === void 0) {
880
- if (this.#browser === _puppeteer_browsers.Browser.CHROMIUM) versionTag = "latest";
1282
+ if (this.#browser === DEFAULT_BROWSER) versionTag = "latest";
881
1283
  else versionTag = "stable";
882
1284
  } else versionTag = this.#options.browserTag;
883
1285
  this.#browserTag = versionTag;
@@ -904,21 +1306,24 @@ let BrowserService = class BrowserService {
904
1306
  this.#useLockedBrowser = useLockedBrowser;
905
1307
  }
906
1308
  async hasBrowserInstalled(browser, buildId) {
907
- return (await (0, _puppeteer_browsers.getInstalledBrowsers)({ cacheDir: this.#cacheDir })).find((insBrowser) => {
908
- return insBrowser.browser === browser && insBrowser.buildId === buildId;
1309
+ const { Browser: BrowserEnum, getInstalledBrowsers } = await loadPuppeteerBrowsers();
1310
+ const expected = toEnumMember(BrowserEnum, browser, "browser");
1311
+ return (await getInstalledBrowsers({ cacheDir: this.#cacheDir })).find((insBrowser) => {
1312
+ return insBrowser.browser === expected && insBrowser.buildId === buildId;
909
1313
  }) !== void 0;
910
1314
  }
911
1315
  async getExecutablePath() {
912
- const browser = this.#browser;
1316
+ const { Browser: BrowserEnum, BrowserPlatform, detectBrowserPlatform, getInstalledBrowsers, resolveBuildId } = await loadPuppeteerBrowsers();
1317
+ const browser = toEnumMember(BrowserEnum, this.#browser, "browser");
913
1318
  const versionTag = this.#browserTag;
914
- const browserPlatform = (0, _puppeteer_browsers.detectBrowserPlatform)() ?? _puppeteer_browsers.BrowserPlatform.LINUX;
1319
+ const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
915
1320
  let buildId = null;
916
1321
  if (this.#useLockedBrowser) {
917
1322
  buildId = this.getLockedBuildId(browser);
918
1323
  _nestjs_common.Logger.log(`Using locked browser ${buildId}`, "NestJsPdf");
919
1324
  }
920
- buildId ??= await (0, _puppeteer_browsers.resolveBuildId)(browser, browserPlatform, versionTag);
921
- const installedBrowser = (await (0, _puppeteer_browsers.getInstalledBrowsers)({ cacheDir: this.#cacheDir })).find((insBrowser) => {
1325
+ buildId ??= await resolveBuildId(browser, browserPlatform, versionTag);
1326
+ const installedBrowser = (await getInstalledBrowsers({ cacheDir: this.#cacheDir })).find((insBrowser) => {
922
1327
  return insBrowser.browser === browser && insBrowser.buildId === buildId;
923
1328
  });
924
1329
  if (installedBrowser === void 0) {
@@ -930,7 +1335,8 @@ let BrowserService = class BrowserService {
930
1335
  }
931
1336
  async #launchBrowser(args, headless, executablePathBin) {
932
1337
  const executablePath = executablePathBin ?? await this.getExecutablePath();
933
- const browser = await (0, puppeteer.launch)({
1338
+ const { launch } = await loadPuppeteer();
1339
+ const browser = await launch({
934
1340
  executablePath,
935
1341
  headless,
936
1342
  args,
@@ -966,8 +1372,7 @@ BrowserService = __decorate([
966
1372
  __decorateParam(0, (0, _nestjs_common.Inject)("PDF_PARAMETERS")),
967
1373
  __decorateMetadata("design:paramtypes", [Object])
968
1374
  ], BrowserService);
969
- //#endregion
970
- //#region src/puppeteer/libs/loadEngine.utils.ts
1375
+ // src/puppeteer/libs/loadEngine.utils.ts
971
1376
  const requireEngine = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
972
1377
  /**
973
1378
  * Load an optional template engine on first use, so the library can be imported
@@ -984,8 +1389,7 @@ function loadEngine(packageName, engineName) {
984
1389
  }
985
1390
  return mod.__esModule && "default" in mod ? mod.default : mod;
986
1391
  }
987
- //#endregion
988
- //#region src/puppeteer/engines/ejs/ejs.service.ts
1392
+ // src/puppeteer/engines/ejs/ejs.service.ts
989
1393
  let EjsService = class EjsService {
990
1394
  #ejs;
991
1395
  get #engine() {
@@ -1015,8 +1419,7 @@ let EjsService = class EjsService {
1015
1419
  }
1016
1420
  };
1017
1421
  EjsService = __decorate([(0, _nestjs_common.Injectable)()], EjsService);
1018
- //#endregion
1019
- //#region src/puppeteer/engines/eta/eta.service.ts
1422
+ // src/puppeteer/engines/eta/eta.service.ts
1020
1423
  let EtaService = class EtaService {
1021
1424
  #etaModule;
1022
1425
  #eta;
@@ -1087,8 +1490,7 @@ let EtaService = class EtaService {
1087
1490
  }
1088
1491
  };
1089
1492
  EtaService = __decorate([(0, _nestjs_common.Injectable)()], EtaService);
1090
- //#endregion
1091
- //#region src/puppeteer/engines/handlebars/handlebars.service.ts
1493
+ // src/puppeteer/engines/handlebars/handlebars.service.ts
1092
1494
  let HandlebarsService = class HandlebarsService {
1093
1495
  #handlebars;
1094
1496
  #cachedOptions;
@@ -1143,8 +1545,7 @@ let HandlebarsService = class HandlebarsService {
1143
1545
  }
1144
1546
  };
1145
1547
  HandlebarsService = __decorate([(0, _nestjs_common.Injectable)()], HandlebarsService);
1146
- //#endregion
1147
- //#region src/puppeteer/engines/liquid/liquid.service.ts
1548
+ // src/puppeteer/engines/liquid/liquid.service.ts
1148
1549
  let LiquidService = class LiquidService {
1149
1550
  #liquidModule;
1150
1551
  #liquid;
@@ -1205,8 +1606,7 @@ let LiquidService = class LiquidService {
1205
1606
  }
1206
1607
  };
1207
1608
  LiquidService = __decorate([(0, _nestjs_common.Injectable)()], LiquidService);
1208
- //#endregion
1209
- //#region src/puppeteer/engines/mjml/mjml.service.ts
1609
+ // src/puppeteer/engines/mjml/mjml.service.ts
1210
1610
  let MjmlService = class MjmlService {
1211
1611
  #mjml;
1212
1612
  get #engine() {
@@ -1232,8 +1632,7 @@ let MjmlService = class MjmlService {
1232
1632
  }
1233
1633
  };
1234
1634
  MjmlService = __decorate([(0, _nestjs_common.Injectable)()], MjmlService);
1235
- //#endregion
1236
- //#region src/puppeteer/engines/mustache/mustache.service.ts
1635
+ // src/puppeteer/engines/mustache/mustache.service.ts
1237
1636
  let MustacheService = class MustacheService {
1238
1637
  #mustache;
1239
1638
  #templateCache = /* @__PURE__ */ new Map();
@@ -1296,8 +1695,7 @@ let MustacheService = class MustacheService {
1296
1695
  }
1297
1696
  };
1298
1697
  MustacheService = __decorate([(0, _nestjs_common.Injectable)()], MustacheService);
1299
- //#endregion
1300
- //#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
1698
+ // src/puppeteer/engines/nunjucks/nunjucks.service.ts
1301
1699
  let NunjucksService = class NunjucksService {
1302
1700
  #nunjucks;
1303
1701
  get #engine() {
@@ -1349,8 +1747,7 @@ let NunjucksService = class NunjucksService {
1349
1747
  }
1350
1748
  };
1351
1749
  NunjucksService = __decorate([(0, _nestjs_common.Injectable)()], NunjucksService);
1352
- //#endregion
1353
- //#region src/puppeteer/engines/pug/pug.service.ts
1750
+ // src/puppeteer/engines/pug/pug.service.ts
1354
1751
  let PugService = class PugService {
1355
1752
  #pug;
1356
1753
  get #engine() {
@@ -1375,16 +1772,15 @@ let PugService = class PugService {
1375
1772
  }
1376
1773
  };
1377
1774
  PugService = __decorate([(0, _nestjs_common.Injectable)()], PugService);
1378
- //#endregion
1379
- //#region src/puppeteer/libs/requireService.utils.ts
1775
+ // src/puppeteer/libs/requireService.utils.ts
1380
1776
  function requireService(service, name) {
1381
1777
  if (!service) throw new EngineNotAvailableException(name);
1382
1778
  return service;
1383
1779
  }
1384
- //#endregion
1385
- //#region src/puppeteer/puppeteer.service.ts
1780
+ // src/puppeteer/puppeteer.service.ts
1386
1781
  let PuppeteerService = class PuppeteerService {
1387
- #browserService;
1782
+ #renderer;
1783
+ #jobs;
1388
1784
  #options;
1389
1785
  #hbsService;
1390
1786
  #mjmlService;
@@ -1394,8 +1790,9 @@ let PuppeteerService = class PuppeteerService {
1394
1790
  #etaService;
1395
1791
  #mustacheService;
1396
1792
  #liquidService;
1397
- constructor(browserService, options, hbsService, mjmlService, pugService, ejsService, nunjucksService, etaService, mustacheService, liquidService) {
1398
- this.#browserService = browserService;
1793
+ constructor(renderer, jobs, options, hbsService, mjmlService, pugService, ejsService, nunjucksService, etaService, mustacheService, liquidService) {
1794
+ this.#renderer = renderer;
1795
+ this.#jobs = jobs;
1399
1796
  this.#options = options;
1400
1797
  this.#hbsService = hbsService;
1401
1798
  this.#mjmlService = mjmlService;
@@ -1414,87 +1811,19 @@ let PuppeteerService = class PuppeteerService {
1414
1811
  const job = this.#limit(async () => {
1415
1812
  signal?.throwIfAborted();
1416
1813
  started = true;
1417
- const mergePuppeteerOptions = mergePuppeteerParameters(this.#options, options);
1418
- if (mergePuppeteerOptions.chromiumRevision !== void 0) _nestjs_common.Logger.warn("Using `chromiumRevision` is no longer supported since the puppeteer update.");
1419
- const headless = mergePuppeteerOptions.headless ?? true;
1420
- const executablePath = mergePuppeteerOptions.executablePath || void 0;
1421
- const args = mergePuppeteerOptions.extraPuppeteerArgs || [
1422
- "--autoplay-policy=user-gesture-required",
1423
- "--disable-background-networking",
1424
- "--disable-background-timer-throttling",
1425
- "--disable-backgrounding-occluded-windows",
1426
- "--disable-breakpad",
1427
- "--disable-client-side-phishing-detection",
1428
- "--disable-component-update",
1429
- "--disable-default-apps",
1430
- "--disable-dev-shm-usage",
1431
- "--disable-domain-reliability",
1432
- "--disable-extensions",
1433
- "--disable-features=AudioServiceOutOfProcess",
1434
- "--disable-hang-monitor",
1435
- "--disable-ipc-flooding-protection",
1436
- "--disable-notifications",
1437
- "--disable-offer-store-unmasked-wallet-cards",
1438
- "--disable-print-preview",
1439
- "--disable-prompt-on-repost",
1440
- "--disable-renderer-backgrounding",
1441
- "--disable-setuid-sandbox",
1442
- "--disable-speech-api",
1443
- "--disable-sync",
1444
- "--hide-scrollbars",
1445
- "--ignore-gpu-blacklist",
1446
- "--metrics-recording-only",
1447
- "--mute-audio",
1448
- "--no-default-browser-check",
1449
- "--no-first-run",
1450
- "--no-pings",
1451
- "--password-store=basic",
1452
- "--use-gl=swiftshader",
1453
- "--use-mock-keychain",
1454
- "--disable-accelerated-2d-canvas",
1455
- "--no-zygote",
1456
- "--disable-gpu"
1457
- ];
1458
- this.#browserService.markJobStarted();
1459
- let context = null;
1460
- let closing;
1461
- const onAbort = () => {
1462
- if (!context) return;
1463
- closing = context.close();
1464
- closing.catch(() => void 0);
1465
- };
1466
- signal?.addEventListener("abort", onAbort, { once: true });
1814
+ const mergedOptions = mergePuppeteerParameters(this.#options, options);
1815
+ this.#jobs.markJobStarted();
1467
1816
  try {
1468
- context = await this.#browserService.createContext(args, headless, executablePath);
1469
- signal?.throwIfAborted();
1470
- const page = await context.newPage();
1471
- if (mergePuppeteerOptions.security) await installRequestGuard(context, page, mergePuppeteerOptions.security);
1472
- const pdfOptions = mergePuppeteerOptions.pdfOptions ?? { format: "A4" };
1473
- await page.setContent(html, { waitUntil: "domcontentloaded" });
1474
- await page.emulateMediaType("screen");
1475
- await page.waitForNetworkIdle({
1476
- idleTime: 500,
1477
- timeout: 3e4
1478
- });
1479
- /* v8 ignore next */
1480
- await page.evaluate(() => document.fonts.ready);
1481
- const pdf = await page.pdf(pdfOptions);
1817
+ const pdf = await this.#renderer.render(html, mergedOptions, signal);
1482
1818
  signal?.throwIfAborted();
1483
- return mergePuppeteerOptions.watermark ? await addWatermark(pdf, mergePuppeteerOptions.watermark) : pdf;
1819
+ return mergedOptions.watermark ? await addWatermark(pdf, mergedOptions.watermark) : pdf;
1484
1820
  } catch (e) {
1485
1821
  if (signal?.aborted) throw signal.reason;
1486
1822
  _nestjs_common.Logger.error(e);
1487
1823
  if (e instanceof NestjsPdfException) throw e;
1488
1824
  throw new PdfGenerationException(`PDF generation failed: ${String(e)}`, { cause: e });
1489
1825
  } finally {
1490
- signal?.removeEventListener("abort", onAbort);
1491
- if (context) try {
1492
- if (closing) await closing;
1493
- else await context.close();
1494
- } catch (error) {
1495
- _nestjs_common.Logger.error(error);
1496
- }
1497
- await this.#browserService.markJobFinished();
1826
+ await this.#jobs.markJobFinished();
1498
1827
  }
1499
1828
  });
1500
1829
  if (!signal) return job;
@@ -1578,8 +1907,9 @@ let PuppeteerService = class PuppeteerService {
1578
1907
  };
1579
1908
  PuppeteerService = __decorate([
1580
1909
  (0, _nestjs_common.Injectable)(),
1581
- __decorateParam(1, (0, _nestjs_common.Inject)(PDF_PARAMETERS)),
1582
- __decorateParam(2, (0, _nestjs_common.Optional)()),
1910
+ __decorateParam(0, (0, _nestjs_common.Inject)(PDF_RENDERER)),
1911
+ __decorateParam(1, (0, _nestjs_common.Inject)(BrowserService)),
1912
+ __decorateParam(2, (0, _nestjs_common.Inject)(PDF_PARAMETERS)),
1583
1913
  __decorateParam(3, (0, _nestjs_common.Optional)()),
1584
1914
  __decorateParam(4, (0, _nestjs_common.Optional)()),
1585
1915
  __decorateParam(5, (0, _nestjs_common.Optional)()),
@@ -1587,8 +1917,10 @@ PuppeteerService = __decorate([
1587
1917
  __decorateParam(7, (0, _nestjs_common.Optional)()),
1588
1918
  __decorateParam(8, (0, _nestjs_common.Optional)()),
1589
1919
  __decorateParam(9, (0, _nestjs_common.Optional)()),
1920
+ __decorateParam(10, (0, _nestjs_common.Optional)()),
1590
1921
  __decorateMetadata("design:paramtypes", [
1591
- typeof BrowserService === "undefined" ? Object : BrowserService,
1922
+ Object,
1923
+ Object,
1592
1924
  Object,
1593
1925
  typeof HandlebarsService === "undefined" ? Object : HandlebarsService,
1594
1926
  typeof MjmlService === "undefined" ? Object : MjmlService,
@@ -1600,8 +1932,7 @@ PuppeteerService = __decorate([
1600
1932
  typeof LiquidService === "undefined" ? Object : LiquidService
1601
1933
  ])
1602
1934
  ], PuppeteerService);
1603
- //#endregion
1604
- //#region src/nestjs-pdf.service.ts
1935
+ // src/nestjs-pdf.service.ts
1605
1936
  let NestjsPdfService = class NestjsPdfService {
1606
1937
  #puppeteerService;
1607
1938
  constructor(puppeteerService) {
@@ -1821,9 +2152,14 @@ let NestjsPdfService = class NestjsPdfService {
1821
2152
  }
1822
2153
  };
1823
2154
  NestjsPdfService = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof PuppeteerService === "undefined" ? Object : PuppeteerService])], NestjsPdfService);
1824
- //#endregion
1825
- //#region src/puppeteer/puppeteer.module.ts
2155
+ // src/puppeteer/puppeteer.module.ts
1826
2156
  var _PuppeteerModule;
2157
+ /** Builds the renderer of the configured provider, once the parameters are known. */
2158
+ const pdfRendererProvider = {
2159
+ provide: PDF_RENDERER,
2160
+ inject: [PDF_PARAMETERS, BrowserService],
2161
+ useFactory: createPdfRenderer
2162
+ };
1827
2163
  let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
1828
2164
  #browserService;
1829
2165
  #pdfParams;
@@ -1832,7 +2168,12 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
1832
2168
  this.#pdfParams = pdfParams;
1833
2169
  }
1834
2170
  async onModuleInit() {
1835
- if (!this.#pdfParams.executablePath) await this.#browserService.install(this.#pdfParams.useLockedBrowser ?? false);
2171
+ if (!usesPuppeteer(this.#pdfParams)) return;
2172
+ await loadPuppeteer();
2173
+ if (!this.#pdfParams.executablePath) {
2174
+ await loadPuppeteerBrowsers();
2175
+ await this.#browserService.install(this.#pdfParams.useLockedBrowser ?? false);
2176
+ }
1836
2177
  }
1837
2178
  static forRoot(pdfParameters) {
1838
2179
  return {
@@ -1876,6 +2217,7 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
1876
2217
  pdfParamsProvider,
1877
2218
  PuppeteerService,
1878
2219
  BrowserService,
2220
+ pdfRendererProvider,
1879
2221
  HandlebarsService,
1880
2222
  MjmlService,
1881
2223
  PugService,
@@ -1903,6 +2245,7 @@ PuppeteerModule = _PuppeteerModule = __decorate([
1903
2245
  providers: [
1904
2246
  PuppeteerService,
1905
2247
  BrowserService,
2248
+ pdfRendererProvider,
1906
2249
  MjmlService,
1907
2250
  PugService,
1908
2251
  EjsService,
@@ -1922,11 +2265,11 @@ PuppeteerModule = _PuppeteerModule = __decorate([
1922
2265
  LiquidService
1923
2266
  ]
1924
2267
  }),
2268
+ __decorateParam(0, (0, _nestjs_common.Inject)(BrowserService)),
1925
2269
  __decorateParam(1, (0, _nestjs_common.Inject)(PDF_PARAMETERS)),
1926
- __decorateMetadata("design:paramtypes", [typeof BrowserService === "undefined" ? Object : BrowserService, Object])
2270
+ __decorateMetadata("design:paramtypes", [Object, Object])
1927
2271
  ], PuppeteerModule);
1928
- //#endregion
1929
- //#region src/nestjs-pdf.module.ts
2272
+ // src/nestjs-pdf.module.ts
1930
2273
  var _NestjsPdfModule;
1931
2274
  let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
1932
2275
  static forRoot(options) {
@@ -1947,7 +2290,6 @@ let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
1947
2290
  }
1948
2291
  };
1949
2292
  NestjsPdfModule = _NestjsPdfModule = __decorate([(0, _nestjs_common.Module)({})], NestjsPdfModule);
1950
- //#endregion
1951
2293
  exports.BrowserInstallationException = BrowserInstallationException;
1952
2294
  exports.BrowserUnavailableException = BrowserUnavailableException;
1953
2295
  Object.defineProperty(exports, "EjsService", {
@@ -2026,6 +2368,7 @@ Object.defineProperty(exports, "PuppeteerService", {
2026
2368
  return PuppeteerService;
2027
2369
  }
2028
2370
  });
2371
+ exports.RendererConfigurationException = RendererConfigurationException;
2029
2372
  exports.SignatureDependencyException = SignatureDependencyException;
2030
2373
  exports.SignaturePlacementException = SignaturePlacementException;
2031
2374
  exports.TemplateConfigurationException = TemplateConfigurationException;