@shad0wz7/nestjs-pdf 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/index.cjs +310 -202
- package/dist/index.d.cts +93 -70
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +93 -70
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +301 -203
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -17
package/dist/index.mjs
CHANGED
|
@@ -43,6 +43,73 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
43
43
|
}) : target, mod));
|
|
44
44
|
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
45
45
|
//#endregion
|
|
46
|
+
//#region src/exceptions/nestjs-pdf.exception.ts
|
|
47
|
+
let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
|
|
48
|
+
NestjsPdfErrorCode["ENGINE_NOT_AVAILABLE"] = "ENGINE_NOT_AVAILABLE";
|
|
49
|
+
NestjsPdfErrorCode["TEMPLATE_CONFIGURATION_ERROR"] = "TEMPLATE_CONFIGURATION_ERROR";
|
|
50
|
+
NestjsPdfErrorCode["TEMPLATE_RENDER_ERROR"] = "TEMPLATE_RENDER_ERROR";
|
|
51
|
+
NestjsPdfErrorCode["BROWSER_INSTALLATION_ERROR"] = "BROWSER_INSTALLATION_ERROR";
|
|
52
|
+
NestjsPdfErrorCode["BROWSER_UNAVAILABLE"] = "BROWSER_UNAVAILABLE";
|
|
53
|
+
NestjsPdfErrorCode["PDF_GENERATION_ERROR"] = "PDF_GENERATION_ERROR";
|
|
54
|
+
NestjsPdfErrorCode["SIGNATURE_DEPENDENCY_ERROR"] = "SIGNATURE_DEPENDENCY_ERROR";
|
|
55
|
+
NestjsPdfErrorCode["SIGNATURE_PLACEMENT_ERROR"] = "SIGNATURE_PLACEMENT_ERROR";
|
|
56
|
+
return NestjsPdfErrorCode;
|
|
57
|
+
}({});
|
|
58
|
+
var NestjsPdfException = class extends Error {
|
|
59
|
+
constructor(message, options) {
|
|
60
|
+
super(message, options);
|
|
61
|
+
this.name = this.constructor.name;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/exceptions/browser-installation.exception.ts
|
|
66
|
+
var BrowserInstallationException = class extends NestjsPdfException {
|
|
67
|
+
code = "BROWSER_INSTALLATION_ERROR";
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/exceptions/browser-unavailable.exception.ts
|
|
71
|
+
var BrowserUnavailableException = class extends NestjsPdfException {
|
|
72
|
+
code = "BROWSER_UNAVAILABLE";
|
|
73
|
+
};
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/exceptions/engine-not-available.exception.ts
|
|
76
|
+
var EngineNotAvailableException = class extends NestjsPdfException {
|
|
77
|
+
code = "ENGINE_NOT_AVAILABLE";
|
|
78
|
+
constructor(engineName) {
|
|
79
|
+
super(`${engineName} service is not available. If the problem persists, open an issue in the repo.`);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/exceptions/pdf-generation.exception.ts
|
|
84
|
+
var PdfGenerationException = class extends NestjsPdfException {
|
|
85
|
+
code = "PDF_GENERATION_ERROR";
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/exceptions/signature-dependency.exception.ts
|
|
89
|
+
var SignatureDependencyException = class extends NestjsPdfException {
|
|
90
|
+
code = "SIGNATURE_DEPENDENCY_ERROR";
|
|
91
|
+
};
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/exceptions/signature-placement.exception.ts
|
|
94
|
+
var SignaturePlacementException = class extends NestjsPdfException {
|
|
95
|
+
code = "SIGNATURE_PLACEMENT_ERROR";
|
|
96
|
+
};
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/exceptions/template-configuration.exception.ts
|
|
99
|
+
var TemplateConfigurationException = class extends NestjsPdfException {
|
|
100
|
+
code = "TEMPLATE_CONFIGURATION_ERROR";
|
|
101
|
+
};
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/exceptions/template-render.exception.ts
|
|
104
|
+
var TemplateRenderException = class extends NestjsPdfException {
|
|
105
|
+
engine;
|
|
106
|
+
code = "TEMPLATE_RENDER_ERROR";
|
|
107
|
+
constructor(engine, message, options) {
|
|
108
|
+
super(message, options);
|
|
109
|
+
this.engine = engine;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
//#endregion
|
|
46
113
|
//#region src/helpers/getRelativePath.helper.ts
|
|
47
114
|
/**
|
|
48
115
|
* Get the relative path to a value from the module directory.
|
|
@@ -65,7 +132,7 @@ async function loadPdfjs() {
|
|
|
65
132
|
pdfjsPromise = await import("pdfjs-dist/legacy/build/pdf.mjs");
|
|
66
133
|
} catch (error) {
|
|
67
134
|
pdfjsPromise = void 0;
|
|
68
|
-
throw new
|
|
135
|
+
throw new SignatureDependencyException([
|
|
69
136
|
"Failed to load pdfjs-dist.",
|
|
70
137
|
"If you use anchor-based signature placement in Node.js, make sure @napi-rs/canvas is installed.",
|
|
71
138
|
"Try: npm install @napi-rs/canvas",
|
|
@@ -111,7 +178,6 @@ function addSignatureFieldAt(pdfDoc, pageIndex, opts) {
|
|
|
111
178
|
const { fieldName, x, y, width, height } = opts;
|
|
112
179
|
const context = pdfDoc.context;
|
|
113
180
|
const page = pdfDoc.getPages()[pageIndex];
|
|
114
|
-
if (!page) throw new Error(`Page ${pageIndex} not found`);
|
|
115
181
|
const rectArray = context.obj([
|
|
116
182
|
PDFNumber.of(x),
|
|
117
183
|
PDFNumber.of(y),
|
|
@@ -168,7 +234,9 @@ async function addSignatureFieldUsingAnchor(pdf, fieldName = "SignatureDebtor",
|
|
|
168
234
|
const sigHeight = 50;
|
|
169
235
|
if (anchor) {
|
|
170
236
|
const pageIndex = anchor.pageIndex;
|
|
171
|
-
const
|
|
237
|
+
const page = pdfDoc.getPages()[pageIndex];
|
|
238
|
+
if (!page) throw new SignaturePlacementException(`Page ${pageIndex} not found`);
|
|
239
|
+
const { width: pw, height: ph } = page.getSize();
|
|
172
240
|
const padX = 40;
|
|
173
241
|
const padY = 7;
|
|
174
242
|
let x = anchor.x - sigWidth / 2 + padX;
|
|
@@ -186,7 +254,10 @@ async function addSignatureFieldUsingAnchor(pdf, fieldName = "SignatureDebtor",
|
|
|
186
254
|
} else {
|
|
187
255
|
const pages = pdfDoc.getPages();
|
|
188
256
|
const pageIndex = pages.length - 1;
|
|
189
|
-
const
|
|
257
|
+
const page = pages.at(-1);
|
|
258
|
+
/* v8 ignore next -- pdf-lib always produces at least one page on save/load; only a hand-crafted, malformed PDF could hit this */
|
|
259
|
+
if (!page) throw new SignaturePlacementException(`Page ${pageIndex} not found`);
|
|
260
|
+
const { width: pageWidth } = page.getSize();
|
|
190
261
|
addSignatureFieldAt(pdfDoc, pageIndex, {
|
|
191
262
|
fieldName,
|
|
192
263
|
x: (pageWidth - sigWidth) / 2,
|
|
@@ -334,19 +405,19 @@ function mergePuppeteerParameters(defaults, overrides) {
|
|
|
334
405
|
//#region src/helpers/tokens.ts
|
|
335
406
|
const PDF_PARAMETERS = "PDF_PARAMETERS";
|
|
336
407
|
//#endregion
|
|
337
|
-
//#region \0@oxc-project+runtime@0.
|
|
408
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateMetadata.js
|
|
338
409
|
function __decorateMetadata(k, v) {
|
|
339
410
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
340
411
|
}
|
|
341
412
|
//#endregion
|
|
342
|
-
//#region \0@oxc-project+runtime@0.
|
|
413
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
|
|
343
414
|
function __decorateParam(paramIndex, decorator) {
|
|
344
415
|
return function(target, key) {
|
|
345
416
|
decorator(target, key, paramIndex);
|
|
346
417
|
};
|
|
347
418
|
}
|
|
348
419
|
//#endregion
|
|
349
|
-
//#region \0@oxc-project+runtime@0.
|
|
420
|
+
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
|
|
350
421
|
function __decorate$3(decorators, target, key, desc) {
|
|
351
422
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
352
423
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -376,47 +447,47 @@ function isTargetClosedError(error) {
|
|
|
376
447
|
return error.name === "TargetCloseError" || error.message.includes("Target closed") || error.message.includes("Target.createTarget");
|
|
377
448
|
}
|
|
378
449
|
let BrowserService = class BrowserService {
|
|
379
|
-
cacheDir;
|
|
380
|
-
options;
|
|
381
|
-
|
|
382
|
-
browser;
|
|
450
|
+
#cacheDir;
|
|
451
|
+
#options;
|
|
452
|
+
#browserInstance = null;
|
|
453
|
+
#browser;
|
|
383
454
|
activeJobs = 0;
|
|
384
455
|
totalJobs = 0;
|
|
385
|
-
recycleRequested = false;
|
|
386
|
-
recycling = false;
|
|
387
|
-
shuttingDown = false;
|
|
456
|
+
#recycleRequested = false;
|
|
457
|
+
#recycling = false;
|
|
458
|
+
#shuttingDown = false;
|
|
388
459
|
/** Max time to wait for in-flight PDF jobs to finish before closing the browser on shutdown. */
|
|
389
460
|
shutdownDrainTimeoutMs = 15e3;
|
|
390
|
-
browserTag;
|
|
391
|
-
useLockedBrowser;
|
|
392
|
-
buildId;
|
|
461
|
+
#browserTag;
|
|
462
|
+
#useLockedBrowser;
|
|
463
|
+
#buildId;
|
|
393
464
|
constructor(pdfParams) {
|
|
394
|
-
this
|
|
395
|
-
this
|
|
396
|
-
this
|
|
397
|
-
this
|
|
398
|
-
this
|
|
399
|
-
this
|
|
465
|
+
this.#cacheDir = resolve(".cache/puppeteer-browser");
|
|
466
|
+
this.#options = pdfParams;
|
|
467
|
+
this.#loadBuildId();
|
|
468
|
+
this.#loadBrowser();
|
|
469
|
+
this.#loadBrowserTag();
|
|
470
|
+
this.#loadUseLockedBrowser();
|
|
400
471
|
}
|
|
401
472
|
async onModuleDestroy() {
|
|
402
|
-
this
|
|
403
|
-
await this
|
|
404
|
-
if (this
|
|
405
|
-
await this.
|
|
473
|
+
this.#shuttingDown = true;
|
|
474
|
+
await this.#waitForIdle(this.shutdownDrainTimeoutMs);
|
|
475
|
+
if (this.#browserInstance?.connected) try {
|
|
476
|
+
await this.#browserInstance.close();
|
|
406
477
|
} catch (error) {
|
|
407
478
|
Logger.warn(`Failed to close browser on module destroy: ${error instanceof Error ? error.message : String(error)}`);
|
|
408
479
|
}
|
|
409
|
-
if (this
|
|
480
|
+
if (this.#options?.cleanupBrowserCacheOnExit !== false) await this.#cleanupCacheBestEffort();
|
|
410
481
|
}
|
|
411
482
|
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
412
|
-
async waitForIdle(timeoutMs) {
|
|
483
|
+
async #waitForIdle(timeoutMs) {
|
|
413
484
|
const start = Date.now();
|
|
414
485
|
while (this.activeJobs > 0 && Date.now() - start < timeoutMs) await sleep(50);
|
|
415
486
|
if (this.activeJobs > 0) Logger.warn(`Shutdown: ${this.activeJobs} PDF job(s) still running after ${timeoutMs}ms, closing the browser anyway`);
|
|
416
487
|
}
|
|
417
488
|
async getBrowserInstance(args, headless, executablePathBin) {
|
|
418
|
-
if (!this
|
|
419
|
-
return this
|
|
489
|
+
if (!this.#browserInstance?.connected) this.#browserInstance = await this.#launchBrowser(args, headless, executablePathBin);
|
|
490
|
+
return this.#browserInstance;
|
|
420
491
|
}
|
|
421
492
|
async createContext(args, headless, executablePath) {
|
|
422
493
|
const browser = await this.getBrowserInstance(args, headless, executablePath);
|
|
@@ -425,41 +496,41 @@ let BrowserService = class BrowserService {
|
|
|
425
496
|
} catch (error) {
|
|
426
497
|
if (!isTargetClosedError(error)) throw error;
|
|
427
498
|
Logger.warn("Puppeteer browser closed while creating a context, retrying once");
|
|
428
|
-
this
|
|
499
|
+
this.#browserInstance = null;
|
|
429
500
|
return await (await this.getBrowserInstance(args, headless, executablePath)).createBrowserContext();
|
|
430
501
|
}
|
|
431
502
|
}
|
|
432
503
|
markJobStarted() {
|
|
433
|
-
if (this
|
|
504
|
+
if (this.#shuttingDown) throw new BrowserUnavailableException("nestjs-pdf is shutting down, refusing new PDF jobs");
|
|
434
505
|
this.activeJobs += 1;
|
|
435
506
|
this.totalJobs += 1;
|
|
436
|
-
if (this.totalJobs >= 200) this
|
|
507
|
+
if (this.totalJobs >= 200) this.#recycleRequested = true;
|
|
437
508
|
}
|
|
438
509
|
async markJobFinished() {
|
|
439
510
|
this.activeJobs = Math.max(0, this.activeJobs - 1);
|
|
440
511
|
await this.recycleBrowserIfNeeded();
|
|
441
512
|
}
|
|
442
513
|
async recycleBrowserIfNeeded() {
|
|
443
|
-
if (!this
|
|
444
|
-
if (this
|
|
514
|
+
if (!this.#recycleRequested) return;
|
|
515
|
+
if (this.#recycling) return;
|
|
445
516
|
if (this.activeJobs > 0) return;
|
|
446
|
-
if (!this
|
|
447
|
-
this
|
|
517
|
+
if (!this.#browserInstance) return;
|
|
518
|
+
this.#recycling = true;
|
|
448
519
|
try {
|
|
449
|
-
if (this.
|
|
450
|
-
this
|
|
520
|
+
if (this.#browserInstance.connected) await this.#browserInstance.close();
|
|
521
|
+
this.#browserInstance = null;
|
|
451
522
|
this.totalJobs = 0;
|
|
452
|
-
this
|
|
523
|
+
this.#recycleRequested = false;
|
|
453
524
|
Logger.log("Puppeteer browser recycled successfully");
|
|
454
525
|
} catch (error) {
|
|
455
526
|
Logger.warn(`Failed to recycle browser: ${error instanceof Error ? error.message : String(error)}`);
|
|
456
527
|
} finally {
|
|
457
|
-
this
|
|
528
|
+
this.#recycling = false;
|
|
458
529
|
}
|
|
459
530
|
}
|
|
460
|
-
async cleanupCacheBestEffort() {
|
|
531
|
+
async #cleanupCacheBestEffort() {
|
|
461
532
|
const logger = new Logger("NestJsPdf");
|
|
462
|
-
const dir = this
|
|
533
|
+
const dir = this.#cacheDir;
|
|
463
534
|
try {
|
|
464
535
|
if (!existsSync(dir)) return;
|
|
465
536
|
logger.log(`Cleanup puppeteer cache: ${dir}`);
|
|
@@ -480,100 +551,109 @@ let BrowserService = class BrowserService {
|
|
|
480
551
|
}
|
|
481
552
|
}
|
|
482
553
|
async install(lock = false) {
|
|
483
|
-
|
|
484
|
-
|
|
554
|
+
try {
|
|
555
|
+
return await this.#doInstall(lock);
|
|
556
|
+
} catch (error) {
|
|
557
|
+
if (error instanceof NestjsPdfException) throw error;
|
|
558
|
+
throw new BrowserInstallationException(`Could not install browser: ${String(error)}`, { cause: error });
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
async #doInstall(lock) {
|
|
562
|
+
const browser = this.#browser;
|
|
563
|
+
const versionTag = this.#browserTag;
|
|
485
564
|
const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
|
|
486
565
|
let buildId;
|
|
487
|
-
if (this
|
|
488
|
-
else buildId = this
|
|
566
|
+
if (this.#buildId === void 0) buildId = await resolveBuildId(browser, browserPlatform, versionTag);
|
|
567
|
+
else buildId = this.#buildId;
|
|
489
568
|
Logger.log(`Browser ${browser} ${versionTag} build id: ${buildId}`, "NestJsPdf");
|
|
490
569
|
if (await this.hasBrowserInstalled(browser, buildId)) {
|
|
491
570
|
Logger.log("Browser already installed", "NestJsPdf");
|
|
492
|
-
if (lock) this
|
|
571
|
+
if (lock) this.#writeLockFile(browser, buildId);
|
|
493
572
|
return;
|
|
494
573
|
} else {
|
|
495
574
|
Logger.log("Starting browser installation", "NestJsPdf");
|
|
496
575
|
const installOption = {
|
|
497
|
-
cacheDir: this
|
|
576
|
+
cacheDir: this.#cacheDir,
|
|
498
577
|
browser,
|
|
499
578
|
buildId,
|
|
500
|
-
baseUrl: this
|
|
579
|
+
baseUrl: this.#options?.browserInstallBaseUrl ?? void 0
|
|
501
580
|
};
|
|
502
581
|
if (await canDownload(installOption)) {
|
|
503
582
|
Logger.log(`Installing ${installOption.browser} ${installOption.buildId}`, "NestJsPdf");
|
|
504
583
|
const installedBrowser = await install(installOption);
|
|
505
584
|
if (await this.hasBrowserInstalled(browser, buildId)) {
|
|
506
585
|
Logger.log("Browser installed successfully", "NestJsPdf");
|
|
507
|
-
if (lock) this
|
|
586
|
+
if (lock) this.#writeLockFile(browser, buildId);
|
|
508
587
|
return installedBrowser;
|
|
509
588
|
} else Logger.error("Browser installation failed", "NestJsPdf");
|
|
510
589
|
} else Logger.error(`Error, can't install ${installOption.browser} ${installOption.buildId}`, "NestJsPdf");
|
|
511
590
|
}
|
|
512
591
|
return null;
|
|
513
592
|
}
|
|
514
|
-
loadBrowser() {
|
|
593
|
+
#loadBrowser() {
|
|
515
594
|
let browser;
|
|
516
|
-
if (this
|
|
517
|
-
else browser = this
|
|
518
|
-
this
|
|
595
|
+
if (this.#options?.browser === void 0) browser = Browser.CHROMIUM;
|
|
596
|
+
else browser = this.#options.browser;
|
|
597
|
+
this.#browser = browser;
|
|
519
598
|
}
|
|
520
599
|
getBrowser() {
|
|
521
|
-
return this
|
|
600
|
+
return this.#browser;
|
|
522
601
|
}
|
|
523
|
-
loadBrowserTag() {
|
|
602
|
+
#loadBrowserTag() {
|
|
524
603
|
let versionTag;
|
|
525
|
-
if (this
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
this.browserTag
|
|
604
|
+
if (this.#options?.browserTag === void 0) {
|
|
605
|
+
if (this.#browser === Browser.CHROMIUM) versionTag = "latest";
|
|
606
|
+
else versionTag = "stable";
|
|
607
|
+
} else versionTag = this.#options.browserTag;
|
|
608
|
+
this.#browserTag = versionTag;
|
|
529
609
|
}
|
|
530
|
-
loadBuildId() {
|
|
610
|
+
#loadBuildId() {
|
|
531
611
|
let buildId;
|
|
532
|
-
if (this
|
|
533
|
-
else buildId = this
|
|
534
|
-
this
|
|
612
|
+
if (this.#options?.buildId === void 0) buildId = void 0;
|
|
613
|
+
else buildId = this.#options.buildId;
|
|
614
|
+
this.#buildId = buildId;
|
|
535
615
|
}
|
|
536
616
|
setBrowserTag(browserTag) {
|
|
537
|
-
this
|
|
617
|
+
this.#browserTag = browserTag;
|
|
538
618
|
}
|
|
539
619
|
getBrowserTag() {
|
|
540
|
-
return this
|
|
620
|
+
return this.#browserTag;
|
|
541
621
|
}
|
|
542
622
|
getBuildId() {
|
|
543
|
-
return this
|
|
623
|
+
return this.#buildId;
|
|
544
624
|
}
|
|
545
|
-
loadUseLockedBrowser() {
|
|
625
|
+
#loadUseLockedBrowser() {
|
|
546
626
|
let useLockedBrowser;
|
|
547
|
-
if (this
|
|
548
|
-
else useLockedBrowser = this
|
|
549
|
-
this
|
|
627
|
+
if (this.#options?.useLockedBrowser === void 0) useLockedBrowser = false;
|
|
628
|
+
else useLockedBrowser = this.#options.useLockedBrowser;
|
|
629
|
+
this.#useLockedBrowser = useLockedBrowser;
|
|
550
630
|
}
|
|
551
631
|
async hasBrowserInstalled(browser, buildId) {
|
|
552
|
-
return (await getInstalledBrowsers({ cacheDir: this
|
|
632
|
+
return (await getInstalledBrowsers({ cacheDir: this.#cacheDir })).find((insBrowser) => {
|
|
553
633
|
return insBrowser.browser === browser && insBrowser.buildId === buildId;
|
|
554
634
|
}) !== void 0;
|
|
555
635
|
}
|
|
556
636
|
async getExecutablePath() {
|
|
557
|
-
const browser = this
|
|
558
|
-
const versionTag = this
|
|
637
|
+
const browser = this.#browser;
|
|
638
|
+
const versionTag = this.#browserTag;
|
|
559
639
|
const browserPlatform = detectBrowserPlatform() ?? BrowserPlatform.LINUX;
|
|
560
640
|
let buildId = null;
|
|
561
|
-
if (this
|
|
641
|
+
if (this.#useLockedBrowser) {
|
|
562
642
|
buildId = this.getLockedBuildId(browser);
|
|
563
643
|
Logger.log(`Using locked browser ${buildId}`, "NestJsPdf");
|
|
564
644
|
}
|
|
565
645
|
buildId ??= await resolveBuildId(browser, browserPlatform, versionTag);
|
|
566
|
-
const installedBrowser = (await getInstalledBrowsers({ cacheDir: this
|
|
646
|
+
const installedBrowser = (await getInstalledBrowsers({ cacheDir: this.#cacheDir })).find((insBrowser) => {
|
|
567
647
|
return insBrowser.browser === browser && insBrowser.buildId === buildId;
|
|
568
648
|
});
|
|
569
649
|
if (installedBrowser === void 0) {
|
|
570
650
|
const newinstalledBrowser = await this.install();
|
|
571
|
-
if (newinstalledBrowser === null || newinstalledBrowser === void 0) throw new
|
|
651
|
+
if (newinstalledBrowser === null || newinstalledBrowser === void 0) throw new BrowserInstallationException("Could not install browser");
|
|
572
652
|
else return newinstalledBrowser.executablePath;
|
|
573
653
|
}
|
|
574
654
|
return installedBrowser.executablePath;
|
|
575
655
|
}
|
|
576
|
-
async launchBrowser(args, headless, executablePathBin) {
|
|
656
|
+
async #launchBrowser(args, headless, executablePathBin) {
|
|
577
657
|
const executablePath = executablePathBin ?? await this.getExecutablePath();
|
|
578
658
|
const browser = await launch({
|
|
579
659
|
executablePath,
|
|
@@ -582,12 +662,12 @@ let BrowserService = class BrowserService {
|
|
|
582
662
|
});
|
|
583
663
|
browser.on("disconnected", () => {
|
|
584
664
|
Logger.warn("Puppeteer browser disconnected");
|
|
585
|
-
if (this
|
|
665
|
+
if (this.#browserInstance === browser) this.#browserInstance = null;
|
|
586
666
|
});
|
|
587
667
|
return browser;
|
|
588
668
|
}
|
|
589
|
-
writeLockFile(browser, buildId) {
|
|
590
|
-
const lockFile = resolve(this
|
|
669
|
+
#writeLockFile(browser, buildId) {
|
|
670
|
+
const lockFile = resolve(this.#cacheDir, `${browser}.lock`);
|
|
591
671
|
const data = JSON.stringify({
|
|
592
672
|
browser,
|
|
593
673
|
buildId,
|
|
@@ -597,7 +677,7 @@ let BrowserService = class BrowserService {
|
|
|
597
677
|
Logger.log(`Browser ${browser} locked to build ${buildId}`, "NestJsPdf");
|
|
598
678
|
}
|
|
599
679
|
getLockedBuildId(browser) {
|
|
600
|
-
const lockFile = resolve(this
|
|
680
|
+
const lockFile = resolve(this.#cacheDir, `${browser}.lock`);
|
|
601
681
|
if (existsSync(lockFile)) {
|
|
602
682
|
const data = readFileSync(lockFile);
|
|
603
683
|
return JSON.parse(data.toString()).buildId;
|
|
@@ -620,7 +700,7 @@ let EjsService = class EjsService {
|
|
|
620
700
|
...options
|
|
621
701
|
});
|
|
622
702
|
} catch (error) {
|
|
623
|
-
throw new
|
|
703
|
+
throw new TemplateRenderException("EJS", `EJS rendering failed: ${String(error)}`, { cause: error });
|
|
624
704
|
}
|
|
625
705
|
}
|
|
626
706
|
async renderFile(filePath, data = {}, options) {
|
|
@@ -630,7 +710,7 @@ let EjsService = class EjsService {
|
|
|
630
710
|
...options
|
|
631
711
|
});
|
|
632
712
|
} catch (error) {
|
|
633
|
-
throw new
|
|
713
|
+
throw new TemplateRenderException("EJS", `EJS file rendering failed: ${String(error)}`, { cause: error });
|
|
634
714
|
}
|
|
635
715
|
}
|
|
636
716
|
};
|
|
@@ -638,11 +718,11 @@ EjsService = __decorate$3([Injectable()], EjsService);
|
|
|
638
718
|
//#endregion
|
|
639
719
|
//#region src/puppeteer/engines/eta/eta.service.ts
|
|
640
720
|
let EtaService = class EtaService {
|
|
641
|
-
eta;
|
|
642
|
-
templateCache = /* @__PURE__ */ new Map();
|
|
643
|
-
maxCacheSize = 100;
|
|
721
|
+
#eta;
|
|
722
|
+
#templateCache = /* @__PURE__ */ new Map();
|
|
723
|
+
#maxCacheSize = 100;
|
|
644
724
|
constructor() {
|
|
645
|
-
this
|
|
725
|
+
this.#eta = new Eta({
|
|
646
726
|
cache: true,
|
|
647
727
|
autoEscape: true,
|
|
648
728
|
useWith: true
|
|
@@ -663,9 +743,9 @@ let EtaService = class EtaService {
|
|
|
663
743
|
useWith: true,
|
|
664
744
|
...options,
|
|
665
745
|
varName: options.varName ?? "it"
|
|
666
|
-
}) : this
|
|
746
|
+
}) : this.#eta).renderString(template, data);
|
|
667
747
|
} catch (error) {
|
|
668
|
-
throw new
|
|
748
|
+
throw new TemplateRenderException("Eta", `Eta rendering failed: ${String(error)}`, { cause: error });
|
|
669
749
|
}
|
|
670
750
|
}
|
|
671
751
|
/**
|
|
@@ -679,53 +759,54 @@ let EtaService = class EtaService {
|
|
|
679
759
|
try {
|
|
680
760
|
const resolvedPath = resolve(filePath);
|
|
681
761
|
const useCache = options?.cache ?? true;
|
|
682
|
-
let template = useCache ? this
|
|
762
|
+
let template = useCache ? this.#templateCache.get(resolvedPath) : void 0;
|
|
683
763
|
if (!template) {
|
|
684
764
|
template = readFileSync(resolvedPath, "utf-8");
|
|
685
|
-
if (useCache && this
|
|
765
|
+
if (useCache && this.#templateCache.size < this.#maxCacheSize) this.#templateCache.set(resolvedPath, template);
|
|
686
766
|
}
|
|
687
767
|
return this.render(template, data, options);
|
|
688
768
|
} catch (error) {
|
|
689
|
-
throw new
|
|
769
|
+
throw new TemplateRenderException("Eta", `Eta file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
690
770
|
}
|
|
691
771
|
}
|
|
692
772
|
/**
|
|
693
773
|
* Clear the template cache
|
|
694
774
|
*/
|
|
695
775
|
clearCache() {
|
|
696
|
-
this
|
|
776
|
+
this.#templateCache.clear();
|
|
697
777
|
}
|
|
698
778
|
/**
|
|
699
779
|
* Get the current cache size
|
|
700
780
|
* @returns The number of cached templates
|
|
701
781
|
*/
|
|
702
782
|
getCacheSize() {
|
|
703
|
-
return this
|
|
783
|
+
return this.#templateCache.size;
|
|
704
784
|
}
|
|
705
785
|
};
|
|
706
786
|
EtaService = __decorate$3([Injectable(), __decorateMetadata("design:paramtypes", [])], EtaService);
|
|
707
787
|
//#endregion
|
|
708
788
|
//#region src/puppeteer/engines/handlebars/handlebars.service.ts
|
|
709
789
|
let HandlebarsService = class HandlebarsService {
|
|
710
|
-
cachedOptions;
|
|
711
|
-
cachedEnv;
|
|
790
|
+
#cachedOptions;
|
|
791
|
+
#cachedEnv;
|
|
712
792
|
render(template, parameters = {}, options = {}) {
|
|
713
793
|
try {
|
|
714
|
-
return this
|
|
794
|
+
return this.#getEnv(options).compile(template, options.compileOptions)(parameters, options.templateOptions);
|
|
715
795
|
} catch (error) {
|
|
716
|
-
|
|
796
|
+
if (error instanceof NestjsPdfException) throw error;
|
|
797
|
+
throw new TemplateRenderException("Handlebars", `Handlebars rendering failed: ${String(error)}`, { cause: error });
|
|
717
798
|
}
|
|
718
799
|
}
|
|
719
800
|
renderFile(file, parameters = {}, options = {}) {
|
|
720
|
-
if (options.templateDirectory === void 0) throw new
|
|
801
|
+
if (options.templateDirectory === void 0) throw new TemplateConfigurationException("Handlebars file rendering failed: option `templateDirectory` is not set");
|
|
721
802
|
const baseDir = resolve(process.cwd(), options.templateDirectory);
|
|
722
803
|
const templatePath = resolve(baseDir, file);
|
|
723
|
-
if (templatePath !== baseDir && !templatePath.startsWith(baseDir + sep)) throw new
|
|
804
|
+
if (templatePath !== baseDir && !templatePath.startsWith(baseDir + sep)) throw new TemplateConfigurationException(`Handlebars file rendering failed: ’${file}’ resolves outside \`templateDirectory\``);
|
|
724
805
|
let template;
|
|
725
806
|
try {
|
|
726
807
|
template = readFileSync(templatePath, "utf8");
|
|
727
808
|
} catch (error) {
|
|
728
|
-
throw new
|
|
809
|
+
throw new TemplateRenderException("Handlebars", `Handlebars file rendering failed: ${String(error)}`, { cause: error });
|
|
729
810
|
}
|
|
730
811
|
return this.render(template, parameters, options);
|
|
731
812
|
}
|
|
@@ -734,19 +815,19 @@ let HandlebarsService = class HandlebarsService {
|
|
|
734
815
|
* nothing leaks into the global Handlebars. Memoised for the common case where
|
|
735
816
|
* the same options object is reused across calls (e.g. the module `hbsOptions`).
|
|
736
817
|
*/
|
|
737
|
-
getEnv(options) {
|
|
738
|
-
if (this
|
|
818
|
+
#getEnv(options) {
|
|
819
|
+
if (this.#cachedEnv && this.#cachedOptions === options) return this.#cachedEnv;
|
|
739
820
|
const env = Handlebars.create();
|
|
740
821
|
for (const helper of options.helpers ?? []) env.registerHelper(helper.name, helper.fn);
|
|
741
|
-
this
|
|
742
|
-
this
|
|
743
|
-
this
|
|
822
|
+
this.#registerPartials(env, options.partialDirectory);
|
|
823
|
+
this.#cachedOptions = options;
|
|
824
|
+
this.#cachedEnv = env;
|
|
744
825
|
return env;
|
|
745
826
|
}
|
|
746
|
-
registerPartials(env, partialDirectory) {
|
|
827
|
+
#registerPartials(env, partialDirectory) {
|
|
747
828
|
if (partialDirectory === void 0) return;
|
|
748
829
|
const partialPath = join(process.cwd(), partialDirectory);
|
|
749
|
-
if (!existsSync(partialPath)) throw new
|
|
830
|
+
if (!existsSync(partialPath)) throw new TemplateConfigurationException(`Handlebars partial directory does not exist: ${partialPath}`);
|
|
750
831
|
for (const entry of readdirSync(partialPath)) {
|
|
751
832
|
const filePath = join(partialPath, entry);
|
|
752
833
|
if (!statSync(filePath).isFile()) continue;
|
|
@@ -759,11 +840,20 @@ HandlebarsService = __decorate$3([Injectable()], HandlebarsService);
|
|
|
759
840
|
//#region src/puppeteer/engines/mjml/mjml.service.ts
|
|
760
841
|
let MjmlService = class MjmlService {
|
|
761
842
|
async render(template, options) {
|
|
762
|
-
|
|
763
|
-
|
|
843
|
+
try {
|
|
844
|
+
const { html } = await mjml(template, options);
|
|
845
|
+
return html;
|
|
846
|
+
} catch (error) {
|
|
847
|
+
throw new TemplateRenderException("MJML", `MJML rendering failed: ${String(error)}`, { cause: error });
|
|
848
|
+
}
|
|
764
849
|
}
|
|
765
850
|
async renderFile(filePath, options) {
|
|
766
|
-
|
|
851
|
+
let template;
|
|
852
|
+
try {
|
|
853
|
+
template = readFileSync(filePath, "utf-8");
|
|
854
|
+
} catch (error) {
|
|
855
|
+
throw new TemplateRenderException("MJML", `MJML file rendering failed: ${String(error)}`, { cause: error });
|
|
856
|
+
}
|
|
767
857
|
return await this.render(template, options);
|
|
768
858
|
}
|
|
769
859
|
};
|
|
@@ -771,8 +861,8 @@ MjmlService = __decorate$3([Injectable()], MjmlService);
|
|
|
771
861
|
//#endregion
|
|
772
862
|
//#region src/puppeteer/engines/mustache/mustache.service.ts
|
|
773
863
|
let MustacheService = class MustacheService {
|
|
774
|
-
templateCache = /* @__PURE__ */ new Map();
|
|
775
|
-
maxCacheSize = 100;
|
|
864
|
+
#templateCache = /* @__PURE__ */ new Map();
|
|
865
|
+
#maxCacheSize = 100;
|
|
776
866
|
/**
|
|
777
867
|
* Render a Mustache template from a string
|
|
778
868
|
* @param template The template string to render
|
|
@@ -788,7 +878,7 @@ let MustacheService = class MustacheService {
|
|
|
788
878
|
escape: options?.escape
|
|
789
879
|
});
|
|
790
880
|
} catch (error) {
|
|
791
|
-
throw new
|
|
881
|
+
throw new TemplateRenderException("Mustache", `Mustache rendering failed: ${String(error)}`, { cause: error });
|
|
792
882
|
}
|
|
793
883
|
}
|
|
794
884
|
/**
|
|
@@ -801,28 +891,28 @@ let MustacheService = class MustacheService {
|
|
|
801
891
|
renderFile(filePath, data = {}, options) {
|
|
802
892
|
try {
|
|
803
893
|
const resolvedPath = resolve(filePath);
|
|
804
|
-
let template = this
|
|
894
|
+
let template = this.#templateCache.get(resolvedPath);
|
|
805
895
|
if (!template) {
|
|
806
896
|
template = readFileSync(resolvedPath, "utf-8");
|
|
807
|
-
if (this
|
|
897
|
+
if (this.#templateCache.size < this.#maxCacheSize) this.#templateCache.set(resolvedPath, template);
|
|
808
898
|
}
|
|
809
899
|
return this.render(template, data, options);
|
|
810
900
|
} catch (error) {
|
|
811
|
-
throw new
|
|
901
|
+
throw new TemplateRenderException("Mustache", `Mustache file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
812
902
|
}
|
|
813
903
|
}
|
|
814
904
|
/**
|
|
815
905
|
* Clear the template cache
|
|
816
906
|
*/
|
|
817
907
|
clearCache() {
|
|
818
|
-
this
|
|
908
|
+
this.#templateCache.clear();
|
|
819
909
|
}
|
|
820
910
|
/**
|
|
821
911
|
* Get the current cache size
|
|
822
912
|
* @returns The number of cached templates
|
|
823
913
|
*/
|
|
824
914
|
getCacheSize() {
|
|
825
|
-
return this
|
|
915
|
+
return this.#templateCache.size;
|
|
826
916
|
}
|
|
827
917
|
};
|
|
828
918
|
MustacheService = __decorate$3([Injectable()], MustacheService);
|
|
@@ -850,7 +940,7 @@ let NunjucksService = class NunjucksService {
|
|
|
850
940
|
}
|
|
851
941
|
return nunjucks.renderString(template, data);
|
|
852
942
|
} catch (error) {
|
|
853
|
-
throw new
|
|
943
|
+
throw new TemplateRenderException("Nunjucks", `Nunjucks rendering failed: ${String(error)}`, { cause: error });
|
|
854
944
|
}
|
|
855
945
|
}
|
|
856
946
|
renderFile(filePath, data = {}, options) {
|
|
@@ -867,7 +957,7 @@ let NunjucksService = class NunjucksService {
|
|
|
867
957
|
}
|
|
868
958
|
return nunjucks.render(filePath, data);
|
|
869
959
|
} catch (error) {
|
|
870
|
-
throw new
|
|
960
|
+
throw new TemplateRenderException("Nunjucks", `Nunjucks file rendering failed: ${String(error)}`, { cause: error });
|
|
871
961
|
}
|
|
872
962
|
}
|
|
873
963
|
};
|
|
@@ -879,7 +969,7 @@ let PugService = class PugService {
|
|
|
879
969
|
try {
|
|
880
970
|
return pug.compile(template, { ...options })(data);
|
|
881
971
|
} catch (error) {
|
|
882
|
-
throw new
|
|
972
|
+
throw new TemplateRenderException("Pug", `Pug rendering failed: ${String(error)}`, { cause: error });
|
|
883
973
|
}
|
|
884
974
|
}
|
|
885
975
|
renderFile(filePath, data = {}, options) {
|
|
@@ -887,7 +977,7 @@ let PugService = class PugService {
|
|
|
887
977
|
const template = readFileSync(filePath, "utf-8");
|
|
888
978
|
return this.render(template, data, options);
|
|
889
979
|
} catch (error) {
|
|
890
|
-
throw new
|
|
980
|
+
throw new TemplateRenderException("Pug", `Pug file rendering failed: ${String(error)}`, { cause: error });
|
|
891
981
|
}
|
|
892
982
|
}
|
|
893
983
|
};
|
|
@@ -895,36 +985,36 @@ PugService = __decorate$3([Injectable()], PugService);
|
|
|
895
985
|
//#endregion
|
|
896
986
|
//#region src/puppeteer/libs/requireService.utils.ts
|
|
897
987
|
function requireService(service, name) {
|
|
898
|
-
if (!service) throw new
|
|
988
|
+
if (!service) throw new EngineNotAvailableException(name);
|
|
899
989
|
return service;
|
|
900
990
|
}
|
|
901
991
|
//#endregion
|
|
902
992
|
//#region src/puppeteer/puppeteer.service.ts
|
|
903
993
|
let PuppeteerService = class PuppeteerService {
|
|
904
|
-
browserService;
|
|
905
|
-
options;
|
|
906
|
-
hbsService;
|
|
907
|
-
mjmlService;
|
|
908
|
-
pugService;
|
|
909
|
-
ejsService;
|
|
910
|
-
nunjucksService;
|
|
911
|
-
etaService;
|
|
912
|
-
mustacheService;
|
|
994
|
+
#browserService;
|
|
995
|
+
#options;
|
|
996
|
+
#hbsService;
|
|
997
|
+
#mjmlService;
|
|
998
|
+
#pugService;
|
|
999
|
+
#ejsService;
|
|
1000
|
+
#nunjucksService;
|
|
1001
|
+
#etaService;
|
|
1002
|
+
#mustacheService;
|
|
913
1003
|
constructor(browserService, options, hbsService, mjmlService, pugService, ejsService, nunjucksService, etaService, mustacheService) {
|
|
914
|
-
this
|
|
915
|
-
this
|
|
916
|
-
this
|
|
917
|
-
this
|
|
918
|
-
this
|
|
919
|
-
this
|
|
920
|
-
this
|
|
921
|
-
this
|
|
922
|
-
this
|
|
923
|
-
}
|
|
924
|
-
limit = pLimit(3);
|
|
1004
|
+
this.#browserService = browserService;
|
|
1005
|
+
this.#options = options;
|
|
1006
|
+
this.#hbsService = hbsService;
|
|
1007
|
+
this.#mjmlService = mjmlService;
|
|
1008
|
+
this.#pugService = pugService;
|
|
1009
|
+
this.#ejsService = ejsService;
|
|
1010
|
+
this.#nunjucksService = nunjucksService;
|
|
1011
|
+
this.#etaService = etaService;
|
|
1012
|
+
this.#mustacheService = mustacheService;
|
|
1013
|
+
}
|
|
1014
|
+
#limit = pLimit(3);
|
|
925
1015
|
async generatePdfFromHtml(html, options) {
|
|
926
|
-
return this
|
|
927
|
-
const mergePuppeteerOptions = mergePuppeteerParameters(this
|
|
1016
|
+
return this.#limit(async () => {
|
|
1017
|
+
const mergePuppeteerOptions = mergePuppeteerParameters(this.#options, options);
|
|
928
1018
|
if (mergePuppeteerOptions.chromiumRevision !== void 0) Logger.warn("Using `chromiumRevision` is no longer supported since the puppeteer update.");
|
|
929
1019
|
const headless = mergePuppeteerOptions.headless ?? true;
|
|
930
1020
|
const executablePath = mergePuppeteerOptions.executablePath || void 0;
|
|
@@ -966,10 +1056,10 @@ let PuppeteerService = class PuppeteerService {
|
|
|
966
1056
|
"--no-zygote",
|
|
967
1057
|
"--disable-gpu"
|
|
968
1058
|
];
|
|
969
|
-
this
|
|
1059
|
+
this.#browserService.markJobStarted();
|
|
970
1060
|
let context = null;
|
|
971
1061
|
try {
|
|
972
|
-
context = await this
|
|
1062
|
+
context = await this.#browserService.createContext(args, headless, executablePath);
|
|
973
1063
|
const page = await context.newPage();
|
|
974
1064
|
const pdfOptions = mergePuppeteerOptions.pdfOptions ?? { format: "A4" };
|
|
975
1065
|
await page.setContent(html, { waitUntil: "domcontentloaded" });
|
|
@@ -978,75 +1068,77 @@ let PuppeteerService = class PuppeteerService {
|
|
|
978
1068
|
idleTime: 500,
|
|
979
1069
|
timeout: 3e4
|
|
980
1070
|
});
|
|
1071
|
+
/* v8 ignore next */
|
|
981
1072
|
await page.evaluate(() => document.fonts.ready);
|
|
982
1073
|
return await page.pdf(pdfOptions);
|
|
983
1074
|
} catch (e) {
|
|
984
1075
|
Logger.error(e);
|
|
985
|
-
throw e;
|
|
1076
|
+
if (e instanceof NestjsPdfException) throw e;
|
|
1077
|
+
throw new PdfGenerationException(`PDF generation failed: ${String(e)}`, { cause: e });
|
|
986
1078
|
} finally {
|
|
987
1079
|
if (context) try {
|
|
988
1080
|
await context.close();
|
|
989
1081
|
} catch (error) {
|
|
990
1082
|
Logger.error(error);
|
|
991
1083
|
}
|
|
992
|
-
await this
|
|
1084
|
+
await this.#browserService.markJobFinished();
|
|
993
1085
|
}
|
|
994
1086
|
});
|
|
995
1087
|
}
|
|
996
1088
|
async generatePdfFromTemplateHbsString(template, parameters = {}, options) {
|
|
997
|
-
const html = requireService(this
|
|
1089
|
+
const html = requireService(this.#hbsService, "Handlebars").render(template, parameters, options?.hbsOptions ?? this.#options.hbsOptions);
|
|
998
1090
|
return this.generatePdfFromHtml(html, options);
|
|
999
1091
|
}
|
|
1000
1092
|
async generatePdfFromTemplateHbsFile(file, parameters = {}, options) {
|
|
1001
|
-
const html = requireService(this
|
|
1093
|
+
const html = requireService(this.#hbsService, "Handlebars").renderFile(file, parameters, options?.hbsOptions ?? this.#options.hbsOptions);
|
|
1002
1094
|
return this.generatePdfFromHtml(html, options);
|
|
1003
1095
|
}
|
|
1004
1096
|
async generatePdfFromMjmlString(template, options) {
|
|
1005
|
-
const html = await requireService(this
|
|
1097
|
+
const html = await requireService(this.#mjmlService, "MJML").render(template, options?.mjmlOptions ?? this.#options.mjmlOptions);
|
|
1006
1098
|
return this.generatePdfFromHtml(html, options);
|
|
1007
1099
|
}
|
|
1008
1100
|
async generatePdfFromMjmlFile(file, options) {
|
|
1009
|
-
const html = await requireService(this
|
|
1101
|
+
const html = await requireService(this.#mjmlService, "MJML").renderFile(file, options?.mjmlOptions ?? this.#options.mjmlOptions);
|
|
1010
1102
|
return this.generatePdfFromHtml(html, options);
|
|
1011
1103
|
}
|
|
1012
1104
|
async generatePdfFromPugString(template, data = {}, options) {
|
|
1013
|
-
const html = requireService(this
|
|
1105
|
+
const html = requireService(this.#pugService, "Pug").render(template, data, options?.pugOptions ?? this.#options.pugOptions);
|
|
1014
1106
|
return this.generatePdfFromHtml(html, options);
|
|
1015
1107
|
}
|
|
1016
1108
|
async generatePdfFromPugFile(file, data = {}, options) {
|
|
1017
|
-
const html = requireService(this
|
|
1109
|
+
const html = requireService(this.#pugService, "Pug").renderFile(file, data, options?.pugOptions ?? this.#options.pugOptions);
|
|
1018
1110
|
return this.generatePdfFromHtml(html, options);
|
|
1019
1111
|
}
|
|
1020
1112
|
async generatePdfFromEjsString(template, data = {}, options) {
|
|
1021
|
-
const html = await requireService(this
|
|
1113
|
+
const html = await requireService(this.#ejsService, "EJS").render(template, data, options?.ejsOptions ?? this.#options.ejsOptions);
|
|
1022
1114
|
return this.generatePdfFromHtml(html, options);
|
|
1023
1115
|
}
|
|
1024
1116
|
async generatePdfFromEjsFile(file, data = {}, options) {
|
|
1025
|
-
const html = await requireService(this
|
|
1117
|
+
const html = await requireService(this.#ejsService, "EJS").renderFile(file, data, options?.ejsOptions ?? this.#options.ejsOptions);
|
|
1026
1118
|
return this.generatePdfFromHtml(html, options);
|
|
1027
1119
|
}
|
|
1028
1120
|
async generatePdfFromNunjucksString(template, data = {}, options) {
|
|
1029
|
-
const html = requireService(this
|
|
1121
|
+
const html = requireService(this.#nunjucksService, "Nunjucks").render(template, data, options?.nunjucksOptions ?? this.#options.nunjucksOptions);
|
|
1030
1122
|
return this.generatePdfFromHtml(html, options);
|
|
1031
1123
|
}
|
|
1032
1124
|
async generatePdfFromNunjucksFile(file, data = {}, options) {
|
|
1033
|
-
const html = requireService(this
|
|
1125
|
+
const html = requireService(this.#nunjucksService, "Nunjucks").renderFile(file, data, options?.nunjucksOptions ?? this.#options.nunjucksOptions);
|
|
1034
1126
|
return this.generatePdfFromHtml(html, options);
|
|
1035
1127
|
}
|
|
1036
1128
|
async generatePdfFromEtaString(template, data = {}, options) {
|
|
1037
|
-
const html = requireService(this
|
|
1129
|
+
const html = requireService(this.#etaService, "Eta").render(template, data, options?.etaOptions ?? this.#options.etaOptions);
|
|
1038
1130
|
return this.generatePdfFromHtml(html, options);
|
|
1039
1131
|
}
|
|
1040
1132
|
async generatePdfFromEtaFile(file, data = {}, options) {
|
|
1041
|
-
const html = requireService(this
|
|
1133
|
+
const html = requireService(this.#etaService, "Eta").renderFile(file, data, options?.etaOptions ?? this.#options.etaOptions);
|
|
1042
1134
|
return this.generatePdfFromHtml(html, options);
|
|
1043
1135
|
}
|
|
1044
1136
|
async generatePdfFromMustacheString(template, data = {}, options) {
|
|
1045
|
-
const html = requireService(this
|
|
1137
|
+
const html = requireService(this.#mustacheService, "Mustache").render(template, data, options?.mustacheOptions ?? this.#options.mustacheOptions);
|
|
1046
1138
|
return this.generatePdfFromHtml(html, options);
|
|
1047
1139
|
}
|
|
1048
1140
|
async generatePdfFromMustacheFile(file, data = {}, options) {
|
|
1049
|
-
const html = requireService(this
|
|
1141
|
+
const html = requireService(this.#mustacheService, "Mustache").renderFile(file, data, options?.mustacheOptions ?? this.#options.mustacheOptions);
|
|
1050
1142
|
return this.generatePdfFromHtml(html, options);
|
|
1051
1143
|
}
|
|
1052
1144
|
};
|
|
@@ -1075,9 +1167,9 @@ PuppeteerService = __decorate$3([
|
|
|
1075
1167
|
//#endregion
|
|
1076
1168
|
//#region src/nestjs-pdf.service.ts
|
|
1077
1169
|
let NestjsPdfService = class NestjsPdfService {
|
|
1078
|
-
puppeteerService;
|
|
1170
|
+
#puppeteerService;
|
|
1079
1171
|
constructor(puppeteerService) {
|
|
1080
|
-
this
|
|
1172
|
+
this.#puppeteerService = puppeteerService;
|
|
1081
1173
|
}
|
|
1082
1174
|
/**
|
|
1083
1175
|
* @param html HTML string to convert to PDF
|
|
@@ -1086,7 +1178,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1086
1178
|
* @description This method uses the Puppeteer service to generate a PDF from an HTML string. Generation options can be customized by passing a `PuppeteerParameters` object as the second argument. This allows you to control various aspects of PDF rendering, such as page size, margins, background display, etc. If no options are provided, the default parameters defined in the Puppeteer service will be used.
|
|
1087
1179
|
*/
|
|
1088
1180
|
generatePdfFromHtml(html, options) {
|
|
1089
|
-
return this
|
|
1181
|
+
return this.#puppeteerService.generatePdfFromHtml(html, options);
|
|
1090
1182
|
}
|
|
1091
1183
|
/**
|
|
1092
1184
|
* @param template Handlebars template string
|
|
@@ -1096,7 +1188,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1096
1188
|
* @description This method generates a PDF from a Handlebars template provided as a string. The parameters to inject into the template are passed in the `parameters` object, which is used to render the template before converting it to PDF. PDF generation options can also be customized by passing a `PuppeteerParameters` object as the third argument. This allows you to control various aspects of PDF rendering, such as page size, margins, background display, etc. If no options are provided, the default parameters defined in the Puppeteer service will be used.
|
|
1097
1189
|
*/
|
|
1098
1190
|
generatePdfFromTemplateHbsString(template, parameters = {}, options) {
|
|
1099
|
-
return this
|
|
1191
|
+
return this.#puppeteerService.generatePdfFromTemplateHbsString(template, parameters, options);
|
|
1100
1192
|
}
|
|
1101
1193
|
/**
|
|
1102
1194
|
* @param file Path to the Handlebars template file
|
|
@@ -1106,7 +1198,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1106
1198
|
* @description This method generates a PDF from a Handlebars template located at the specified file path. The file path is passed as a string in the `file` parameter. The parameters to inject into the template are passed in the `parameters` object, which is used to render the template before converting it to PDF. PDF generation options can also be customized by passing a `PuppeteerParameters` object as the third argument. This allows you to control various aspects of PDF rendering, such as page size, margins, background display, etc. If no options are provided, the default parameters defined in the Puppeteer service will be used.
|
|
1107
1199
|
*/
|
|
1108
1200
|
generatePdfFromTemplateHbsFile(file, parameters = {}, options) {
|
|
1109
|
-
return this
|
|
1201
|
+
return this.#puppeteerService.generatePdfFromTemplateHbsFile(file, parameters, options);
|
|
1110
1202
|
}
|
|
1111
1203
|
/**
|
|
1112
1204
|
* @param template MJML template string
|
|
@@ -1115,7 +1207,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1115
1207
|
* @description This method generates a PDF from an MJML template provided as a string. MJML (MJML Markup Language) is a markup language designed to reduce the pain of coding a responsive email. The template is first rendered to HTML using the MJML renderer, then converted to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the second argument.
|
|
1116
1208
|
*/
|
|
1117
1209
|
generatePdfFromMjmlString(template, options) {
|
|
1118
|
-
return this
|
|
1210
|
+
return this.#puppeteerService.generatePdfFromMjmlString(template, options);
|
|
1119
1211
|
}
|
|
1120
1212
|
/**
|
|
1121
1213
|
* @param file Path to the MJML template file
|
|
@@ -1124,7 +1216,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1124
1216
|
* @description This method generates a PDF from an MJML template located at the specified file path. The file path is passed as a string in the `file` parameter. The template is first rendered to HTML using the MJML renderer, then converted to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the second argument.
|
|
1125
1217
|
*/
|
|
1126
1218
|
generatePdfFromMjmlFile(file, options) {
|
|
1127
|
-
return this
|
|
1219
|
+
return this.#puppeteerService.generatePdfFromMjmlFile(file, options);
|
|
1128
1220
|
}
|
|
1129
1221
|
/**
|
|
1130
1222
|
* @param template EJS template string
|
|
@@ -1134,7 +1226,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1134
1226
|
* @description This method generates a PDF from an EJS (Embedded JavaScript) template provided as a string. EJS is a templating language with a simple, straightforward syntax. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1135
1227
|
*/
|
|
1136
1228
|
generatePdfFromEjsString(template, data = {}, options) {
|
|
1137
|
-
return this
|
|
1229
|
+
return this.#puppeteerService.generatePdfFromEjsString(template, data, options);
|
|
1138
1230
|
}
|
|
1139
1231
|
/**
|
|
1140
1232
|
* @param file Path to the EJS template file
|
|
@@ -1144,7 +1236,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1144
1236
|
* @description This method generates a PDF from an EJS template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1145
1237
|
*/
|
|
1146
1238
|
generatePdfFromEjsFile(file, data = {}, options) {
|
|
1147
|
-
return this
|
|
1239
|
+
return this.#puppeteerService.generatePdfFromEjsFile(file, data, options);
|
|
1148
1240
|
}
|
|
1149
1241
|
/**
|
|
1150
1242
|
* @param template Pug template string
|
|
@@ -1154,7 +1246,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1154
1246
|
* @description This method generates a PDF from a Pug template provided as a string. Pug is a clean, whitespace-sensitive syntax for writing HTML. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1155
1247
|
*/
|
|
1156
1248
|
generatePdfFromPugString(template, data = {}, options) {
|
|
1157
|
-
return this
|
|
1249
|
+
return this.#puppeteerService.generatePdfFromPugString(template, data, options);
|
|
1158
1250
|
}
|
|
1159
1251
|
/**
|
|
1160
1252
|
* @param file Path to the Pug template file
|
|
@@ -1164,7 +1256,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1164
1256
|
* @description This method generates a PDF from a Pug template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1165
1257
|
*/
|
|
1166
1258
|
generatePdfFromPugFile(file, data = {}, options) {
|
|
1167
|
-
return this
|
|
1259
|
+
return this.#puppeteerService.generatePdfFromPugFile(file, data, options);
|
|
1168
1260
|
}
|
|
1169
1261
|
/**
|
|
1170
1262
|
* @param template Nunjucks template string
|
|
@@ -1174,7 +1266,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1174
1266
|
* @description This method generates a PDF from a Nunjucks template provided as a string. Nunjucks is a powerful templating language with support for inheritance, macros, and filters. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1175
1267
|
*/
|
|
1176
1268
|
generatePdfFromNunjucksString(template, data = {}, options) {
|
|
1177
|
-
return this
|
|
1269
|
+
return this.#puppeteerService.generatePdfFromNunjucksString(template, data, options);
|
|
1178
1270
|
}
|
|
1179
1271
|
/**
|
|
1180
1272
|
* @param file Path to the Nunjucks template file
|
|
@@ -1184,7 +1276,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1184
1276
|
* @description This method generates a PDF from a Nunjucks template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1185
1277
|
*/
|
|
1186
1278
|
generatePdfFromNunjucksFile(file, data = {}, options) {
|
|
1187
|
-
return this
|
|
1279
|
+
return this.#puppeteerService.generatePdfFromNunjucksFile(file, data, options);
|
|
1188
1280
|
}
|
|
1189
1281
|
/**
|
|
1190
1282
|
* @param template Eta template string
|
|
@@ -1194,7 +1286,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1194
1286
|
* @description This method generates a PDF from an Eta template provided as a string. Eta is a fast and lightweight embedded templating language with a syntax similar to EJS but with better performance. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1195
1287
|
*/
|
|
1196
1288
|
generatePdfFromEtaString(template, data = {}, options) {
|
|
1197
|
-
return this
|
|
1289
|
+
return this.#puppeteerService.generatePdfFromEtaString(template, data, options);
|
|
1198
1290
|
}
|
|
1199
1291
|
/**
|
|
1200
1292
|
* @param file Path to the Eta template file
|
|
@@ -1204,7 +1296,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1204
1296
|
* @description This method generates a PDF from an Eta template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1205
1297
|
*/
|
|
1206
1298
|
generatePdfFromEtaFile(file, data = {}, options) {
|
|
1207
|
-
return this
|
|
1299
|
+
return this.#puppeteerService.generatePdfFromEtaFile(file, data, options);
|
|
1208
1300
|
}
|
|
1209
1301
|
/**
|
|
1210
1302
|
* @param template Mustache template string
|
|
@@ -1214,7 +1306,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1214
1306
|
* @description This method generates a PDF from a Mustache template provided as a string. Mustache is a logic-less template language that emphasizes readable and simple templates. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1215
1307
|
*/
|
|
1216
1308
|
generatePdfFromMustacheString(template, data = {}, options) {
|
|
1217
|
-
return this
|
|
1309
|
+
return this.#puppeteerService.generatePdfFromMustacheString(template, data, options);
|
|
1218
1310
|
}
|
|
1219
1311
|
/**
|
|
1220
1312
|
* @param file Path to the Mustache template file
|
|
@@ -1224,7 +1316,7 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1224
1316
|
* @description This method generates a PDF from a Mustache template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1225
1317
|
*/
|
|
1226
1318
|
generatePdfFromMustacheFile(file, data = {}, options) {
|
|
1227
|
-
return this
|
|
1319
|
+
return this.#puppeteerService.generatePdfFromMustacheFile(file, data, options);
|
|
1228
1320
|
}
|
|
1229
1321
|
/**
|
|
1230
1322
|
* @param pdf The PDF bytes to modify
|
|
@@ -1285,9 +1377,10 @@ var import_main = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1285
1377
|
defaultValue = r.join(splitter);
|
|
1286
1378
|
value = env[key];
|
|
1287
1379
|
}
|
|
1288
|
-
if (value)
|
|
1289
|
-
|
|
1290
|
-
|
|
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);
|
|
1291
1384
|
if (result === runningParsed[key]) break;
|
|
1292
1385
|
regex.lastIndex = 0;
|
|
1293
1386
|
}
|
|
@@ -1972,10 +2065,11 @@ var import_main$1 = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
|
|
|
1972
2065
|
}
|
|
1973
2066
|
function _vaultPath(options) {
|
|
1974
2067
|
let possibleVaultPath = null;
|
|
1975
|
-
if (options && options.path && options.path.length > 0)
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
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");
|
|
1979
2073
|
if (fs$2.existsSync(possibleVaultPath)) return possibleVaultPath;
|
|
1980
2074
|
return null;
|
|
1981
2075
|
}
|
|
@@ -2002,10 +2096,12 @@ var import_main$1 = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
|
|
|
2002
2096
|
if (options && options.encoding) encoding = options.encoding;
|
|
2003
2097
|
else if (debug) _debug("no encoding is specified (UTF-8 is used by default)");
|
|
2004
2098
|
let optionPaths = [dotenvPath];
|
|
2005
|
-
if (options && options.path)
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
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
|
+
}
|
|
2009
2105
|
}
|
|
2010
2106
|
let lastError;
|
|
2011
2107
|
const parsedAll = {};
|
|
@@ -2085,8 +2181,10 @@ var import_main$1 = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
|
|
|
2085
2181
|
processEnv[key] = parsed[key];
|
|
2086
2182
|
populated[key] = parsed[key];
|
|
2087
2183
|
}
|
|
2088
|
-
if (debug)
|
|
2089
|
-
|
|
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
|
+
}
|
|
2090
2188
|
} else {
|
|
2091
2189
|
processEnv[key] = parsed[key];
|
|
2092
2190
|
populated[key] = parsed[key];
|
|
@@ -2519,14 +2617,14 @@ ConfigModule = ConfigModule_1 = __decorate([Module({
|
|
|
2519
2617
|
//#region src/puppeteer/puppeteer.module.ts
|
|
2520
2618
|
var _PuppeteerModule;
|
|
2521
2619
|
let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
2522
|
-
browserService;
|
|
2523
|
-
pdfParams;
|
|
2620
|
+
#browserService;
|
|
2621
|
+
#pdfParams;
|
|
2524
2622
|
constructor(browserService, pdfParams) {
|
|
2525
|
-
this
|
|
2526
|
-
this
|
|
2623
|
+
this.#browserService = browserService;
|
|
2624
|
+
this.#pdfParams = pdfParams;
|
|
2527
2625
|
}
|
|
2528
2626
|
async onModuleInit() {
|
|
2529
|
-
if (!this
|
|
2627
|
+
if (!this.#pdfParams.executablePath) await this.#browserService.install(this.#pdfParams.useLockedBrowser ?? false);
|
|
2530
2628
|
}
|
|
2531
2629
|
static forRoot(pdfParameters) {
|
|
2532
2630
|
const providers = [
|
|
@@ -2638,6 +2736,6 @@ let NestjsPdfModule = _NestjsPdfModule = class NestjsPdfModule {
|
|
|
2638
2736
|
};
|
|
2639
2737
|
NestjsPdfModule = _NestjsPdfModule = __decorate$3([Module({})], NestjsPdfModule);
|
|
2640
2738
|
//#endregion
|
|
2641
|
-
export { EjsService, EtaService, HandlebarsService, MjmlService, MustacheService, NestjsPdfModule, NestjsPdfService, NunjucksService, PugService, PuppeteerModule, PuppeteerService, getRelativePathToValue };
|
|
2739
|
+
export { BrowserInstallationException, BrowserUnavailableException, EjsService, EngineNotAvailableException, EtaService, HandlebarsService, MjmlService, MustacheService, NestjsPdfErrorCode, NestjsPdfException, NestjsPdfModule, NestjsPdfService, NunjucksService, PdfGenerationException, PugService, PuppeteerModule, PuppeteerService, SignatureDependencyException, SignaturePlacementException, TemplateConfigurationException, TemplateRenderException, getRelativePathToValue };
|
|
2642
2740
|
|
|
2643
2741
|
//# sourceMappingURL=index.mjs.map
|