@shad0wz7/nestjs-pdf 3.1.0 → 3.2.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.mjs CHANGED
@@ -1,11 +1,13 @@
1
- import { createRequire } from "node:module";
2
- import { basename, extname, join, relative, resolve, sep } from "node:path";
3
- import { Global, Inject, Injectable, Logger, Module, Optional } from "@nestjs/common";
4
- import { PDFArray, PDFDict, PDFDocument, PDFName, PDFNumber, PDFString } from "pdf-lib";
1
+ import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
2
+ import { Inject, Injectable, Logger, Module, Optional } from "@nestjs/common";
3
+ import { PDFArray, PDFDict, PDFDocument, PDFName, PDFNumber, PDFString, StandardFonts, degrees, rgb } from "pdf-lib";
5
4
  import { deepmerge } from "deepmerge-ts";
5
+ import { lookup } from "node:dns/promises";
6
6
  import { existsSync, promises, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
7
- import { Browser, BrowserPlatform, canDownload, detectBrowserPlatform, getInstalledBrowsers, install, resolveBuildId } from "@puppeteer/browsers";
8
- import { launch } from "puppeteer";
7
+ import { BlockList, isIP } from "node:net";
8
+ import { fileURLToPath } from "node:url";
9
+ import { TargetType, launch } from "puppeteer";
10
+ import { Browser as Browser$1, BrowserPlatform, canDownload, detectBrowserPlatform, getInstalledBrowsers, install, resolveBuildId } from "@puppeteer/browsers";
9
11
  import ejs from "ejs";
10
12
  import { Eta } from "eta";
11
13
  import Handlebars from "handlebars";
@@ -13,36 +15,6 @@ import mjml from "mjml";
13
15
  import mustache from "mustache";
14
16
  import nunjucks from "nunjucks";
15
17
  import pug from "pug";
16
- import { isObject, isUndefined } from "@nestjs/common/utils/shared.utils.js";
17
- import * as fs$1 from "fs";
18
- import fs from "fs";
19
- import { resolve as resolve$1 } from "path";
20
- import { Subject } from "rxjs";
21
- import { randomUUID } from "crypto";
22
- //#region \0rolldown/runtime.js
23
- var __create = Object.create;
24
- var __defProp = Object.defineProperty;
25
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
26
- var __getOwnPropNames = Object.getOwnPropertyNames;
27
- var __getProtoOf = Object.getPrototypeOf;
28
- var __hasOwnProp = Object.prototype.hasOwnProperty;
29
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
30
- var __copyProps = (to, from, except, desc) => {
31
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
32
- key = keys[i];
33
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
34
- get: ((k) => from[k]).bind(null, key),
35
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
36
- });
37
- }
38
- return to;
39
- };
40
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
41
- value: mod,
42
- enumerable: true
43
- }) : target, mod));
44
- var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
45
- //#endregion
46
18
  //#region src/exceptions/nestjs-pdf.exception.ts
47
19
  let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
48
20
  NestjsPdfErrorCode["ENGINE_NOT_AVAILABLE"] = "ENGINE_NOT_AVAILABLE";
@@ -53,6 +25,7 @@ let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
53
25
  NestjsPdfErrorCode["PDF_GENERATION_ERROR"] = "PDF_GENERATION_ERROR";
54
26
  NestjsPdfErrorCode["SIGNATURE_DEPENDENCY_ERROR"] = "SIGNATURE_DEPENDENCY_ERROR";
55
27
  NestjsPdfErrorCode["SIGNATURE_PLACEMENT_ERROR"] = "SIGNATURE_PLACEMENT_ERROR";
28
+ NestjsPdfErrorCode["WATERMARK_ERROR"] = "WATERMARK_ERROR";
56
29
  return NestjsPdfErrorCode;
57
30
  }({});
58
31
  var NestjsPdfException = class extends Error {
@@ -110,6 +83,11 @@ var TemplateRenderException = class extends NestjsPdfException {
110
83
  }
111
84
  };
112
85
  //#endregion
86
+ //#region src/exceptions/watermark.exception.ts
87
+ var WatermarkException = class extends NestjsPdfException {
88
+ code = "WATERMARK_ERROR";
89
+ };
90
+ //#endregion
113
91
  //#region src/helpers/getRelativePath.helper.ts
114
92
  /**
115
93
  * Get the relative path to a value from the module directory.
@@ -269,6 +247,150 @@ async function addSignatureFieldUsingAnchor(pdf, fieldName = "SignatureDebtor",
269
247
  return await pdfDoc.save();
270
248
  }
271
249
  //#endregion
250
+ //#region src/helpers/watermark.helper.ts
251
+ const DEFAULT_OPACITY = .15;
252
+ const DEFAULT_ROTATION = 45;
253
+ const DEFAULT_FONT_SIZE = 60;
254
+ const DEFAULT_FONT = "HelveticaBold";
255
+ const DEFAULT_COLOR = "#808080";
256
+ const DEFAULT_TILE_SPACING = 100;
257
+ function parseHexColor(color) {
258
+ const match = /^#([\da-f]{3}|[\da-f]{6})$/i.exec(color);
259
+ if (!match) throw new WatermarkException(`Invalid watermark color "${color}", expected #rgb or #rrggbb`);
260
+ const hex = match[1].length === 3 ? [...match[1]].map((c) => c + c).join("") : match[1];
261
+ const channel = (i) => Number.parseInt(hex.slice(i, i + 2), 16) / 255;
262
+ return rgb(channel(0), channel(2), channel(4));
263
+ }
264
+ function embedImage(pdfDoc, bytes) {
265
+ const isPng = bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78;
266
+ const isJpeg = bytes[0] === 255 && bytes[1] === 216;
267
+ if (isPng) return pdfDoc.embedPng(bytes);
268
+ if (isJpeg) return pdfDoc.embedJpg(bytes);
269
+ throw new WatermarkException("Watermark image must be a PNG or JPEG");
270
+ }
271
+ function validate(options) {
272
+ const { text, image, opacity, fontSize, imageWidth, tileSpacing } = options;
273
+ if (!text && !image) throw new WatermarkException("A watermark requires at least a `text` or an `image`");
274
+ if (opacity !== void 0 && !(opacity >= 0 && opacity <= 1)) throw new WatermarkException("Watermark `opacity` must be between 0 and 1");
275
+ if (fontSize !== void 0 && !(fontSize > 0)) throw new WatermarkException("Watermark `fontSize` must be greater than 0");
276
+ if (imageWidth !== void 0 && !(imageWidth > 0)) throw new WatermarkException("Watermark `imageWidth` must be greater than 0");
277
+ if (tileSpacing !== void 0 && !(tileSpacing >= 0)) throw new WatermarkException("Watermark `tileSpacing` must be at least 0");
278
+ }
279
+ function resolvePageIndexes(pages, total) {
280
+ if (!pages) return Array.from({ length: total }, (_, i) => i);
281
+ for (const page of pages) if (!Number.isInteger(page) || page < 1 || page > total) throw new WatermarkException(`Watermark page ${page} is out of range (the PDF has ${total} page(s))`);
282
+ return [...new Set(pages)].map((page) => page - 1);
283
+ }
284
+ /**
285
+ * Centers of the marks for one page, in page coordinates. Tiles follow the
286
+ * rotated axes so rotated marks never overlap each other.
287
+ */
288
+ function markCenters(pageWidth, pageHeight, mark, options) {
289
+ const cx = pageWidth / 2;
290
+ const cy = pageHeight / 2;
291
+ if (options.position === "center") return [{
292
+ x: cx,
293
+ y: cy
294
+ }];
295
+ const theta = options.rotation * Math.PI / 180;
296
+ const cos = Math.cos(theta);
297
+ const sin = Math.sin(theta);
298
+ const stepX = mark.width + options.spacing;
299
+ const stepY = mark.height + options.spacing;
300
+ const reach = Math.hypot(mark.width, mark.height) / 2;
301
+ const n = Math.ceil((Math.hypot(pageWidth, pageHeight) / 2 + reach) / Math.min(stepX, stepY));
302
+ const centers = [];
303
+ for (let i = -n; i <= n; i++) for (let j = -n; j <= n; j++) {
304
+ const x = cx + i * stepX * cos - j * stepY * sin;
305
+ const y = cy + i * stepX * sin + j * stepY * cos;
306
+ if (x >= -reach && x <= pageWidth + reach && y >= -reach && y <= pageHeight + reach) centers.push({
307
+ x,
308
+ y
309
+ });
310
+ }
311
+ return centers;
312
+ }
313
+ async function buildMark(pdfDoc, options, pageWidth) {
314
+ const opacity = options.opacity ?? DEFAULT_OPACITY;
315
+ const rotate = degrees(options.rotation ?? DEFAULT_ROTATION);
316
+ if (options.image) {
317
+ const image = await embedImage(pdfDoc, new Uint8Array(options.image));
318
+ const width = options.imageWidth ?? pageWidth / 2;
319
+ const height = image.height / image.width * width;
320
+ return {
321
+ width,
322
+ height,
323
+ draw: (page, x, y) => page.drawImage(image, {
324
+ x,
325
+ y,
326
+ width,
327
+ height,
328
+ opacity,
329
+ rotate
330
+ })
331
+ };
332
+ }
333
+ const font = await pdfDoc.embedFont(StandardFonts[options.font ?? DEFAULT_FONT]);
334
+ const size = options.fontSize ?? DEFAULT_FONT_SIZE;
335
+ const text = options.text;
336
+ const color = parseHexColor(options.color ?? DEFAULT_COLOR);
337
+ let width;
338
+ try {
339
+ width = font.widthOfTextAtSize(text, size);
340
+ } catch (error) {
341
+ throw new WatermarkException(`Watermark text cannot be rendered with the ${options.font ?? DEFAULT_FONT} font (only WinAnsi characters are supported)`, { cause: error });
342
+ }
343
+ return {
344
+ width,
345
+ height: font.heightAtSize(size, { descender: false }),
346
+ draw: (page, x, y) => page.drawText(text, {
347
+ x,
348
+ y,
349
+ size,
350
+ font,
351
+ color,
352
+ opacity,
353
+ rotate
354
+ })
355
+ };
356
+ }
357
+ /**
358
+ * Stamps a text or image watermark on the pages of an existing PDF.
359
+ */
360
+ async function addWatermark(pdf, options) {
361
+ validate(options);
362
+ try {
363
+ const pdfDoc = await PDFDocument.load(new Uint8Array(pdf));
364
+ const pages = pdfDoc.getPages();
365
+ const indexes = resolvePageIndexes(options.pages, pages.length);
366
+ const position = options.position ?? "center";
367
+ const rotation = options.rotation ?? DEFAULT_ROTATION;
368
+ const spacing = options.tileSpacing ?? DEFAULT_TILE_SPACING;
369
+ const theta = rotation * Math.PI / 180;
370
+ const cos = Math.cos(theta);
371
+ const sin = Math.sin(theta);
372
+ const marks = /* @__PURE__ */ new Map();
373
+ for (const index of indexes) {
374
+ const page = pages[index];
375
+ const { width: pageWidth, height: pageHeight } = page.getSize();
376
+ let mark = marks.get(pageWidth);
377
+ if (!mark) {
378
+ mark = await buildMark(pdfDoc, options, pageWidth);
379
+ marks.set(pageWidth, mark);
380
+ }
381
+ for (const center of markCenters(pageWidth, pageHeight, mark, {
382
+ position,
383
+ rotation,
384
+ spacing
385
+ })) mark.draw(page, center.x - (mark.width / 2 * cos - mark.height / 2 * sin), center.y - (mark.width / 2 * sin + mark.height / 2 * cos));
386
+ }
387
+ return await pdfDoc.save();
388
+ } catch (error) {
389
+ if (error instanceof WatermarkException) throw error;
390
+ throw new WatermarkException(`Failed to add watermark: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
391
+ }
392
+ }
393
+ //#endregion
272
394
  //#region node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
273
395
  var Node = class {
274
396
  value;
@@ -402,6 +524,154 @@ function mergePuppeteerParameters(defaults, overrides) {
402
524
  return deepmerge(defaults, overrides);
403
525
  }
404
526
  //#endregion
527
+ //#region src/helpers/request-guard.helper.ts
528
+ const blockedRanges = new BlockList();
529
+ for (const [address, prefix] of [
530
+ ["0.0.0.0", 8],
531
+ ["10.0.0.0", 8],
532
+ ["100.64.0.0", 10],
533
+ ["127.0.0.0", 8],
534
+ ["169.254.0.0", 16],
535
+ ["172.16.0.0", 12],
536
+ ["192.0.0.0", 24],
537
+ ["192.168.0.0", 16],
538
+ ["198.18.0.0", 15],
539
+ ["224.0.0.0", 4],
540
+ ["240.0.0.0", 4]
541
+ ]) blockedRanges.addSubnet(address, prefix, "ipv4");
542
+ for (const [address, prefix] of [
543
+ ["::", 128],
544
+ ["::1", 128],
545
+ ["64:ff9b::", 96],
546
+ ["fc00::", 7],
547
+ ["fe80::", 10],
548
+ ["ff00::", 8]
549
+ ]) blockedRanges.addSubnet(address, prefix, "ipv6");
550
+ const IPV4_MAPPED_IPV6 = /^::ffff:([\da-f]{1,4}):([\da-f]{1,4})$/i;
551
+ /** True for addresses that must not be reachable from a rendered document. */
552
+ function isPrivateAddress(address) {
553
+ const family = isIP(address);
554
+ if (family === 4) return blockedRanges.check(address, "ipv4");
555
+ if (family === 6) {
556
+ const mapped = IPV4_MAPPED_IPV6.exec(address);
557
+ if (mapped) {
558
+ const high = Number.parseInt(mapped[1], 16);
559
+ const low = Number.parseInt(mapped[2], 16);
560
+ return isPrivateAddress([
561
+ high >> 8,
562
+ high & 255,
563
+ low >> 8,
564
+ low & 255
565
+ ].join("."));
566
+ }
567
+ return blockedRanges.check(address, "ipv6");
568
+ }
569
+ return true;
570
+ }
571
+ function hostMatches(hostname, pattern) {
572
+ const host = hostname.toLowerCase();
573
+ const rule = pattern.toLowerCase();
574
+ if (rule.startsWith("*.")) return host.endsWith(rule.slice(1));
575
+ return host === rule;
576
+ }
577
+ function isLocalhostName(hostname) {
578
+ return hostname === "localhost" || hostname.endsWith(".localhost");
579
+ }
580
+ async function resolvesToPrivateAddress(hostname) {
581
+ const host = hostname.replace(/^\[|\]$/g, "");
582
+ if (isIP(host)) return isPrivateAddress(host);
583
+ if (isLocalhostName(host)) return true;
584
+ try {
585
+ return (await lookup(host, {
586
+ all: true,
587
+ verbatim: true
588
+ })).some(({ address }) => isPrivateAddress(address));
589
+ } catch {
590
+ return true;
591
+ }
592
+ }
593
+ async function isFileAllowed(url, roots) {
594
+ if (roots.length === 0 || url.hostname !== "" && url.hostname !== "localhost") return false;
595
+ let path;
596
+ try {
597
+ path = fileURLToPath(url);
598
+ } catch {
599
+ return false;
600
+ }
601
+ const real = async (candidate) => {
602
+ const missing = [];
603
+ let current = resolve(candidate);
604
+ for (;;) try {
605
+ return join(await promises.realpath(current), ...missing);
606
+ } catch {
607
+ const parent = dirname(current);
608
+ if (parent === current) return resolve(candidate);
609
+ missing.unshift(basename(current));
610
+ current = parent;
611
+ }
612
+ };
613
+ const target = await real(path);
614
+ for (const root of roots) {
615
+ const rel = relative(await real(root), target);
616
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return true;
617
+ }
618
+ return false;
619
+ }
620
+ /** Decides whether the browser may fetch `rawUrl`. */
621
+ async function isRequestAllowed(rawUrl, options) {
622
+ let url;
623
+ try {
624
+ url = new URL(rawUrl);
625
+ } catch {
626
+ return false;
627
+ }
628
+ switch (url.protocol) {
629
+ case "about:":
630
+ case "data:":
631
+ case "blob:": return true;
632
+ case "file:": return isFileAllowed(url, options.allowedFileRoots ?? []);
633
+ case "http:":
634
+ case "https:":
635
+ if (options.allowedHosts) return options.allowedHosts.some((pattern) => hostMatches(url.hostname, pattern));
636
+ if (options.blockPrivateNetworks === false) return true;
637
+ return !await resolvesToPrivateAddress(url.hostname);
638
+ default: return false;
639
+ }
640
+ }
641
+ /** Logs the origin and path only: query strings may carry secrets. */
642
+ function describe(rawUrl) {
643
+ try {
644
+ const url = new URL(rawUrl);
645
+ return `${url.origin === "null" ? `${url.protocol}//` : url.origin}${url.pathname}`;
646
+ } catch {
647
+ return "<invalid url>";
648
+ }
649
+ }
650
+ /**
651
+ * Filters every request the page (and its frames) makes, redirects included,
652
+ * and closes the pop-ups a script could open to escape the filter.
653
+ */
654
+ async function installRequestGuard(context, page, options) {
655
+ context.on("targetcreated", (target) => {
656
+ if (target.type() === TargetType.PAGE && target.opener()) target.page().then((popup) => popup?.close()).catch(() => void 0);
657
+ });
658
+ if (options.javascriptEnabled === false) await page.setJavaScriptEnabled(false);
659
+ await page.setRequestInterception(true);
660
+ page.on("request", (request) => {
661
+ (async () => {
662
+ if (request.isInterceptResolutionHandled()) return;
663
+ const url = request.url();
664
+ const allowed = await isRequestAllowed(url, options).catch(() => false);
665
+ if (request.isInterceptResolutionHandled()) return;
666
+ if (allowed) await request.continue();
667
+ else {
668
+ Logger.warn(`Blocked request to ${describe(url)}`, "NestJsPdf");
669
+ await request.abort("blockedbyclient");
670
+ }
671
+ })().catch(() => void 0);
672
+ });
673
+ }
674
+ //#endregion
405
675
  //#region src/helpers/tokens.ts
406
676
  const PDF_PARAMETERS = "PDF_PARAMETERS";
407
677
  //#endregion
@@ -418,7 +688,7 @@ function __decorateParam(paramIndex, decorator) {
418
688
  }
419
689
  //#endregion
420
690
  //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
421
- function __decorate$3(decorators, target, key, desc) {
691
+ function __decorate(decorators, target, key, desc) {
422
692
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
423
693
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
424
694
  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;
@@ -592,7 +862,7 @@ let BrowserService = class BrowserService {
592
862
  }
593
863
  #loadBrowser() {
594
864
  let browser;
595
- if (this.#options?.browser === void 0) browser = Browser.CHROMIUM;
865
+ if (this.#options?.browser === void 0) browser = Browser$1.CHROMIUM;
596
866
  else browser = this.#options.browser;
597
867
  this.#browser = browser;
598
868
  }
@@ -602,7 +872,7 @@ let BrowserService = class BrowserService {
602
872
  #loadBrowserTag() {
603
873
  let versionTag;
604
874
  if (this.#options?.browserTag === void 0) {
605
- if (this.#browser === Browser.CHROMIUM) versionTag = "latest";
875
+ if (this.#browser === Browser$1.CHROMIUM) versionTag = "latest";
606
876
  else versionTag = "stable";
607
877
  } else versionTag = this.#options.browserTag;
608
878
  this.#browserTag = versionTag;
@@ -658,7 +928,8 @@ let BrowserService = class BrowserService {
658
928
  const browser = await launch({
659
929
  executablePath,
660
930
  headless,
661
- args
931
+ args,
932
+ ignoreDefaultArgs: ["--disable-popup-blocking"]
662
933
  });
663
934
  browser.on("disconnected", () => {
664
935
  Logger.warn("Puppeteer browser disconnected");
@@ -685,7 +956,7 @@ let BrowserService = class BrowserService {
685
956
  return null;
686
957
  }
687
958
  };
688
- BrowserService = __decorate$3([
959
+ BrowserService = __decorate([
689
960
  Injectable(),
690
961
  __decorateParam(0, Inject("PDF_PARAMETERS")),
691
962
  __decorateMetadata("design:paramtypes", [Object])
@@ -714,7 +985,7 @@ let EjsService = class EjsService {
714
985
  }
715
986
  }
716
987
  };
717
- EjsService = __decorate$3([Injectable()], EjsService);
988
+ EjsService = __decorate([Injectable()], EjsService);
718
989
  //#endregion
719
990
  //#region src/puppeteer/engines/eta/eta.service.ts
720
991
  let EtaService = class EtaService {
@@ -783,7 +1054,7 @@ let EtaService = class EtaService {
783
1054
  return this.#templateCache.size;
784
1055
  }
785
1056
  };
786
- EtaService = __decorate$3([Injectable(), __decorateMetadata("design:paramtypes", [])], EtaService);
1057
+ EtaService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [])], EtaService);
787
1058
  //#endregion
788
1059
  //#region src/puppeteer/engines/handlebars/handlebars.service.ts
789
1060
  let HandlebarsService = class HandlebarsService {
@@ -835,7 +1106,7 @@ let HandlebarsService = class HandlebarsService {
835
1106
  }
836
1107
  }
837
1108
  };
838
- HandlebarsService = __decorate$3([Injectable()], HandlebarsService);
1109
+ HandlebarsService = __decorate([Injectable()], HandlebarsService);
839
1110
  //#endregion
840
1111
  //#region src/puppeteer/engines/mjml/mjml.service.ts
841
1112
  let MjmlService = class MjmlService {
@@ -857,7 +1128,7 @@ let MjmlService = class MjmlService {
857
1128
  return await this.render(template, options);
858
1129
  }
859
1130
  };
860
- MjmlService = __decorate$3([Injectable()], MjmlService);
1131
+ MjmlService = __decorate([Injectable()], MjmlService);
861
1132
  //#endregion
862
1133
  //#region src/puppeteer/engines/mustache/mustache.service.ts
863
1134
  let MustacheService = class MustacheService {
@@ -915,7 +1186,7 @@ let MustacheService = class MustacheService {
915
1186
  return this.#templateCache.size;
916
1187
  }
917
1188
  };
918
- MustacheService = __decorate$3([Injectable()], MustacheService);
1189
+ MustacheService = __decorate([Injectable()], MustacheService);
919
1190
  //#endregion
920
1191
  //#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
921
1192
  let NunjucksService = class NunjucksService {
@@ -961,7 +1232,7 @@ let NunjucksService = class NunjucksService {
961
1232
  }
962
1233
  }
963
1234
  };
964
- NunjucksService = __decorate$3([Injectable(), __decorateMetadata("design:paramtypes", [])], NunjucksService);
1235
+ NunjucksService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [])], NunjucksService);
965
1236
  //#endregion
966
1237
  //#region src/puppeteer/engines/pug/pug.service.ts
967
1238
  let PugService = class PugService {
@@ -981,7 +1252,7 @@ let PugService = class PugService {
981
1252
  }
982
1253
  }
983
1254
  };
984
- PugService = __decorate$3([Injectable()], PugService);
1255
+ PugService = __decorate([Injectable()], PugService);
985
1256
  //#endregion
986
1257
  //#region src/puppeteer/libs/requireService.utils.ts
987
1258
  function requireService(service, name) {
@@ -1013,7 +1284,12 @@ let PuppeteerService = class PuppeteerService {
1013
1284
  }
1014
1285
  #limit = pLimit(3);
1015
1286
  async generatePdfFromHtml(html, options) {
1016
- return this.#limit(async () => {
1287
+ const signal = options?.signal ?? this.#options.signal;
1288
+ signal?.throwIfAborted();
1289
+ let started = false;
1290
+ const job = this.#limit(async () => {
1291
+ signal?.throwIfAborted();
1292
+ started = true;
1017
1293
  const mergePuppeteerOptions = mergePuppeteerParameters(this.#options, options);
1018
1294
  if (mergePuppeteerOptions.chromiumRevision !== void 0) Logger.warn("Using `chromiumRevision` is no longer supported since the puppeteer update.");
1019
1295
  const headless = mergePuppeteerOptions.headless ?? true;
@@ -1035,7 +1311,6 @@ let PuppeteerService = class PuppeteerService {
1035
1311
  "--disable-ipc-flooding-protection",
1036
1312
  "--disable-notifications",
1037
1313
  "--disable-offer-store-unmasked-wallet-cards",
1038
- "--disable-popup-blocking",
1039
1314
  "--disable-print-preview",
1040
1315
  "--disable-prompt-on-repost",
1041
1316
  "--disable-renderer-backgrounding",
@@ -1058,9 +1333,18 @@ let PuppeteerService = class PuppeteerService {
1058
1333
  ];
1059
1334
  this.#browserService.markJobStarted();
1060
1335
  let context = null;
1336
+ let closing;
1337
+ const onAbort = () => {
1338
+ if (!context) return;
1339
+ closing = context.close();
1340
+ closing.catch(() => void 0);
1341
+ };
1342
+ signal?.addEventListener("abort", onAbort, { once: true });
1061
1343
  try {
1062
1344
  context = await this.#browserService.createContext(args, headless, executablePath);
1345
+ signal?.throwIfAborted();
1063
1346
  const page = await context.newPage();
1347
+ if (mergePuppeteerOptions.security) await installRequestGuard(context, page, mergePuppeteerOptions.security);
1064
1348
  const pdfOptions = mergePuppeteerOptions.pdfOptions ?? { format: "A4" };
1065
1349
  await page.setContent(html, { waitUntil: "domcontentloaded" });
1066
1350
  await page.emulateMediaType("screen");
@@ -1070,20 +1354,38 @@ let PuppeteerService = class PuppeteerService {
1070
1354
  });
1071
1355
  /* v8 ignore next */
1072
1356
  await page.evaluate(() => document.fonts.ready);
1073
- return await page.pdf(pdfOptions);
1357
+ const pdf = await page.pdf(pdfOptions);
1358
+ signal?.throwIfAborted();
1359
+ return mergePuppeteerOptions.watermark ? await addWatermark(pdf, mergePuppeteerOptions.watermark) : pdf;
1074
1360
  } catch (e) {
1361
+ if (signal?.aborted) throw signal.reason;
1075
1362
  Logger.error(e);
1076
1363
  if (e instanceof NestjsPdfException) throw e;
1077
1364
  throw new PdfGenerationException(`PDF generation failed: ${String(e)}`, { cause: e });
1078
1365
  } finally {
1366
+ signal?.removeEventListener("abort", onAbort);
1079
1367
  if (context) try {
1080
- await context.close();
1368
+ if (closing) await closing;
1369
+ else await context.close();
1081
1370
  } catch (error) {
1082
1371
  Logger.error(error);
1083
1372
  }
1084
1373
  await this.#browserService.markJobFinished();
1085
1374
  }
1086
1375
  });
1376
+ if (!signal) return job;
1377
+ let onQueuedAbort;
1378
+ const abortedWhileQueued = new Promise((_, reject) => {
1379
+ onQueuedAbort = () => {
1380
+ if (!started) reject(signal.reason);
1381
+ };
1382
+ signal.addEventListener("abort", onQueuedAbort, { once: true });
1383
+ });
1384
+ try {
1385
+ return await Promise.race([job, abortedWhileQueued]);
1386
+ } finally {
1387
+ signal.removeEventListener("abort", onQueuedAbort);
1388
+ }
1087
1389
  }
1088
1390
  async generatePdfFromTemplateHbsString(template, parameters = {}, options) {
1089
1391
  const html = requireService(this.#hbsService, "Handlebars").render(template, parameters, options?.hbsOptions ?? this.#options.hbsOptions);
@@ -1142,7 +1444,7 @@ let PuppeteerService = class PuppeteerService {
1142
1444
  return this.generatePdfFromHtml(html, options);
1143
1445
  }
1144
1446
  };
1145
- PuppeteerService = __decorate$3([
1447
+ PuppeteerService = __decorate([
1146
1448
  Injectable(),
1147
1449
  __decorateParam(1, Inject(PDF_PARAMETERS)),
1148
1450
  __decorateParam(2, Optional()),
@@ -1343,1276 +1645,28 @@ let NestjsPdfService = class NestjsPdfService {
1343
1645
  async addSignatureFieldSignatureDebtorRaw(pdf, fieldName = "SignatureDebtor", anchorText = "__SIG_DEBTOR_ANCHOR__") {
1344
1646
  return await addSignatureFieldUsingAnchor(pdf, fieldName, anchorText);
1345
1647
  }
1346
- };
1347
- NestjsPdfService = __decorate$3([Injectable(), __decorateMetadata("design:paramtypes", [typeof PuppeteerService === "undefined" ? Object : PuppeteerService])], NestjsPdfService);
1348
- //#endregion
1349
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/config.constants.js
1350
- var import_main = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
1351
- function _resolveEscapeSequences(value) {
1352
- return value.replace(/\\\$/g, "$");
1353
- }
1354
- function expandValue(value, processEnv, runningParsed) {
1355
- const env = {
1356
- ...runningParsed,
1357
- ...processEnv
1358
- };
1359
- const regex = /(?<!\\)\${([^{}]+)}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
1360
- let result = value;
1361
- let match;
1362
- const seen = /* @__PURE__ */ new Set();
1363
- while ((match = regex.exec(result)) !== null) {
1364
- seen.add(result);
1365
- const [template, bracedExpression, unbracedExpression] = match;
1366
- const expression = bracedExpression || unbracedExpression;
1367
- const opMatch = expression.match(/(:\+|\+|:-|-)/);
1368
- const splitter = opMatch ? opMatch[0] : null;
1369
- const r = expression.split(splitter);
1370
- let defaultValue;
1371
- let value;
1372
- const key = r.shift();
1373
- if ([":+", "+"].includes(splitter)) {
1374
- defaultValue = env[key] ? r.join(splitter) : "";
1375
- value = null;
1376
- } else {
1377
- defaultValue = r.join(splitter);
1378
- value = env[key];
1379
- }
1380
- if (value) {
1381
- if (seen.has(value)) result = result.replace(template, defaultValue);
1382
- else result = result.replace(template, value);
1383
- } else result = result.replace(template, defaultValue);
1384
- if (result === runningParsed[key]) break;
1385
- regex.lastIndex = 0;
1386
- }
1387
- return result;
1388
- }
1389
- function expand(options) {
1390
- const runningParsed = {};
1391
- let processEnv = process.env;
1392
- if (options && options.processEnv != null) processEnv = options.processEnv;
1393
- for (const key in options.parsed) {
1394
- let value = options.parsed[key];
1395
- if (processEnv[key] && processEnv[key] !== value) value = processEnv[key];
1396
- else value = expandValue(value, processEnv, runningParsed);
1397
- options.parsed[key] = _resolveEscapeSequences(value);
1398
- runningParsed[key] = _resolveEscapeSequences(value);
1399
- }
1400
- for (const processKey in options.parsed) processEnv[processKey] = options.parsed[processKey];
1401
- return options;
1402
- }
1403
- module.exports.expand = expand;
1404
- })))();
1405
- /**
1406
- * Injection tokens
1407
- */
1408
- const CONFIGURATION_SERVICE_TOKEN = Symbol("CONFIG_SERVICE");
1409
- const CONFIGURATION_TOKEN = "CONFIGURATION_TOKEN";
1410
- const CONFIGURATION_LOADER = "CONFIGURATION_LOADER";
1411
- const VALIDATED_ENV_LOADER = "VALIDATED_ENV_LOADER";
1412
- const PARTIAL_CONFIGURATION_KEY = "PARTIAL_CONFIGURATION_KEY";
1413
- const VALIDATED_ENV_PROPNAME = "_PROCESS_ENV_VALIDATED";
1414
- //#endregion
1415
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/_internal/isUnsafeProperty.mjs
1416
- /**
1417
- * Checks if a property key is unsafe to access or copy directly.
1418
- *
1419
- * This function is used in functions like `get`, `unset`, and `merge` to prevent
1420
- * prototype pollution attacks by identifying `__proto__`, which modifies the object's
1421
- * prototype chain. `constructor` and `prototype` stay accessible here because lodash
1422
- * keeps reads of them unrestricted; write paths use `isUnsafeToWriteProperty` instead,
1423
- * which also blocks those keys.
1424
- *
1425
- * @param key - The property key to check
1426
- * @returns `true` if the property is unsafe to access directly, `false` otherwise
1427
- * @internal
1428
- */
1429
- function isUnsafeProperty(key) {
1430
- return key === "__proto__";
1431
- }
1432
- //#endregion
1433
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/_internal/isDeepKey.mjs
1434
- /** Matches any deep property path. Examples: `a.b`, `a[0]`, `a["b"]` */
1435
- const regexIsDeepProp$1 = /\.|(\[(?:[^[\]]*|(["'])(?:(?!\2)[^\\]|\\.)*?\2)\])/;
1436
- /**
1437
- * Checks if a given key is a deep key.
1438
- *
1439
- * A deep key is a string that contains a dot (.) or square brackets with a property accessor.
1440
- *
1441
- * @param {PropertyKey} key - The key to check.
1442
- * @returns {boolean} - Returns true if the key is a deep key, otherwise false.
1443
- *
1444
- * Examples:
1445
- *
1446
- * isDeepKey('a.b') // true
1447
- * isDeepKey('a[b]') // true
1448
- * isDeepKey('a') // false
1449
- * isDeepKey(123) // false
1450
- * isDeepKey('a.b.c') // true
1451
- * isDeepKey('a[b][c]') // true
1452
- * isDeepKey('a.') // false
1453
- * isDeepKey('.a') // false
1454
- * isDeepKey('a[b') // false
1455
- * isDeepKey('a]b]') // false
1456
- * isDeepKey('a][b') // false
1457
- * isDeepKey('') // false
1458
- * isDeepKey('a[0]') // true
1459
- *
1460
- */
1461
- function isDeepKey(key) {
1462
- switch (typeof key) {
1463
- case "number":
1464
- case "symbol": return false;
1465
- case "string":
1466
- if (key === "" || key.startsWith(".") || key.endsWith(".")) return false;
1467
- return regexIsDeepProp$1.test(key);
1468
- default: return false;
1469
- }
1470
- }
1471
- //#endregion
1472
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/_internal/toKey.mjs
1473
- /**
1474
- * Converts `value` to a string key if it's not a string or symbol.
1475
- *
1476
- * @private
1477
- * @param {unknown} value The value to inspect.
1478
- * @returns {string|symbol} Returns the key.
1479
- */
1480
- function toKey(value) {
1481
- if (typeof value === "string" || typeof value === "symbol") return value;
1482
- if (Object.is(value?.valueOf?.(), -0)) return "-0";
1483
- return String(value);
1484
- }
1485
- //#endregion
1486
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/util/toString.mjs
1487
- /**
1488
- * Converts `value` to a string.
1489
- *
1490
- * An empty string is returned for `null` and `undefined` values.
1491
- * The sign of `-0` is preserved.
1492
- *
1493
- * @param value - The value to convert.
1494
- * @returns Returns the converted string.
1495
- *
1496
- * @example
1497
- * toString(null) // returns ''
1498
- * toString(undefined) // returns ''
1499
- * toString(-0) // returns '-0'
1500
- * toString([1, 2, -0]) // returns '1,2,-0'
1501
- * toString([Symbol('a'), Symbol('b')]) // returns 'Symbol(a),Symbol(b)'
1502
- */
1503
- function toString(value) {
1504
- if (value == null) return "";
1505
- return baseToString(value);
1506
- }
1507
- function baseToString(value) {
1508
- if (typeof value === "string") return value;
1509
- if (Array.isArray(value)) return value.map(baseToString).join(",");
1510
- const result = String(value);
1511
- if (result === "0" && Object.is(Number(value), -0)) return "-0";
1512
- return result;
1513
- }
1514
- //#endregion
1515
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/util/toPath.mjs
1516
- /**
1517
- * Converts a deep key string into an array of path segments.
1518
- *
1519
- * This function takes a string representing a deep key (e.g., 'a.b.c' or 'a[b][c]') and breaks it down into an array of strings, each representing a segment of the path.
1520
- *
1521
- * @param deepKey - The deep key string to convert.
1522
- * @returns An array of strings, each representing a segment of the path.
1523
- *
1524
- * Examples:
1525
- *
1526
- * toPath('a.b.c') // Returns ['a', 'b', 'c']
1527
- * toPath('a[b][c]') // Returns ['a', 'b', 'c']
1528
- * toPath('.a.b.c') // Returns ['', 'a', 'b', 'c']
1529
- * toPath('a["b.c"].d') // Returns ['a', 'b.c', 'd']
1530
- * toPath('') // Returns []
1531
- * toPath('.a[b].c.d[e]["f.g"].h') // Returns ['', 'a', 'b', 'c', 'd', 'e', 'f.g', 'h']
1532
- */
1533
- function toPath(deepKey) {
1534
- if (Array.isArray(deepKey)) return deepKey.map(toKey);
1535
- if (typeof deepKey === "symbol") return [deepKey];
1536
- deepKey = toString(deepKey);
1537
- const result = [];
1538
- const length = deepKey.length;
1539
- if (length === 0) return result;
1540
- let index = 0;
1541
- let key = "";
1542
- let quoteChar = "";
1543
- let bracket = false;
1544
- let bracketHadQuote = false;
1545
- const bracketNumberRegex = /^-?\d+(?:\.\d+)?$/;
1546
- if (deepKey.charCodeAt(0) === 46) result.push("");
1547
- while (index < length) {
1548
- const char = deepKey[index];
1549
- if (quoteChar) if (char === "\\" && index + 1 < length) {
1550
- index++;
1551
- key += deepKey[index];
1552
- } else if (char === quoteChar) quoteChar = "";
1553
- else key += char;
1554
- else if (bracket) if (char === "\"" || char === "'") {
1555
- quoteChar = char;
1556
- bracketHadQuote = true;
1557
- } else if (char === "]") {
1558
- bracket = false;
1559
- if (!bracketHadQuote && key.includes(".") && !bracketNumberRegex.test(key)) {
1560
- const segments = key.split(".");
1561
- for (let i = 0; i < segments.length; i++) if (segments[i] !== "") result.push(segments[i]);
1562
- } else result.push(key);
1563
- key = "";
1564
- } else key += char;
1565
- else if (char === "[") {
1566
- bracket = true;
1567
- bracketHadQuote = false;
1568
- if (key) {
1569
- result.push(key);
1570
- key = "";
1571
- }
1572
- } else if (char === ".") {
1573
- if (key) {
1574
- result.push(key);
1575
- key = "";
1576
- }
1577
- const next = deepKey[index + 1];
1578
- if (next === void 0 || next === ".") result.push("");
1579
- } else key += char;
1580
- index++;
1581
- }
1582
- if (key) result.push(key);
1583
- return result;
1584
- }
1585
- //#endregion
1586
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/object/get.mjs
1587
- /**
1588
- * Retrieves the value at a given path from an object. If the resolved value is undefined, the defaultValue is returned instead.
1589
- *
1590
- * @param object - The object to query.
1591
- * @param path - The path of the property to get.
1592
- * @param [defaultValue] - The value returned if the resolved value is undefined.
1593
- * @returns Returns the resolved value.
1594
- *
1595
- * @example
1596
- * const object = { a: { b: { c: 1 } } };
1597
- * get(object, 'a.b.c');
1598
- * // => 1
1599
- *
1600
- * get(object, ['a', 'b', 'c']);
1601
- * // => 1
1602
- *
1603
- * get(object, 'a.b.d', 'default');
1604
- * // => 'default'
1605
- */
1606
- function get(object, path, defaultValue) {
1607
- if (object == null) return defaultValue;
1608
- switch (typeof path) {
1609
- case "string": {
1610
- if (isUnsafeProperty(path)) return defaultValue;
1611
- const result = object[path];
1612
- if (result === void 0) if (isDeepKey(path) && !Object.hasOwn(object, path)) return get(object, toPath(path), defaultValue);
1613
- else return defaultValue;
1614
- return result;
1615
- }
1616
- case "number":
1617
- case "symbol": {
1618
- if (typeof path === "number") path = toKey(path);
1619
- const result = object[path];
1620
- if (result === void 0) return defaultValue;
1621
- return result;
1622
- }
1623
- default: {
1624
- if (Array.isArray(path)) return getWithPath(object, path, defaultValue);
1625
- if (Object.is(path?.valueOf(), -0)) path = "-0";
1626
- else path = String(path);
1627
- if (isUnsafeProperty(path)) return defaultValue;
1628
- const result = object[path];
1629
- if (result === void 0) return defaultValue;
1630
- return result;
1631
- }
1632
- }
1633
- }
1634
- function getWithPath(object, path, defaultValue) {
1635
- if (path.length === 0) return defaultValue;
1636
- let current = object;
1637
- for (let index = 0; index < path.length; index++) {
1638
- if (current == null) return defaultValue;
1639
- if (isUnsafeProperty(path[index])) return defaultValue;
1640
- current = current[path[index]];
1641
- }
1642
- if (current === void 0) return defaultValue;
1643
- return current;
1644
- }
1645
- //#endregion
1646
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/_internal/isIndex.mjs
1647
- const IS_UNSIGNED_INTEGER = /^(?:0|[1-9]\d*)$/;
1648
- function isIndex(value, length = Number.MAX_SAFE_INTEGER) {
1649
- switch (typeof value) {
1650
- case "number": return Number.isInteger(value) && value >= 0 && value < length;
1651
- case "symbol": return false;
1652
- case "string": return IS_UNSIGNED_INTEGER.test(value);
1653
- }
1654
- }
1655
- //#endregion
1656
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/_internal/getTag.mjs
1657
- /**
1658
- * Gets the `toStringTag` of `value`.
1659
- *
1660
- * @private
1661
- * @param {T} value The value to query.
1662
- * @returns {string} Returns the `Object.prototype.toString.call` result.
1663
- */
1664
- function getTag(value) {
1665
- if (value == null) return value === void 0 ? "[object Undefined]" : "[object Null]";
1666
- return Object.prototype.toString.call(value);
1667
- }
1668
- //#endregion
1669
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/predicate/isArguments.mjs
1670
- /**
1671
- * Checks if the given value is an arguments object.
1672
- *
1673
- * This function tests whether the provided value is an arguments object or not.
1674
- * It returns `true` if the value is an arguments object, and `false` otherwise.
1675
- *
1676
- * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to an arguments object.
1677
- *
1678
- * @param value - The value to test if it is an arguments object.
1679
- * @returns `true` if the value is an arguments, `false` otherwise.
1680
- *
1681
- * @example
1682
- * const args = (function() { return arguments; })();
1683
- * const strictArgs = (function() { 'use strict'; return arguments; })();
1684
- * const value = [1, 2, 3];
1685
- *
1686
- * console.log(isArguments(args)); // true
1687
- * console.log(isArguments(strictArgs)); // true
1688
- * console.log(isArguments(value)); // false
1689
- */
1690
- function isArguments(value) {
1691
- return value !== null && typeof value === "object" && getTag(value) === "[object Arguments]";
1692
- }
1693
- //#endregion
1694
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/object/has.mjs
1695
- /**
1696
- * Checks if a given path exists within an object.
1697
- *
1698
- * You can provide the path as a single property key, an array of property keys,
1699
- * or a string representing a deep path.
1700
- *
1701
- * If the path is an index and the object is an array or an arguments object, the function will verify
1702
- * if the index is valid and within the bounds of the array or arguments object, even if the array or
1703
- * arguments object is sparse (i.e., not all indexes are defined).
1704
- *
1705
- * @param object - The object to query.
1706
- * @param path - The path to check. This can be a single property key,
1707
- * an array of property keys, or a string representing a deep path.
1708
- * @returns Returns `true` if the path exists in the object, `false` otherwise.
1709
- *
1710
- * @example
1711
- *
1712
- * const obj = { a: { b: { c: 3 } } };
1713
- *
1714
- * has(obj, 'a'); // true
1715
- * has(obj, ['a', 'b']); // true
1716
- * has(obj, ['a', 'b', 'c']); // true
1717
- * has(obj, 'a.b.c'); // true
1718
- * has(obj, 'a.b.d'); // false
1719
- * has(obj, ['a', 'b', 'c', 'd']); // false
1720
- * has([], 0); // false
1721
- * has([1, 2, 3], 2); // true
1722
- * has([1, 2, 3], 5); // false
1723
- */
1724
- function has(object, path) {
1725
- let resolvedPath;
1726
- if (Array.isArray(path)) resolvedPath = path;
1727
- else if (typeof path === "string" && isDeepKey(path) && !(path in Object(object))) resolvedPath = toPath(path);
1728
- else resolvedPath = [path];
1729
- if (resolvedPath.length === 0) return false;
1730
- let current = object;
1731
- for (let i = 0; i < resolvedPath.length; i++) {
1732
- const key = resolvedPath[i];
1733
- if (current == null || !Object.hasOwn(current, key)) {
1734
- if (!((Array.isArray(current) || isArguments(current)) && isIndex(key) && key < current.length)) return false;
1735
- }
1736
- current = current[key];
1737
- }
1738
- return true;
1739
- }
1740
- //#endregion
1741
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/predicate/isObject.mjs
1742
- /**
1743
- * Checks if the given value is an object. An object is a value that is
1744
- * not a primitive type (string, number, boolean, symbol, null, or undefined).
1745
- *
1746
- * This function tests whether the provided value is an object or not.
1747
- * It returns `true` if the value is an object, and `false` otherwise.
1748
- *
1749
- * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to an object value.
1750
- *
1751
- * @param value - The value to check if it is an object.
1752
- * @returns `true` if the value is an object, `false` otherwise.
1753
- *
1754
- * @example
1755
- * const value1 = {};
1756
- * const value2 = [1, 2, 3];
1757
- * const value3 = () => {};
1758
- * const value4 = null;
1759
- *
1760
- * console.log(isObject(value1)); // true
1761
- * console.log(isObject(value2)); // true
1762
- * console.log(isObject(value3)); // true
1763
- * console.log(isObject(value4)); // false
1764
- */
1765
- function isObject$1(value) {
1766
- return value !== null && (typeof value === "object" || typeof value === "function");
1767
- }
1768
- //#endregion
1769
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/predicate/isSymbol.mjs
1770
- /**
1771
- * Check whether a value is a symbol.
1772
- *
1773
- * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `symbol`.
1774
- *
1775
- * @param value The value to check.
1776
- * @returns Returns `true` if `value` is a symbol, else `false`.
1777
- * @example
1778
- * isSymbol(Symbol.iterator);
1779
- * // => true
1780
- *
1781
- * isSymbol('abc');
1782
- * // => false
1783
- */
1784
- function isSymbol(value) {
1785
- return typeof value === "symbol" || value instanceof Symbol;
1786
- }
1787
- //#endregion
1788
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/_internal/isKey.mjs
1789
- /** Matches any deep property path. (e.g. `a.b[0].c`)*/
1790
- const regexIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/;
1791
- /** Matches any word character (alphanumeric & underscore).*/
1792
- const regexIsPlainProp = /^\w*$/;
1793
- /**
1794
- * Checks if `value` is a property name and not a property path. (It's ok that the `value` is not in the keys of the `object`)
1795
- * @param {unknown} value The value to check.
1796
- * @param {unknown} object The object to query.
1797
- * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
1798
- *
1799
- * @example
1800
- * isKey('a', { a: 1 });
1801
- * // => true
1802
- *
1803
- * isKey('a.b', { a: { b: 2 } });
1804
- * // => false
1805
- */
1806
- function isKey(value, object) {
1807
- if (Array.isArray(value)) return false;
1808
- if (typeof value === "number" || typeof value === "boolean" || value == null || isSymbol(value)) return true;
1809
- return typeof value === "string" && (regexIsPlainProp.test(value) || !regexIsDeepProp.test(value)) || object != null && Object.hasOwn(object, value);
1810
- }
1811
- //#endregion
1812
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/util/eq.mjs
1813
- /**
1814
- * Performs a `SameValueZero` comparison between two values to determine if they are equivalent.
1815
- *
1816
- * @param value The value to compare.
1817
- * @param other The other value to compare.
1818
- * @returns Returns `true` if the values are equivalent, else `false`.
1819
- *
1820
- * @example
1821
- * eq(1, 1); // true
1822
- * eq(0, -0); // true
1823
- * eq(NaN, NaN); // true
1824
- * eq('a', Object('a')); // false
1825
- */
1826
- function eq(value, other) {
1827
- return value === other || Number.isNaN(value) && Number.isNaN(other);
1828
- }
1829
- //#endregion
1830
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/_internal/assignValue.mjs
1831
- const assignValue = (object, key, value) => {
1832
- const objValue = object[key];
1833
- if (!(Object.hasOwn(object, key) && eq(objValue, value)) || value === void 0 && !(key in object)) object[key] = value;
1834
- };
1835
- //#endregion
1836
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/_internal/isUnsafeToWriteProperty.mjs
1837
- /**
1838
- * Checks if a property key is unsafe to write to.
1839
- *
1840
- * Writing through `__proto__`, `constructor`, or `prototype` can reach
1841
- * `Object.prototype` and pollute every object, so write paths like `set`,
1842
- * `update`, and `zipObjectDeep` abort when a path segment matches one of
1843
- * these keys, matching lodash's behavior.
1844
- *
1845
- * Read paths like `get` and `unset` use `isUnsafeProperty` instead, which
1846
- * only blocks `__proto__`; lodash keeps reads of `constructor` and
1847
- * `prototype` unrestricted.
1848
- *
1849
- * @param key - The property key to check
1850
- * @returns `true` if the property is unsafe to write to, `false` otherwise
1851
- * @internal
1852
- */
1853
- function isUnsafeToWriteProperty(key) {
1854
- return key === "__proto__" || key === "constructor" || key === "prototype";
1855
- }
1856
- //#endregion
1857
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/object/updateWith.mjs
1858
- /**
1859
- * Updates the value at the specified path of the given object using an updater function and a customizer.
1860
- * If any part of the path does not exist, it will be created.
1861
- *
1862
- * @template T - The type of the object.
1863
- * @template R - The type of the return value.
1864
- * @param obj - The object to modify.
1865
- * @param path - The path of the property to update.
1866
- * @param updater - The function to produce the updated value.
1867
- * @param customizer - The function to customize the update process.
1868
- * @returns The modified object.
1869
- *
1870
- * @example
1871
- * const object = { 'a': [{ 'b': { 'c': 3 } }] };
1872
- * updateWith(object, 'a[0].b.c', (n) => n * n);
1873
- * // => { 'a': [{ 'b': { 'c': 9 } }] }
1874
- */
1875
- function updateWith(obj, path, updater, customizer) {
1876
- if (obj == null && !isObject$1(obj)) return obj;
1877
- let resolvedPath;
1878
- if (isKey(path, obj)) resolvedPath = [path];
1879
- else if (Array.isArray(path)) resolvedPath = path;
1880
- else resolvedPath = toPath(path);
1881
- const updateValue = updater(get(obj, resolvedPath));
1882
- let current = obj;
1883
- for (let i = 0; i < resolvedPath.length && current != null; i++) {
1884
- const key = toKey(resolvedPath[i]);
1885
- if (isUnsafeToWriteProperty(key)) return obj;
1886
- let newValue;
1887
- if (i === resolvedPath.length - 1) newValue = updateValue;
1888
- else {
1889
- const objValue = current[key];
1890
- const customizerResult = customizer?.(objValue, key, obj);
1891
- newValue = customizerResult !== void 0 ? customizerResult : isObject$1(objValue) ? objValue : isIndex(resolvedPath[i + 1]) ? [] : {};
1892
- }
1893
- assignValue(current, key, newValue);
1894
- current = current[key];
1895
- }
1896
- return obj;
1897
- }
1898
- //#endregion
1899
- //#region node_modules/.pnpm/es-toolkit@1.51.0/node_modules/es-toolkit/dist/compat/object/set.mjs
1900
- /**
1901
- * Sets the value at the specified path of the given object. If any part of the path does not exist, it will be created.
1902
- *
1903
- * @template T - The type of the object.
1904
- * @param obj - The object to modify.
1905
- * @param path - The path of the property to set.
1906
- * @param value - The value to set.
1907
- * @returns The modified object.
1908
- *
1909
- * @example
1910
- * // Set a value in a nested object
1911
- * const obj = { a: { b: { c: 3 } } };
1912
- * set(obj, 'a.b.c', 4);
1913
- * console.log(obj.a.b.c); // 4
1914
- *
1915
- * @example
1916
- * // Set a value in an array
1917
- * const arr = [1, 2, 3];
1918
- * set(arr, 1, 4);
1919
- * console.log(arr[1]); // 4
1920
- *
1921
- * @example
1922
- * // Create non-existent path and set value
1923
- * const obj = {};
1924
- * set(obj, 'a.b.c', 4);
1925
- * console.log(obj); // { a: { b: { c: 4 } } }
1926
- */
1927
- function set(obj, path, value) {
1928
- return updateWith(obj, path, () => value, () => void 0);
1929
- }
1930
- //#endregion
1931
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/utils/get-config-token.util.js
1932
- /**
1933
- * @publicApi
1934
- */
1935
- function getConfigToken(token) {
1936
- return `CONFIGURATION(${token.toString()})`;
1937
- }
1938
- //#endregion
1939
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/utils/get-default-parser.util.js
1940
- var import_main$1 = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
1941
- const fs$2 = __require("fs");
1942
- const path = __require("path");
1943
- const os = __require("os");
1944
- const crypto = __require("crypto");
1945
- const TIPS = [
1946
- "◈ encrypted .env [www.dotenvx.com]",
1947
- "◈ secrets for agents [www.dotenvx.com]",
1948
- "⌁ auth for agents [www.vestauth.com]",
1949
- "⌘ custom filepath { path: '/custom/path/.env' }",
1950
- "⌘ enable debugging { debug: true }",
1951
- "⌘ override existing { override: true }",
1952
- "⌘ suppress logs { quiet: true }",
1953
- "⌘ multiple files { path: ['.env.local', '.env'] }"
1954
- ];
1955
- function _getRandomTip() {
1956
- return TIPS[Math.floor(Math.random() * TIPS.length)];
1957
- }
1958
- function parseBoolean(value) {
1959
- if (typeof value === "string") return ![
1960
- "false",
1961
- "0",
1962
- "no",
1963
- "off",
1964
- ""
1965
- ].includes(value.toLowerCase());
1966
- return Boolean(value);
1967
- }
1968
- function supportsAnsi() {
1969
- return process.stdout.isTTY;
1970
- }
1971
- function dim(text) {
1972
- return supportsAnsi() ? `\x1b[2m${text}\x1b[0m` : text;
1973
- }
1974
- const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
1975
- function parse(src) {
1976
- const obj = {};
1977
- let lines = src.toString();
1978
- lines = lines.replace(/\r\n?/gm, "\n");
1979
- let match;
1980
- while ((match = LINE.exec(lines)) != null) {
1981
- const key = match[1];
1982
- let value = match[2] || "";
1983
- value = value.trim();
1984
- const maybeQuote = value[0];
1985
- value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
1986
- if (maybeQuote === "\"") {
1987
- value = value.replace(/\\n/g, "\n");
1988
- value = value.replace(/\\r/g, "\r");
1989
- }
1990
- obj[key] = value;
1991
- }
1992
- return obj;
1993
- }
1994
- function _parseVault(options) {
1995
- options = options || {};
1996
- const vaultPath = _vaultPath(options);
1997
- options.path = vaultPath;
1998
- const result = DotenvModule.configDotenv(options);
1999
- if (!result.parsed) {
2000
- const err = /* @__PURE__ */ new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
2001
- err.code = "MISSING_DATA";
2002
- throw err;
2003
- }
2004
- const keys = _dotenvKey(options).split(",");
2005
- const length = keys.length;
2006
- let decrypted;
2007
- for (let i = 0; i < length; i++) try {
2008
- const attrs = _instructions(result, keys[i].trim());
2009
- decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
2010
- break;
2011
- } catch (error) {
2012
- if (i + 1 >= length) throw error;
2013
- }
2014
- return DotenvModule.parse(decrypted);
2015
- }
2016
- function _warn(message) {
2017
- console.error(`⚠ ${message}`);
2018
- }
2019
- function _debug(message) {
2020
- console.log(`┆ ${message}`);
2021
- }
2022
- function _log(message) {
2023
- console.log(`◇ ${message}`);
2024
- }
2025
- function _dotenvKey(options) {
2026
- if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) return options.DOTENV_KEY;
2027
- if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) return process.env.DOTENV_KEY;
2028
- return "";
2029
- }
2030
- function _instructions(result, dotenvKey) {
2031
- let uri;
2032
- try {
2033
- uri = new URL(dotenvKey);
2034
- } catch (error) {
2035
- if (error.code === "ERR_INVALID_URL") {
2036
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
2037
- err.code = "INVALID_DOTENV_KEY";
2038
- throw err;
2039
- }
2040
- throw error;
2041
- }
2042
- const key = uri.password;
2043
- if (!key) {
2044
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing key part");
2045
- err.code = "INVALID_DOTENV_KEY";
2046
- throw err;
2047
- }
2048
- const environment = uri.searchParams.get("environment");
2049
- if (!environment) {
2050
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: Missing environment part");
2051
- err.code = "INVALID_DOTENV_KEY";
2052
- throw err;
2053
- }
2054
- const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
2055
- const ciphertext = result.parsed[environmentKey];
2056
- if (!ciphertext) {
2057
- const err = /* @__PURE__ */ new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
2058
- err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
2059
- throw err;
2060
- }
2061
- return {
2062
- ciphertext,
2063
- key
2064
- };
2065
- }
2066
- function _vaultPath(options) {
2067
- let possibleVaultPath = null;
2068
- if (options && options.path && options.path.length > 0) {
2069
- if (Array.isArray(options.path)) {
2070
- for (const filepath of options.path) if (fs$2.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
2071
- } else possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
2072
- } else possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
2073
- if (fs$2.existsSync(possibleVaultPath)) return possibleVaultPath;
2074
- return null;
2075
- }
2076
- function _resolveHome(envPath) {
2077
- return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
2078
- }
2079
- function _configVault(options) {
2080
- const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
2081
- const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
2082
- if (debug || !quiet) _log("loading env from encrypted .env.vault");
2083
- const parsed = DotenvModule._parseVault(options);
2084
- let processEnv = process.env;
2085
- if (options && options.processEnv != null) processEnv = options.processEnv;
2086
- DotenvModule.populate(processEnv, parsed, options);
2087
- return { parsed };
2088
- }
2089
- function configDotenv(options) {
2090
- const dotenvPath = path.resolve(process.cwd(), ".env");
2091
- let encoding = "utf8";
2092
- let processEnv = process.env;
2093
- if (options && options.processEnv != null) processEnv = options.processEnv;
2094
- let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
2095
- let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
2096
- if (options && options.encoding) encoding = options.encoding;
2097
- else if (debug) _debug("no encoding is specified (UTF-8 is used by default)");
2098
- let optionPaths = [dotenvPath];
2099
- if (options && options.path) {
2100
- if (!Array.isArray(options.path)) optionPaths = [_resolveHome(options.path)];
2101
- else {
2102
- optionPaths = [];
2103
- for (const filepath of options.path) optionPaths.push(_resolveHome(filepath));
2104
- }
2105
- }
2106
- let lastError;
2107
- const parsedAll = {};
2108
- for (const path of optionPaths) try {
2109
- const parsed = DotenvModule.parse(fs$2.readFileSync(path, { encoding }));
2110
- DotenvModule.populate(parsedAll, parsed, options);
2111
- } catch (e) {
2112
- if (debug) _debug(`failed to load ${path} ${e.message}`);
2113
- lastError = e;
2114
- }
2115
- const populated = DotenvModule.populate(processEnv, parsedAll, options);
2116
- debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
2117
- quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
2118
- if (debug || !quiet) {
2119
- const keysCount = Object.keys(populated).length;
2120
- const shortPaths = [];
2121
- for (const filePath of optionPaths) try {
2122
- const relative = path.relative(process.cwd(), filePath);
2123
- shortPaths.push(relative);
2124
- } catch (e) {
2125
- if (debug) _debug(`failed to load ${filePath} ${e.message}`);
2126
- lastError = e;
2127
- }
2128
- _log(`injected env (${keysCount}) from ${shortPaths.join(",")} ${dim(`// tip: ${_getRandomTip()}`)}`);
2129
- }
2130
- if (lastError) return {
2131
- parsed: parsedAll,
2132
- error: lastError
2133
- };
2134
- else return { parsed: parsedAll };
2135
- }
2136
- function config(options) {
2137
- if (_dotenvKey(options).length === 0) return DotenvModule.configDotenv(options);
2138
- const vaultPath = _vaultPath(options);
2139
- if (!vaultPath) {
2140
- _warn(`you set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}`);
2141
- return DotenvModule.configDotenv(options);
2142
- }
2143
- return DotenvModule._configVault(options);
2144
- }
2145
- function decrypt(encrypted, keyStr) {
2146
- const key = Buffer.from(keyStr.slice(-64), "hex");
2147
- let ciphertext = Buffer.from(encrypted, "base64");
2148
- const nonce = ciphertext.subarray(0, 12);
2149
- const authTag = ciphertext.subarray(-16);
2150
- ciphertext = ciphertext.subarray(12, -16);
2151
- try {
2152
- const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
2153
- aesgcm.setAuthTag(authTag);
2154
- return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
2155
- } catch (error) {
2156
- const isRange = error instanceof RangeError;
2157
- const invalidKeyLength = error.message === "Invalid key length";
2158
- const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
2159
- if (isRange || invalidKeyLength) {
2160
- const err = /* @__PURE__ */ new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
2161
- err.code = "INVALID_DOTENV_KEY";
2162
- throw err;
2163
- } else if (decryptionFailed) {
2164
- const err = /* @__PURE__ */ new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
2165
- err.code = "DECRYPTION_FAILED";
2166
- throw err;
2167
- } else throw error;
2168
- }
2169
- }
2170
- function populate(processEnv, parsed, options = {}) {
2171
- const debug = Boolean(options && options.debug);
2172
- const override = Boolean(options && options.override);
2173
- const populated = {};
2174
- if (typeof parsed !== "object") {
2175
- const err = /* @__PURE__ */ new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
2176
- err.code = "OBJECT_REQUIRED";
2177
- throw err;
2178
- }
2179
- for (const key of Object.keys(parsed)) if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
2180
- if (override === true) {
2181
- processEnv[key] = parsed[key];
2182
- populated[key] = parsed[key];
2183
- }
2184
- if (debug) {
2185
- if (override === true) _debug(`"${key}" is already defined and WAS overwritten`);
2186
- else _debug(`"${key}" is already defined and was NOT overwritten`);
2187
- }
2188
- } else {
2189
- processEnv[key] = parsed[key];
2190
- populated[key] = parsed[key];
2191
- }
2192
- return populated;
2193
- }
2194
- const DotenvModule = {
2195
- configDotenv,
2196
- _configVault,
2197
- _parseVault,
2198
- config,
2199
- decrypt,
2200
- parse,
2201
- populate
2202
- };
2203
- module.exports.configDotenv = DotenvModule.configDotenv;
2204
- module.exports._configVault = DotenvModule._configVault;
2205
- module.exports._parseVault = DotenvModule._parseVault;
2206
- module.exports.config = DotenvModule.config;
2207
- module.exports.decrypt = DotenvModule.decrypt;
2208
- module.exports.parse = DotenvModule.parse;
2209
- module.exports.populate = DotenvModule.populate;
2210
- module.exports = DotenvModule;
2211
- })))(), 1);
2212
- const getDefaultParser = () => import_main$1.parse;
2213
- //#endregion
2214
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/config.service.js
2215
- var __decorate$2 = function(decorators, target, key, desc) {
2216
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2217
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2218
- 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;
2219
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2220
- };
2221
- var __metadata = function(k, v) {
2222
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
2223
- };
2224
- var __param = function(paramIndex, decorator) {
2225
- return function(target, key) {
2226
- decorator(target, key, paramIndex);
2227
- };
2228
- };
2229
- /**
2230
- * @publicApi
2231
- */
2232
- let ConfigService = class ConfigService {
2233
- set isCacheEnabled(value) {
2234
- this._isCacheEnabled = value;
2235
- }
2236
- get isCacheEnabled() {
2237
- return this._isCacheEnabled;
2238
- }
2239
- set skipProcessEnv(value) {
2240
- this._skipProcessEnv = value;
2241
- }
2242
- get skipProcessEnv() {
2243
- return this._skipProcessEnv;
2244
- }
2245
- constructor(internalConfig = {}) {
2246
- this.internalConfig = internalConfig;
2247
- this.cache = {};
2248
- this._changes$ = new Subject();
2249
- this._skipProcessEnv = false;
2250
- this._isCacheEnabled = false;
2251
- this.envFilePaths = [];
2252
- this.parser = getDefaultParser();
2253
- }
2254
- /**
2255
- * Returns a stream of configuration changes.
2256
- * Each event contains the attribute path, the old value and the new value.
2257
- */
2258
- get changes$() {
2259
- return this._changes$.asObservable();
2260
- }
2261
- /**
2262
- * Get a configuration value (either custom configuration or process environment variable)
2263
- * based on property path (you can use dot notation to traverse nested object, e.g. "database.host").
2264
- * It returns a default value if the key does not exist.
2265
- * @param propertyPath
2266
- * @param defaultValueOrOptions
2267
- */
2268
- get(propertyPath, defaultValueOrOptions, options) {
2269
- const internalValue = this.getFromInternalConfig(propertyPath);
2270
- if (!isUndefined(internalValue)) return internalValue;
2271
- const validatedEnvValue = this.getFromValidatedEnv(propertyPath);
2272
- if (!isUndefined(validatedEnvValue)) return validatedEnvValue;
2273
- const defaultValue = this.isGetOptionsObject(defaultValueOrOptions) && !options ? void 0 : defaultValueOrOptions;
2274
- if (!this._skipProcessEnv) {
2275
- const processEnvValue = this.getFromProcessEnv(propertyPath, defaultValue);
2276
- if (!isUndefined(processEnvValue)) return processEnvValue;
2277
- }
2278
- return defaultValue;
2279
- }
2280
- /**
2281
- * Get a configuration value (either custom configuration or process environment variable)
2282
- * based on property path (you can use dot notation to traverse nested object, e.g. "database.host").
2283
- * It returns a default value if the key does not exist.
2284
- * If the default value is undefined an exception will be thrown.
2285
- * @param propertyPath
2286
- * @param defaultValueOrOptions
2287
- */
2288
- getOrThrow(propertyPath, defaultValueOrOptions, options) {
2289
- const value = this.get(propertyPath, defaultValueOrOptions, options);
2290
- if (isUndefined(value)) throw new TypeError(`Configuration key "${propertyPath.toString()}" does not exist`);
2291
- return value;
2292
- }
2293
- /**
2294
- * Sets a configuration value based on property path.
2295
- * @param propertyPath
2296
- * @param value
2297
- */
2298
- set(propertyPath, value) {
2299
- const oldValue = this.get(propertyPath);
2300
- set(this.internalConfig, propertyPath, value);
2301
- if (typeof propertyPath === "string") {
2302
- process.env[propertyPath] = String(value);
2303
- this.updateInterpolatedEnv(propertyPath, String(value));
2304
- }
2305
- if (this.isCacheEnabled) this.setInCacheIfDefined(propertyPath, value);
2306
- this._changes$.next({
2307
- path: propertyPath,
2308
- oldValue,
2309
- newValue: value
2310
- });
2311
- }
2312
- /**
2313
- * Sets env file paths from `config.module.ts` to parse.
2314
- * @param paths
2315
- */
2316
- setEnvFilePaths(paths) {
2317
- this.envFilePaths = paths;
2318
- }
2319
- /**
2320
- * Sets parser from `config.module.ts`.
2321
- * @param parser
2322
- */
2323
- setParser(parser) {
2324
- this.parser = parser;
2325
- }
2326
- getFromCache(propertyPath, defaultValue) {
2327
- const cachedValue = get(this.cache, propertyPath);
2328
- return isUndefined(cachedValue) ? defaultValue : cachedValue;
2329
- }
2330
- getFromValidatedEnv(propertyPath) {
2331
- return get(this.internalConfig[VALIDATED_ENV_PROPNAME], propertyPath);
2332
- }
2333
- getFromProcessEnv(propertyPath, defaultValue) {
2334
- if (this.isCacheEnabled && has(this.cache, propertyPath)) {
2335
- const cachedValue = this.getFromCache(propertyPath, defaultValue);
2336
- return !isUndefined(cachedValue) ? cachedValue : defaultValue;
2337
- }
2338
- const processValue = get(process.env, propertyPath);
2339
- this.setInCacheIfDefined(propertyPath, processValue);
2340
- return processValue;
2341
- }
2342
- getFromInternalConfig(propertyPath) {
2343
- return get(this.internalConfig, propertyPath);
2344
- }
2345
- setInCacheIfDefined(propertyPath, value) {
2346
- if (typeof value === "undefined") return;
2347
- set(this.cache, propertyPath, value);
2348
- }
2349
- isGetOptionsObject(options) {
2350
- return options && options?.infer && Object.keys(options).length === 1;
2351
- }
2352
- updateInterpolatedEnv(propertyPath, value) {
2353
- let config = {};
2354
- for (const envFilePath of this.envFilePaths) if (fs.existsSync(envFilePath)) config = Object.assign(this.parser(fs.readFileSync(envFilePath)), config);
2355
- const regex = new RegExp(`\\$\\{?${propertyPath}\\}?`, "g");
2356
- for (const [k, v] of Object.entries(config)) if (regex.test(v)) process.env[k] = v.replace(regex, value);
2357
- }
2358
- };
2359
- ConfigService = __decorate$2([
2360
- Injectable(),
2361
- __param(0, Optional()),
2362
- __param(0, Inject(CONFIGURATION_TOKEN)),
2363
- __metadata("design:paramtypes", [Object])
2364
- ], ConfigService);
2365
- //#endregion
2366
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/config-host.module.js
2367
- var __decorate$1 = function(decorators, target, key, desc) {
2368
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2369
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2370
- 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;
2371
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2372
- };
2373
- /**
2374
- * @publicApi
2375
- */
2376
- let ConfigHostModule = class ConfigHostModule {};
2377
- ConfigHostModule = __decorate$1([Global(), Module({
2378
- providers: [{
2379
- provide: CONFIGURATION_TOKEN,
2380
- useFactory: () => ({})
2381
- }, {
2382
- provide: CONFIGURATION_SERVICE_TOKEN,
2383
- useClass: ConfigService
2384
- }],
2385
- exports: [CONFIGURATION_TOKEN, CONFIGURATION_SERVICE_TOKEN]
2386
- })], ConfigHostModule);
2387
- //#endregion
2388
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/utils/create-config-factory.util.js
2389
- /**
2390
- * @publicApi
2391
- */
2392
- function createConfigProvider(factory) {
2393
- return {
2394
- provide: factory.KEY || getConfigToken(randomUUID()),
2395
- useFactory: factory,
2396
- inject: []
2397
- };
2398
- }
2399
- //#endregion
2400
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/utils/get-registration-token.util.js
2401
- /**
2402
- * @publicApi
2403
- */
2404
- function getRegistrationToken(config) {
2405
- return config[PARTIAL_CONFIGURATION_KEY];
2406
- }
2407
- //#endregion
2408
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/utils/merge-configs.util.js
2409
- /**
2410
- * @publicApi
2411
- */
2412
- function mergeConfigObject(host, partial, token) {
2413
- if (token) {
2414
- set(host, token, partial);
2415
- return partial;
2416
- }
2417
- Object.assign(host, partial);
2418
- }
2419
- //#endregion
2420
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/utils/validate-with-schema.util.js
2421
- /**
2422
- * Joi defaults to `allowUnknown: false` and `abortEarly: true`, which would
2423
- * reject the unrelated variables that are always present in `process.env` and
2424
- * report only the first failure. Previous versions of this package overrode
2425
- * both, so they remain the defaults for Joi schemas unless the user opts out.
2426
- */
2427
- const JOI_DEFAULT_LIBRARY_OPTIONS = {
2428
- abortEarly: false,
2429
- allowUnknown: true
2430
- };
2431
- /**
2432
- * Validates config using a Standard Schema (e.g. Zod, Arktype).
2433
- * @see https://standardschema.dev/
2434
- */
2435
- async function validateWithStandardSchema(schema, config, options) {
2436
- const result = await schema["~standard"].validate(config, getLibraryOptions(schema, options));
2437
- if (result.issues) return {
2438
- error: new Error(formatIssues(result.issues)),
2439
- value: config
2440
- };
2441
- return { value: result.value };
2442
- }
2443
- function getLibraryOptions(schema, options) {
2444
- if (schema["~standard"].vendor !== "joi") return options;
2445
- return {
2446
- ...options,
2447
- libraryOptions: {
2448
- ...JOI_DEFAULT_LIBRARY_OPTIONS,
2449
- ...options?.libraryOptions
2450
- }
2451
- };
2452
- }
2453
- function formatIssues(issues) {
2454
- return issues.map((issue) => {
2455
- const path = formatIssuePath(issue.path);
2456
- return path ? `${path}: ${issue.message}` : issue.message;
2457
- }).join("\n");
2458
- }
2459
- function formatIssuePath(path) {
2460
- return (path ?? []).map((segment) => typeof segment === "object" && segment !== null ? String(segment.key) : String(segment)).join(".");
2461
- }
2462
- //#endregion
2463
- //#region node_modules/.pnpm/@nestjs+config@12.0.0_@nestjs+common@12.0.1_reflect-metadata@0.2.2_rxjs@7.8.2_supports-color@8.1.1__rxjs@7.8.2/node_modules/@nestjs/config/dist/config.module.js
2464
- var __decorate = function(decorators, target, key, desc) {
2465
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2466
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
2467
- 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;
2468
- return c > 3 && r && Object.defineProperty(target, key, r), r;
2469
- };
2470
- var ConfigModule_1;
2471
- /**
2472
- * @publicApi
2473
- */
2474
- let ConfigModule = ConfigModule_1 = class ConfigModule {
2475
- /**
2476
- * This promise resolves when parser completes loading environment variables.
2477
- * When "ignoreEnvFile" is set to true, then it will resolve immediately after the
2478
- * "ConfigModule#forRoot" method is called.
2479
- */
2480
- static get envVariablesLoaded() {
2481
- return this._envVariablesLoaded;
2482
- }
2483
1648
  /**
2484
- * Loads environment variables based on the "ignoreEnvFile" flag and "envFilePath" value.
2485
- * Additionally, registers custom configurations globally.
2486
- * @param options
2487
- */
2488
- static async forRoot(options = {}) {
2489
- const envFilePaths = Array.isArray(options.envFilePath) ? options.envFilePath : [options.envFilePath || resolve$1(process.cwd(), ".env")];
2490
- const parser = options.parser ?? getDefaultParser();
2491
- let validatedEnvConfig = void 0;
2492
- let config = options.ignoreEnvFile ? {} : this.loadEnvFile(envFilePaths, parser, options);
2493
- if (!options.ignoreEnvVars && options.validatePredefined !== false) config = options.override ? {
2494
- ...process.env,
2495
- ...config
2496
- } : {
2497
- ...config,
2498
- ...process.env
2499
- };
2500
- if (options.validate) {
2501
- const validatedConfig = options.validate(config);
2502
- validatedEnvConfig = validatedConfig;
2503
- this.assignVariablesToProcess(validatedConfig, options.override);
2504
- } else if (options.validationSchema) {
2505
- const { error, value: validatedConfig } = await validateWithStandardSchema(options.validationSchema, config, options.validationOptions);
2506
- if (error) throw new Error(`Config validation error: ${error.message}`);
2507
- validatedEnvConfig = {
2508
- ...config,
2509
- ...validatedConfig
2510
- };
2511
- this.assignVariablesToProcess(validatedEnvConfig, options.override);
2512
- } else this.assignVariablesToProcess(config, options.override);
2513
- const isConfigToLoad = options.load && options.load.length;
2514
- const providers = (await Promise.all(options.load || [])).map((factory) => createConfigProvider(factory)).filter((item) => item);
2515
- const configProviderTokens = providers.map((item) => item.provide);
2516
- const configServiceProvider = {
2517
- provide: ConfigService,
2518
- useFactory: (configService) => {
2519
- const untypedConfigService = configService;
2520
- if (options.cache) untypedConfigService.isCacheEnabled = true;
2521
- if (options.skipProcessEnv) untypedConfigService.skipProcessEnv = true;
2522
- configService.setEnvFilePaths(envFilePaths);
2523
- configService.setParser(parser);
2524
- return configService;
2525
- },
2526
- inject: [CONFIGURATION_SERVICE_TOKEN, ...configProviderTokens]
2527
- };
2528
- providers.push(configServiceProvider);
2529
- if (validatedEnvConfig) {
2530
- const validatedEnvConfigLoader = {
2531
- provide: VALIDATED_ENV_LOADER,
2532
- useFactory: (host) => {
2533
- host[VALIDATED_ENV_PROPNAME] = validatedEnvConfig;
2534
- },
2535
- inject: [CONFIGURATION_TOKEN]
2536
- };
2537
- providers.push(validatedEnvConfigLoader);
2538
- }
2539
- this.environmentVariablesLoadedSignal();
2540
- return {
2541
- module: ConfigModule_1,
2542
- global: options.isGlobal,
2543
- providers: isConfigToLoad ? [...providers, {
2544
- provide: CONFIGURATION_LOADER,
2545
- useFactory: (host, ...configurations) => {
2546
- configurations.forEach((item, index) => this.mergePartial(host, item, providers[index]));
2547
- },
2548
- inject: [CONFIGURATION_TOKEN, ...configProviderTokens]
2549
- }] : providers,
2550
- exports: [ConfigService, ...configProviderTokens]
2551
- };
2552
- }
2553
- /**
2554
- * Registers configuration object (partial registration).
2555
- * @param config
1649
+ * @param pdf The PDF bytes to modify
1650
+ * @param options Watermark options (`text` or `image` is required)
1651
+ * @returns Modified PDF with the watermark stamped on the selected pages
1652
+ * @description Stamps a text or image watermark on an existing PDF. By default the mark is centered, rotated by 45° at 15% opacity on every page. Use `position: 'tile'` to repeat it across the page and `pages` to target specific pages (1-based). To watermark a PDF while generating it, pass the same options as `watermark` in the `PuppeteerParameters`.
1653
+ *
1654
+ * ```typescript
1655
+ * const watermarked = await pdfService.addWatermark(pdf, {
1656
+ * text: 'CONFIDENTIAL',
1657
+ * color: '#ff0000',
1658
+ * opacity: 0.2,
1659
+ * });
1660
+ * ```
1661
+ *
1662
+ * Text uses the PDF standard fonts, which only support WinAnsi characters; use an `image` for anything else.
1663
+ * @throws WatermarkException when the options are invalid or the PDF cannot be processed
2556
1664
  */
2557
- static forFeature(config) {
2558
- const configProvider = createConfigProvider(config);
2559
- const serviceProvider = {
2560
- provide: ConfigService,
2561
- useFactory: (configService) => configService,
2562
- inject: [CONFIGURATION_SERVICE_TOKEN, configProvider.provide]
2563
- };
2564
- return {
2565
- module: ConfigModule_1,
2566
- providers: [
2567
- configProvider,
2568
- serviceProvider,
2569
- {
2570
- provide: CONFIGURATION_LOADER,
2571
- useFactory: (host, partialConfig) => {
2572
- this.mergePartial(host, partialConfig, configProvider);
2573
- },
2574
- inject: [CONFIGURATION_TOKEN, configProvider.provide]
2575
- }
2576
- ],
2577
- exports: [ConfigService, configProvider.provide]
2578
- };
2579
- }
2580
- static loadEnvFile(envFilePaths, parser, options) {
2581
- let config = {};
2582
- for (const envFilePath of envFilePaths) if (fs$1.existsSync(envFilePath)) {
2583
- config = Object.assign(parser(fs$1.readFileSync(envFilePath)), config);
2584
- if (options.expandVariables) {
2585
- const expandOptions = typeof options.expandVariables === "object" ? options.expandVariables : {};
2586
- config = (0, import_main.expand)({
2587
- ...expandOptions,
2588
- parsed: config
2589
- }).parsed || config;
2590
- }
2591
- }
2592
- return config;
2593
- }
2594
- static assignVariablesToProcess(config, override) {
2595
- if (!isObject(config)) return;
2596
- (override ? Object.keys(config) : Object.keys(config).filter((key) => !(key in process.env))).forEach((key) => {
2597
- const value = config[key];
2598
- if (typeof value === "string") process.env[key] = value;
2599
- else if (typeof value === "boolean" || typeof value === "number") process.env[key] = `${value}`;
2600
- });
2601
- }
2602
- static mergePartial(host, item, provider) {
2603
- const factoryRef = provider.useFactory;
2604
- mergeConfigObject(host, item, getRegistrationToken(factoryRef));
1665
+ async addWatermark(pdf, options) {
1666
+ return await addWatermark(pdf, options);
2605
1667
  }
2606
1668
  };
2607
- ConfigModule._envVariablesLoaded = new Promise((resolve) => ConfigModule_1.environmentVariablesLoadedSignal = resolve);
2608
- ConfigModule = ConfigModule_1 = __decorate([Module({
2609
- imports: [ConfigHostModule],
2610
- providers: [{
2611
- provide: ConfigService,
2612
- useExisting: CONFIGURATION_SERVICE_TOKEN
2613
- }],
2614
- exports: [ConfigHostModule, ConfigService]
2615
- })], ConfigModule);
1669
+ NestjsPdfService = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [typeof PuppeteerService === "undefined" ? Object : PuppeteerService])], NestjsPdfService);
2616
1670
  //#endregion
2617
1671
  //#region src/puppeteer/puppeteer.module.ts
2618
1672
  var _PuppeteerModule;
@@ -2627,23 +1681,21 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
2627
1681
  if (!this.#pdfParams.executablePath) await this.#browserService.install(this.#pdfParams.useLockedBrowser ?? false);
2628
1682
  }
2629
1683
  static forRoot(pdfParameters) {
2630
- const providers = [
2631
- {
2632
- provide: PDF_PARAMETERS,
2633
- useValue: pdfParameters
2634
- },
2635
- HandlebarsService,
2636
- MjmlService,
2637
- PugService,
2638
- EjsService,
2639
- NunjucksService,
2640
- EtaService,
2641
- MustacheService
2642
- ];
2643
1684
  return {
2644
1685
  module: _PuppeteerModule,
2645
- imports: [ConfigModule.forRoot()],
2646
- providers,
1686
+ providers: [
1687
+ {
1688
+ provide: PDF_PARAMETERS,
1689
+ useValue: pdfParameters
1690
+ },
1691
+ HandlebarsService,
1692
+ MjmlService,
1693
+ PugService,
1694
+ EjsService,
1695
+ NunjucksService,
1696
+ EtaService,
1697
+ MustacheService
1698
+ ],
2647
1699
  exports: [
2648
1700
  PuppeteerService,
2649
1701
  MjmlService,
@@ -2663,7 +1715,7 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
2663
1715
  };
2664
1716
  return {
2665
1717
  module: _PuppeteerModule,
2666
- imports: [...options.imports ?? [], ConfigModule.forRoot()],
1718
+ imports: options.imports ?? [],
2667
1719
  providers: [
2668
1720
  pdfParamsProvider,
2669
1721
  PuppeteerService,
@@ -2688,7 +1740,7 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
2688
1740
  };
2689
1741
  }
2690
1742
  };
2691
- PuppeteerModule = _PuppeteerModule = __decorate$3([
1743
+ PuppeteerModule = _PuppeteerModule = __decorate([
2692
1744
  Module({
2693
1745
  providers: [
2694
1746
  PuppeteerService,
@@ -2734,8 +1786,8 @@ let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
2734
1786
  };
2735
1787
  }
2736
1788
  };
2737
- NestjsPdfModule = _NestjsPdfModule = __decorate$3([Module({})], NestjsPdfModule);
1789
+ NestjsPdfModule = _NestjsPdfModule = __decorate([Module({})], NestjsPdfModule);
2738
1790
  //#endregion
2739
- export { BrowserInstallationException, BrowserUnavailableException, EjsService, EngineNotAvailableException, EtaService, HandlebarsService, MjmlService, MustacheService, NestjsPdfErrorCode, NestjsPdfException, NestjsPdfModule, NestjsPdfService, NunjucksService, PdfGenerationException, PugService, PuppeteerModule, PuppeteerService, SignatureDependencyException, SignaturePlacementException, TemplateConfigurationException, TemplateRenderException, getRelativePathToValue };
1791
+ export { BrowserInstallationException, BrowserUnavailableException, EjsService, EngineNotAvailableException, EtaService, HandlebarsService, MjmlService, MustacheService, NestjsPdfErrorCode, NestjsPdfException, NestjsPdfModule, NestjsPdfService, NunjucksService, PdfGenerationException, PugService, PuppeteerModule, PuppeteerService, SignatureDependencyException, SignaturePlacementException, TemplateConfigurationException, TemplateRenderException, WatermarkException, getRelativePathToValue };
2740
1792
 
2741
1793
  //# sourceMappingURL=index.mjs.map