@shad0wz7/nestjs-pdf 3.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -26
- package/dist/index.cjs +213 -76
- package/dist/index.d.cts +183 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +183 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +203 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +83 -43
package/README.md
CHANGED
|
@@ -1,18 +1,5 @@
|
|
|
1
1
|
# nestjs-pdf
|
|
2
2
|
|
|
3
|
-
> **v3 — ESM-first, NestJS 10, 11 & 12.** This is the active `main` line: authored
|
|
4
|
-
> in ESM, published as a dual CJS/ESM package, and supports **NestJS 10, 11 and 12**.
|
|
5
|
-
>
|
|
6
|
-
> Need a pure CommonJS package or a Node.js version older than `20.19`? Use the
|
|
7
|
-
> maintenance `v2` branch instead:
|
|
8
|
-
>
|
|
9
|
-
> ```bash
|
|
10
|
-
> npm install @shad0wz7/nestjs-pdf@^2
|
|
11
|
-
> ```
|
|
12
|
-
>
|
|
13
|
-
> See the [`v2` branch README](https://github.com/ShadowZ11/nestjs-pdf/blob/v2/README.md)
|
|
14
|
-
> for details. It receives maintenance/security fixes only — new features land on v3.
|
|
15
|
-
|
|
16
3
|
[](https://www.npmjs.com/package/%40shad0wz7%2Fnestjs-pdf)
|
|
17
4
|
[](https://github.com/ShadowZ11/nestjs-pdf?tab=MIT-1-ov-file)
|
|
18
5
|
[](https://www.npmjs.com/package/%40shad0wz7%2Fnestjs-pdf)
|
|
@@ -20,11 +7,11 @@
|
|
|
20
7
|
[](https://codecov.io/github/ShadowZ11/nestjs-pdf)
|
|
21
8
|
[](https://www.typescriptlang.org/)
|
|
22
9
|
|
|
23
|
-
A NestJS library to generate and manipulate PDFs using Puppeteer and multiple template engines, including Handlebars, EJS, Pug, MJML, Nunjucks, Eta and
|
|
10
|
+
A NestJS library to generate and manipulate PDFs using Puppeteer and multiple template engines, including Handlebars, EJS, Pug, MJML, Nunjucks, Eta, Mustache and Liquid.
|
|
24
11
|
|
|
25
12
|
Main features:
|
|
26
13
|
|
|
27
|
-
- Generate PDFs from HTML, Handlebars, EJS, Pug, MJML, Nunjucks, Eta or
|
|
14
|
+
- Generate PDFs from HTML, Handlebars, EJS, Pug, MJML, Nunjucks, Eta, Mustache or Liquid templates
|
|
28
15
|
- Concurrency limiting for Puppeteer jobs (p-limit)
|
|
29
16
|
- Add signature fields based on a text anchor in an existing PDF
|
|
30
17
|
- Text or image watermarks (centered or tiled) on generated or existing PDFs
|
|
@@ -50,19 +37,39 @@ yarn add @shad0wz7/nestjs-pdf
|
|
|
50
37
|
pnpm add ../path/to/nestjs-pdf
|
|
51
38
|
```
|
|
52
39
|
|
|
53
|
-
|
|
40
|
+
### Template engines
|
|
54
41
|
|
|
55
|
-
|
|
42
|
+
Template engines are **optional peer dependencies**: none of them is installed with the library. Install only the ones you use, as dependencies of your own project:
|
|
43
|
+
|
|
44
|
+
| Engine | Package to install |
|
|
45
|
+
| ---------- | ------------------ |
|
|
46
|
+
| Handlebars | `handlebars` |
|
|
47
|
+
| EJS | `ejs` |
|
|
48
|
+
| Pug | `pug` |
|
|
49
|
+
| MJML | `mjml` |
|
|
50
|
+
| Nunjucks | `nunjucks` |
|
|
51
|
+
| Eta | `eta` |
|
|
52
|
+
| Mustache | `mustache` |
|
|
53
|
+
| Liquid | `liquidjs` |
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# e.g. to render Handlebars templates
|
|
57
|
+
npm install handlebars
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Engines are loaded lazily, the first time you render a template with them: your application starts fine with any subset of engines installed. Rendering with an engine whose package is missing throws an `EngineNotAvailableException` (code `ENGINE_NOT_AVAILABLE`) telling you what to install:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
Pug engine is not available: the 'pug' package is not installed. Run `npm install pug` to use it.
|
|
64
|
+
```
|
|
56
65
|
|
|
57
|
-
|
|
66
|
+
Anchor-based signature placement also relies on `pdfjs-dist`, which needs `@napi-rs/canvas` to be installed in your project (see the signature example in [Quick start](#quick-start)).
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- For Eta: `npm install eta`
|
|
65
|
-
- For Mustache: `npm install mustache`
|
|
68
|
+
> **Upgrading from v3:** engines used to be installed automatically. If you relied on that, add the engines you use to your project's dependencies.
|
|
69
|
+
|
|
70
|
+
## Quick start
|
|
71
|
+
|
|
72
|
+
Import the module and configure it in your Nest application:
|
|
66
73
|
|
|
67
74
|
```ts
|
|
68
75
|
import { Module } from '@nestjs/common';
|
|
@@ -244,6 +251,7 @@ The library exposes Puppeteer options via the `PuppeteerParameters` interface (s
|
|
|
244
251
|
| `nunjucksOptions` | The nunjucks options can be found on [Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html#configure) |
|
|
245
252
|
| `etaOptions` | The eta options can be found on [Eta documentation](https://eta.js.org/docs/4.x.x/api/configuration) |
|
|
246
253
|
| `mustacheOptions` | The mustache options can be found on [Mustache documentation](https://mustache.github.io/mustache.5.html) |
|
|
254
|
+
| `liquidOptions` | The liquid options can be found on [LiquidJS documentation](https://liquidjs.com/tutorials/options.html) |
|
|
247
255
|
| `browser` | The browser to use for the PDF generation. By default: `Browser.CHROMIUM`. Allowed values `Browser.CHROMIUM`, `Browser.CHROMEHEADLESSSHELL`, `Browser.CHROME`, `Browser.FIREFOX`, `Browser.CHROMEDRIVER` ([Official documentation of Browser](https://pptr.dev/browsers-api/browsers.browser)) |
|
|
248
256
|
| `browserTag` | The version of the browser to use for the PDF generation. By default: `BrowserTag.LATEST` if Browser is **CHROMIUM** else `BrowserTag.STABLE`. Allowed values `BrowserTag.STABLE`, `BrowserTag.LATEST`, `BrowserTag.BETA`, `BrowserTag.DEV`, `BrowserTag.CANARY` |
|
|
249
257
|
| `browserInstallBaseUrl` | The baseUrl used for the installation of the browser. This baseUrl is passed to the [`install`](https://pptr.dev/browsers-api/browsers.install) method of `@puppeteer/browsers` |
|
|
@@ -300,7 +308,7 @@ You can use `forRootAsync(...)` if you need to provide configuration asynchronou
|
|
|
300
308
|
|
|
301
309
|
## Error handling
|
|
302
310
|
|
|
303
|
-
All errors thrown by the library (missing template engine, template rendering failures, browser installation issues, PDF generation failures, signature placement issues, ...) are typed exceptions extending the abstract `NestjsPdfException` class, exported from the package root alongside a stable `NestjsPdfErrorCode` enum:
|
|
311
|
+
All errors thrown by the library (missing template engine, template rendering failures, browser installation issues, PDF generation failures, signature placement issues, invalid watermarks, ...) are typed exceptions extending the abstract `NestjsPdfException` class, exported from the package root alongside a stable `NestjsPdfErrorCode` enum:
|
|
304
312
|
|
|
305
313
|
```typescript
|
|
306
314
|
import {
|
package/dist/index.cjs
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region \0rolldown/runtime.js
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
-
get: ((k) => from[k]).bind(null, key),
|
|
14
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
20
|
-
value: mod,
|
|
21
|
-
enumerable: true
|
|
22
|
-
}) : target, mod));
|
|
23
|
-
//#endregion
|
|
24
2
|
let node_path = require("node:path");
|
|
25
3
|
let _nestjs_common = require("@nestjs/common");
|
|
26
4
|
let pdf_lib = require("pdf-lib");
|
|
@@ -31,19 +9,7 @@ let node_net = require("node:net");
|
|
|
31
9
|
let node_url = require("node:url");
|
|
32
10
|
let puppeteer = require("puppeteer");
|
|
33
11
|
let _puppeteer_browsers = require("@puppeteer/browsers");
|
|
34
|
-
let
|
|
35
|
-
ejs = __toESM(ejs, 1);
|
|
36
|
-
let eta = require("eta");
|
|
37
|
-
let handlebars = require("handlebars");
|
|
38
|
-
handlebars = __toESM(handlebars, 1);
|
|
39
|
-
let mjml = require("mjml");
|
|
40
|
-
mjml = __toESM(mjml, 1);
|
|
41
|
-
let mustache = require("mustache");
|
|
42
|
-
mustache = __toESM(mustache, 1);
|
|
43
|
-
let nunjucks = require("nunjucks");
|
|
44
|
-
nunjucks = __toESM(nunjucks, 1);
|
|
45
|
-
let pug = require("pug");
|
|
46
|
-
pug = __toESM(pug, 1);
|
|
12
|
+
let node_module = require("node:module");
|
|
47
13
|
//#region src/exceptions/nestjs-pdf.exception.ts
|
|
48
14
|
let NestjsPdfErrorCode = /* @__PURE__ */ function(NestjsPdfErrorCode) {
|
|
49
15
|
NestjsPdfErrorCode["ENGINE_NOT_AVAILABLE"] = "ENGINE_NOT_AVAILABLE";
|
|
@@ -77,8 +43,8 @@ var BrowserUnavailableException = class extends NestjsPdfException {
|
|
|
77
43
|
//#region src/exceptions/engine-not-available.exception.ts
|
|
78
44
|
var EngineNotAvailableException = class extends NestjsPdfException {
|
|
79
45
|
code = "ENGINE_NOT_AVAILABLE";
|
|
80
|
-
constructor(engineName) {
|
|
81
|
-
super(`${engineName} service is not available. If the problem persists, open an issue in the repo
|
|
46
|
+
constructor(engineName, packageName, options) {
|
|
47
|
+
super(packageName ? `${engineName} engine is not available: the '${packageName}' package is not installed. Run \`npm install ${packageName}\` to use it.` : `${engineName} service is not available. If the problem persists, open an issue in the repo.`, options);
|
|
82
48
|
}
|
|
83
49
|
};
|
|
84
50
|
//#endregion
|
|
@@ -478,7 +444,7 @@ var Queue = class {
|
|
|
478
444
|
}
|
|
479
445
|
};
|
|
480
446
|
//#endregion
|
|
481
|
-
//#region node_modules/.pnpm/p-limit@7.3.
|
|
447
|
+
//#region node_modules/.pnpm/p-limit@7.3.3/node_modules/p-limit/index.js
|
|
482
448
|
function pLimit(concurrency) {
|
|
483
449
|
let rejectOnClear = false;
|
|
484
450
|
if (typeof concurrency === "object") ({concurrency, rejectOnClear = false} = concurrency);
|
|
@@ -537,7 +503,17 @@ function pLimit(concurrency) {
|
|
|
537
503
|
}
|
|
538
504
|
},
|
|
539
505
|
map: { async value(iterable, function_) {
|
|
540
|
-
const promises =
|
|
506
|
+
const promises = [];
|
|
507
|
+
try {
|
|
508
|
+
Array.from(iterable, (value, index) => {
|
|
509
|
+
const promise = generator(function_, value, index);
|
|
510
|
+
promises.push(promise);
|
|
511
|
+
return promise;
|
|
512
|
+
});
|
|
513
|
+
} catch (error) {
|
|
514
|
+
for (const promise of promises) promise.catch(() => {});
|
|
515
|
+
throw error;
|
|
516
|
+
}
|
|
541
517
|
return Promise.all(promises);
|
|
542
518
|
} }
|
|
543
519
|
});
|
|
@@ -704,19 +680,19 @@ async function installRequestGuard(context, page, options) {
|
|
|
704
680
|
//#region src/helpers/tokens.ts
|
|
705
681
|
const PDF_PARAMETERS = "PDF_PARAMETERS";
|
|
706
682
|
//#endregion
|
|
707
|
-
//#region \0@oxc-project+runtime@0.
|
|
683
|
+
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateMetadata.js
|
|
708
684
|
function __decorateMetadata(k, v) {
|
|
709
685
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
710
686
|
}
|
|
711
687
|
//#endregion
|
|
712
|
-
//#region \0@oxc-project+runtime@0.
|
|
688
|
+
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateParam.js
|
|
713
689
|
function __decorateParam(paramIndex, decorator) {
|
|
714
690
|
return function(target, key) {
|
|
715
691
|
decorator(target, key, paramIndex);
|
|
716
692
|
};
|
|
717
693
|
}
|
|
718
694
|
//#endregion
|
|
719
|
-
//#region \0@oxc-project+runtime@0.
|
|
695
|
+
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorate.js
|
|
720
696
|
function __decorate(decorators, target, key, desc) {
|
|
721
697
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
722
698
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -991,11 +967,34 @@ BrowserService = __decorate([
|
|
|
991
967
|
__decorateMetadata("design:paramtypes", [Object])
|
|
992
968
|
], BrowserService);
|
|
993
969
|
//#endregion
|
|
970
|
+
//#region src/puppeteer/libs/loadEngine.utils.ts
|
|
971
|
+
const requireEngine = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
972
|
+
/**
|
|
973
|
+
* Load an optional template engine on first use, so the library can be imported
|
|
974
|
+
* without every engine installed. `require` (not `import()`) is used on purpose:
|
|
975
|
+
* most engines expose a synchronous render API.
|
|
976
|
+
*/
|
|
977
|
+
function loadEngine(packageName, engineName) {
|
|
978
|
+
let mod;
|
|
979
|
+
try {
|
|
980
|
+
mod = requireEngine(packageName);
|
|
981
|
+
} catch (error) {
|
|
982
|
+
if (error.code === "MODULE_NOT_FOUND") throw new EngineNotAvailableException(engineName, packageName, { cause: error });
|
|
983
|
+
throw error;
|
|
984
|
+
}
|
|
985
|
+
return mod.__esModule && "default" in mod ? mod.default : mod;
|
|
986
|
+
}
|
|
987
|
+
//#endregion
|
|
994
988
|
//#region src/puppeteer/engines/ejs/ejs.service.ts
|
|
995
989
|
let EjsService = class EjsService {
|
|
990
|
+
#ejs;
|
|
991
|
+
get #engine() {
|
|
992
|
+
return this.#ejs ??= loadEngine("ejs", "EJS");
|
|
993
|
+
}
|
|
996
994
|
async render(template, data = {}, options) {
|
|
995
|
+
const engine = this.#engine;
|
|
997
996
|
try {
|
|
998
|
-
return await
|
|
997
|
+
return await engine.render(template, data, {
|
|
999
998
|
async: true,
|
|
1000
999
|
...options
|
|
1001
1000
|
});
|
|
@@ -1004,8 +1003,9 @@ let EjsService = class EjsService {
|
|
|
1004
1003
|
}
|
|
1005
1004
|
}
|
|
1006
1005
|
async renderFile(filePath, data = {}, options) {
|
|
1006
|
+
const engine = this.#engine;
|
|
1007
1007
|
try {
|
|
1008
|
-
return await
|
|
1008
|
+
return await engine.renderFile(filePath, data, {
|
|
1009
1009
|
async: true,
|
|
1010
1010
|
...options
|
|
1011
1011
|
});
|
|
@@ -1018,15 +1018,12 @@ EjsService = __decorate([(0, _nestjs_common.Injectable)()], EjsService);
|
|
|
1018
1018
|
//#endregion
|
|
1019
1019
|
//#region src/puppeteer/engines/eta/eta.service.ts
|
|
1020
1020
|
let EtaService = class EtaService {
|
|
1021
|
+
#etaModule;
|
|
1021
1022
|
#eta;
|
|
1022
1023
|
#templateCache = /* @__PURE__ */ new Map();
|
|
1023
1024
|
#maxCacheSize = 100;
|
|
1024
|
-
|
|
1025
|
-
this.#
|
|
1026
|
-
cache: true,
|
|
1027
|
-
autoEscape: true,
|
|
1028
|
-
useWith: true
|
|
1029
|
-
});
|
|
1025
|
+
get #engine() {
|
|
1026
|
+
return this.#etaModule ??= loadEngine("eta", "Eta");
|
|
1030
1027
|
}
|
|
1031
1028
|
/**
|
|
1032
1029
|
* Render an Eta template from a string
|
|
@@ -1036,14 +1033,19 @@ let EtaService = class EtaService {
|
|
|
1036
1033
|
* @returns The rendered HTML string
|
|
1037
1034
|
*/
|
|
1038
1035
|
render(template, data = {}, options) {
|
|
1036
|
+
const { Eta } = this.#engine;
|
|
1039
1037
|
try {
|
|
1040
|
-
return (options && Object.keys(options).length > 0 ? new
|
|
1038
|
+
return (options && Object.keys(options).length > 0 ? new Eta({
|
|
1041
1039
|
cache: true,
|
|
1042
1040
|
autoEscape: true,
|
|
1043
1041
|
useWith: true,
|
|
1044
1042
|
...options,
|
|
1045
1043
|
varName: options.varName ?? "it"
|
|
1046
|
-
}) : this.#eta
|
|
1044
|
+
}) : this.#eta ??= new Eta({
|
|
1045
|
+
cache: true,
|
|
1046
|
+
autoEscape: true,
|
|
1047
|
+
useWith: true
|
|
1048
|
+
})).renderString(template, data);
|
|
1047
1049
|
} catch (error) {
|
|
1048
1050
|
throw new TemplateRenderException("Eta", `Eta rendering failed: ${String(error)}`, { cause: error });
|
|
1049
1051
|
}
|
|
@@ -1066,6 +1068,7 @@ let EtaService = class EtaService {
|
|
|
1066
1068
|
}
|
|
1067
1069
|
return this.render(template, data, options);
|
|
1068
1070
|
} catch (error) {
|
|
1071
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1069
1072
|
throw new TemplateRenderException("Eta", `Eta file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
1070
1073
|
}
|
|
1071
1074
|
}
|
|
@@ -1083,12 +1086,16 @@ let EtaService = class EtaService {
|
|
|
1083
1086
|
return this.#templateCache.size;
|
|
1084
1087
|
}
|
|
1085
1088
|
};
|
|
1086
|
-
EtaService = __decorate([(0, _nestjs_common.Injectable)()
|
|
1089
|
+
EtaService = __decorate([(0, _nestjs_common.Injectable)()], EtaService);
|
|
1087
1090
|
//#endregion
|
|
1088
1091
|
//#region src/puppeteer/engines/handlebars/handlebars.service.ts
|
|
1089
1092
|
let HandlebarsService = class HandlebarsService {
|
|
1093
|
+
#handlebars;
|
|
1090
1094
|
#cachedOptions;
|
|
1091
1095
|
#cachedEnv;
|
|
1096
|
+
get #engine() {
|
|
1097
|
+
return this.#handlebars ??= loadEngine("handlebars", "Handlebars");
|
|
1098
|
+
}
|
|
1092
1099
|
render(template, parameters = {}, options = {}) {
|
|
1093
1100
|
try {
|
|
1094
1101
|
return this.#getEnv(options).compile(template, options.compileOptions)(parameters, options.templateOptions);
|
|
@@ -1117,7 +1124,7 @@ let HandlebarsService = class HandlebarsService {
|
|
|
1117
1124
|
*/
|
|
1118
1125
|
#getEnv(options) {
|
|
1119
1126
|
if (this.#cachedEnv && this.#cachedOptions === options) return this.#cachedEnv;
|
|
1120
|
-
const env =
|
|
1127
|
+
const env = this.#engine.create();
|
|
1121
1128
|
for (const helper of options.helpers ?? []) env.registerHelper(helper.name, helper.fn);
|
|
1122
1129
|
this.#registerPartials(env, options.partialDirectory);
|
|
1123
1130
|
this.#cachedOptions = options;
|
|
@@ -1137,11 +1144,78 @@ let HandlebarsService = class HandlebarsService {
|
|
|
1137
1144
|
};
|
|
1138
1145
|
HandlebarsService = __decorate([(0, _nestjs_common.Injectable)()], HandlebarsService);
|
|
1139
1146
|
//#endregion
|
|
1147
|
+
//#region src/puppeteer/engines/liquid/liquid.service.ts
|
|
1148
|
+
let LiquidService = class LiquidService {
|
|
1149
|
+
#liquidModule;
|
|
1150
|
+
#liquid;
|
|
1151
|
+
#templateCache = /* @__PURE__ */ new Map();
|
|
1152
|
+
#maxCacheSize = 100;
|
|
1153
|
+
get #engine() {
|
|
1154
|
+
return this.#liquidModule ??= loadEngine("liquidjs", "Liquid");
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Render a Liquid template from a string
|
|
1158
|
+
* @param template The template string to render
|
|
1159
|
+
* @param data The data object to use for rendering
|
|
1160
|
+
* @param options Optional Liquid engine options
|
|
1161
|
+
* @returns The rendered HTML string
|
|
1162
|
+
*/
|
|
1163
|
+
render(template, data = {}, options) {
|
|
1164
|
+
const { Liquid } = this.#engine;
|
|
1165
|
+
try {
|
|
1166
|
+
return (options && Object.keys(options).length > 0 ? new Liquid(options) : this.#liquid ??= new Liquid()).parseAndRenderSync(template, data);
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
throw new TemplateRenderException("Liquid", `Liquid rendering failed: ${String(error)}`, { cause: error });
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Render a Liquid template from a file
|
|
1173
|
+
* @param filePath The path to the template file
|
|
1174
|
+
* @param data The data object to use for rendering
|
|
1175
|
+
* @param options Optional Liquid engine options
|
|
1176
|
+
* @returns The rendered HTML string
|
|
1177
|
+
*/
|
|
1178
|
+
renderFile(filePath, data = {}, options) {
|
|
1179
|
+
try {
|
|
1180
|
+
const resolvedPath = (0, node_path.resolve)(filePath);
|
|
1181
|
+
const useCache = options?.cache !== false;
|
|
1182
|
+
let template = useCache ? this.#templateCache.get(resolvedPath) : void 0;
|
|
1183
|
+
if (!template) {
|
|
1184
|
+
template = (0, node_fs.readFileSync)(resolvedPath, "utf-8");
|
|
1185
|
+
if (useCache && this.#templateCache.size < this.#maxCacheSize) this.#templateCache.set(resolvedPath, template);
|
|
1186
|
+
}
|
|
1187
|
+
return this.render(template, data, options);
|
|
1188
|
+
} catch (error) {
|
|
1189
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1190
|
+
throw new TemplateRenderException("Liquid", `Liquid file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Clear the template cache
|
|
1195
|
+
*/
|
|
1196
|
+
clearCache() {
|
|
1197
|
+
this.#templateCache.clear();
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Get the current cache size
|
|
1201
|
+
* @returns The number of cached templates
|
|
1202
|
+
*/
|
|
1203
|
+
getCacheSize() {
|
|
1204
|
+
return this.#templateCache.size;
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
LiquidService = __decorate([(0, _nestjs_common.Injectable)()], LiquidService);
|
|
1208
|
+
//#endregion
|
|
1140
1209
|
//#region src/puppeteer/engines/mjml/mjml.service.ts
|
|
1141
1210
|
let MjmlService = class MjmlService {
|
|
1211
|
+
#mjml;
|
|
1212
|
+
get #engine() {
|
|
1213
|
+
return this.#mjml ??= loadEngine("mjml", "MJML");
|
|
1214
|
+
}
|
|
1142
1215
|
async render(template, options) {
|
|
1216
|
+
const engine = this.#engine;
|
|
1143
1217
|
try {
|
|
1144
|
-
const { html } = await (
|
|
1218
|
+
const { html } = await engine(template, options);
|
|
1145
1219
|
return html;
|
|
1146
1220
|
} catch (error) {
|
|
1147
1221
|
throw new TemplateRenderException("MJML", `MJML rendering failed: ${String(error)}`, { cause: error });
|
|
@@ -1161,8 +1235,12 @@ MjmlService = __decorate([(0, _nestjs_common.Injectable)()], MjmlService);
|
|
|
1161
1235
|
//#endregion
|
|
1162
1236
|
//#region src/puppeteer/engines/mustache/mustache.service.ts
|
|
1163
1237
|
let MustacheService = class MustacheService {
|
|
1238
|
+
#mustache;
|
|
1164
1239
|
#templateCache = /* @__PURE__ */ new Map();
|
|
1165
1240
|
#maxCacheSize = 100;
|
|
1241
|
+
get #engine() {
|
|
1242
|
+
return this.#mustache ??= loadEngine("mustache", "Mustache");
|
|
1243
|
+
}
|
|
1166
1244
|
/**
|
|
1167
1245
|
* Render a Mustache template from a string
|
|
1168
1246
|
* @param template The template string to render
|
|
@@ -1171,9 +1249,10 @@ let MustacheService = class MustacheService {
|
|
|
1171
1249
|
* @returns The rendered HTML string
|
|
1172
1250
|
*/
|
|
1173
1251
|
render(template, data = {}, options) {
|
|
1252
|
+
const engine = this.#engine;
|
|
1174
1253
|
try {
|
|
1175
1254
|
const tags = options?.tags ?? ["{{", "}}"];
|
|
1176
|
-
return
|
|
1255
|
+
return engine.render(template, data, void 0, {
|
|
1177
1256
|
tags,
|
|
1178
1257
|
escape: options?.escape
|
|
1179
1258
|
});
|
|
@@ -1198,6 +1277,7 @@ let MustacheService = class MustacheService {
|
|
|
1198
1277
|
}
|
|
1199
1278
|
return this.render(template, data, options);
|
|
1200
1279
|
} catch (error) {
|
|
1280
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1201
1281
|
throw new TemplateRenderException("Mustache", `Mustache file rendering failed for ${filePath}: ${String(error)}`, { cause: error });
|
|
1202
1282
|
}
|
|
1203
1283
|
}
|
|
@@ -1219,14 +1299,20 @@ MustacheService = __decorate([(0, _nestjs_common.Injectable)()], MustacheService
|
|
|
1219
1299
|
//#endregion
|
|
1220
1300
|
//#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
1221
1301
|
let NunjucksService = class NunjucksService {
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1302
|
+
#nunjucks;
|
|
1303
|
+
get #engine() {
|
|
1304
|
+
if (!this.#nunjucks) {
|
|
1305
|
+
this.#nunjucks = loadEngine("nunjucks", "Nunjucks");
|
|
1306
|
+
this.#nunjucks.configure({
|
|
1307
|
+
noCache: true,
|
|
1308
|
+
trimBlocks: true,
|
|
1309
|
+
lstripBlocks: true
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
return this.#nunjucks;
|
|
1228
1313
|
}
|
|
1229
1314
|
render(template, data = {}, options) {
|
|
1315
|
+
const nunjucks = this.#engine;
|
|
1230
1316
|
try {
|
|
1231
1317
|
if (options) {
|
|
1232
1318
|
const configOptions = {
|
|
@@ -1236,14 +1322,15 @@ let NunjucksService = class NunjucksService {
|
|
|
1236
1322
|
trimBlocks: options.trimBlocks ?? true,
|
|
1237
1323
|
lstripBlocks: options.lstripBlocks ?? true
|
|
1238
1324
|
};
|
|
1239
|
-
nunjucks.
|
|
1325
|
+
nunjucks.configure(configOptions);
|
|
1240
1326
|
}
|
|
1241
|
-
return nunjucks.
|
|
1327
|
+
return nunjucks.renderString(template, data);
|
|
1242
1328
|
} catch (error) {
|
|
1243
1329
|
throw new TemplateRenderException("Nunjucks", `Nunjucks rendering failed: ${String(error)}`, { cause: error });
|
|
1244
1330
|
}
|
|
1245
1331
|
}
|
|
1246
1332
|
renderFile(filePath, data = {}, options) {
|
|
1333
|
+
const nunjucks = this.#engine;
|
|
1247
1334
|
try {
|
|
1248
1335
|
if (options) {
|
|
1249
1336
|
const configOptions = {
|
|
@@ -1253,21 +1340,26 @@ let NunjucksService = class NunjucksService {
|
|
|
1253
1340
|
trimBlocks: options.trimBlocks ?? true,
|
|
1254
1341
|
lstripBlocks: options.lstripBlocks ?? true
|
|
1255
1342
|
};
|
|
1256
|
-
nunjucks.
|
|
1343
|
+
nunjucks.configure(configOptions);
|
|
1257
1344
|
}
|
|
1258
|
-
return nunjucks.
|
|
1345
|
+
return nunjucks.render(filePath, data);
|
|
1259
1346
|
} catch (error) {
|
|
1260
1347
|
throw new TemplateRenderException("Nunjucks", `Nunjucks file rendering failed: ${String(error)}`, { cause: error });
|
|
1261
1348
|
}
|
|
1262
1349
|
}
|
|
1263
1350
|
};
|
|
1264
|
-
NunjucksService = __decorate([(0, _nestjs_common.Injectable)()
|
|
1351
|
+
NunjucksService = __decorate([(0, _nestjs_common.Injectable)()], NunjucksService);
|
|
1265
1352
|
//#endregion
|
|
1266
1353
|
//#region src/puppeteer/engines/pug/pug.service.ts
|
|
1267
1354
|
let PugService = class PugService {
|
|
1355
|
+
#pug;
|
|
1356
|
+
get #engine() {
|
|
1357
|
+
return this.#pug ??= loadEngine("pug", "Pug");
|
|
1358
|
+
}
|
|
1268
1359
|
render(template, data = {}, options) {
|
|
1360
|
+
const engine = this.#engine;
|
|
1269
1361
|
try {
|
|
1270
|
-
return
|
|
1362
|
+
return engine.compile(template, { ...options })(data);
|
|
1271
1363
|
} catch (error) {
|
|
1272
1364
|
throw new TemplateRenderException("Pug", `Pug rendering failed: ${String(error)}`, { cause: error });
|
|
1273
1365
|
}
|
|
@@ -1277,6 +1369,7 @@ let PugService = class PugService {
|
|
|
1277
1369
|
const template = (0, node_fs.readFileSync)(filePath, "utf-8");
|
|
1278
1370
|
return this.render(template, data, options);
|
|
1279
1371
|
} catch (error) {
|
|
1372
|
+
if (error instanceof EngineNotAvailableException) throw error;
|
|
1280
1373
|
throw new TemplateRenderException("Pug", `Pug file rendering failed: ${String(error)}`, { cause: error });
|
|
1281
1374
|
}
|
|
1282
1375
|
}
|
|
@@ -1300,7 +1393,8 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1300
1393
|
#nunjucksService;
|
|
1301
1394
|
#etaService;
|
|
1302
1395
|
#mustacheService;
|
|
1303
|
-
|
|
1396
|
+
#liquidService;
|
|
1397
|
+
constructor(browserService, options, hbsService, mjmlService, pugService, ejsService, nunjucksService, etaService, mustacheService, liquidService) {
|
|
1304
1398
|
this.#browserService = browserService;
|
|
1305
1399
|
this.#options = options;
|
|
1306
1400
|
this.#hbsService = hbsService;
|
|
@@ -1310,6 +1404,7 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1310
1404
|
this.#nunjucksService = nunjucksService;
|
|
1311
1405
|
this.#etaService = etaService;
|
|
1312
1406
|
this.#mustacheService = mustacheService;
|
|
1407
|
+
this.#liquidService = liquidService;
|
|
1313
1408
|
}
|
|
1314
1409
|
#limit = pLimit(3);
|
|
1315
1410
|
async generatePdfFromHtml(html, options) {
|
|
@@ -1472,6 +1567,14 @@ let PuppeteerService = class PuppeteerService {
|
|
|
1472
1567
|
const html = requireService(this.#mustacheService, "Mustache").renderFile(file, data, options?.mustacheOptions ?? this.#options.mustacheOptions);
|
|
1473
1568
|
return this.generatePdfFromHtml(html, options);
|
|
1474
1569
|
}
|
|
1570
|
+
async generatePdfFromLiquidString(template, data = {}, options) {
|
|
1571
|
+
const html = requireService(this.#liquidService, "Liquid").render(template, data, options?.liquidOptions ?? this.#options.liquidOptions);
|
|
1572
|
+
return this.generatePdfFromHtml(html, options);
|
|
1573
|
+
}
|
|
1574
|
+
async generatePdfFromLiquidFile(file, data = {}, options) {
|
|
1575
|
+
const html = requireService(this.#liquidService, "Liquid").renderFile(file, data, options?.liquidOptions ?? this.#options.liquidOptions);
|
|
1576
|
+
return this.generatePdfFromHtml(html, options);
|
|
1577
|
+
}
|
|
1475
1578
|
};
|
|
1476
1579
|
PuppeteerService = __decorate([
|
|
1477
1580
|
(0, _nestjs_common.Injectable)(),
|
|
@@ -1483,6 +1586,7 @@ PuppeteerService = __decorate([
|
|
|
1483
1586
|
__decorateParam(6, (0, _nestjs_common.Optional)()),
|
|
1484
1587
|
__decorateParam(7, (0, _nestjs_common.Optional)()),
|
|
1485
1588
|
__decorateParam(8, (0, _nestjs_common.Optional)()),
|
|
1589
|
+
__decorateParam(9, (0, _nestjs_common.Optional)()),
|
|
1486
1590
|
__decorateMetadata("design:paramtypes", [
|
|
1487
1591
|
typeof BrowserService === "undefined" ? Object : BrowserService,
|
|
1488
1592
|
Object,
|
|
@@ -1492,7 +1596,8 @@ PuppeteerService = __decorate([
|
|
|
1492
1596
|
typeof EjsService === "undefined" ? Object : EjsService,
|
|
1493
1597
|
typeof NunjucksService === "undefined" ? Object : NunjucksService,
|
|
1494
1598
|
typeof EtaService === "undefined" ? Object : EtaService,
|
|
1495
|
-
typeof MustacheService === "undefined" ? Object : MustacheService
|
|
1599
|
+
typeof MustacheService === "undefined" ? Object : MustacheService,
|
|
1600
|
+
typeof LiquidService === "undefined" ? Object : LiquidService
|
|
1496
1601
|
])
|
|
1497
1602
|
], PuppeteerService);
|
|
1498
1603
|
//#endregion
|
|
@@ -1650,6 +1755,26 @@ let NestjsPdfService = class NestjsPdfService {
|
|
|
1650
1755
|
return this.#puppeteerService.generatePdfFromMustacheFile(file, data, options);
|
|
1651
1756
|
}
|
|
1652
1757
|
/**
|
|
1758
|
+
* @param template Liquid template string
|
|
1759
|
+
* @param data Data to inject into the template
|
|
1760
|
+
* @param options PDF generation options (optional)
|
|
1761
|
+
* @returns PDF generated from the provided Liquid template with data applied
|
|
1762
|
+
* @description This method generates a PDF from a Liquid template provided as a string. Liquid is a safe, Shopify-compatible template language with filters, tags, partials and layouts. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1763
|
+
*/
|
|
1764
|
+
generatePdfFromLiquidString(template, data = {}, options) {
|
|
1765
|
+
return this.#puppeteerService.generatePdfFromLiquidString(template, data, options);
|
|
1766
|
+
}
|
|
1767
|
+
/**
|
|
1768
|
+
* @param file Path to the Liquid template file
|
|
1769
|
+
* @param data Data to inject into the template
|
|
1770
|
+
* @param options PDF generation options (optional)
|
|
1771
|
+
* @returns PDF generated from the Liquid template at the provided file path with data applied
|
|
1772
|
+
* @description This method generates a PDF from a Liquid template located at the specified file path. The file path is passed as a string in the `file` parameter. The data to inject into the template is passed in the `data` object, which is used to render the template before converting it to PDF. PDF generation options can be customized by passing a `PuppeteerParameters` object as the third argument.
|
|
1773
|
+
*/
|
|
1774
|
+
generatePdfFromLiquidFile(file, data = {}, options) {
|
|
1775
|
+
return this.#puppeteerService.generatePdfFromLiquidFile(file, data, options);
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1653
1778
|
* @param pdf The PDF bytes to modify
|
|
1654
1779
|
* @param fieldName The name of the signature field to add (default: 'SignatureDebtor')
|
|
1655
1780
|
* @param anchorText The text anchor to locate the signature field position (default: '__SIG_DEBTOR_ANCHOR__')
|
|
@@ -1723,7 +1848,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1723
1848
|
EjsService,
|
|
1724
1849
|
NunjucksService,
|
|
1725
1850
|
EtaService,
|
|
1726
|
-
MustacheService
|
|
1851
|
+
MustacheService,
|
|
1852
|
+
LiquidService
|
|
1727
1853
|
],
|
|
1728
1854
|
exports: [
|
|
1729
1855
|
PuppeteerService,
|
|
@@ -1732,7 +1858,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1732
1858
|
EjsService,
|
|
1733
1859
|
NunjucksService,
|
|
1734
1860
|
EtaService,
|
|
1735
|
-
MustacheService
|
|
1861
|
+
MustacheService,
|
|
1862
|
+
LiquidService
|
|
1736
1863
|
]
|
|
1737
1864
|
};
|
|
1738
1865
|
}
|
|
@@ -1755,7 +1882,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1755
1882
|
EjsService,
|
|
1756
1883
|
NunjucksService,
|
|
1757
1884
|
EtaService,
|
|
1758
|
-
MustacheService
|
|
1885
|
+
MustacheService,
|
|
1886
|
+
LiquidService
|
|
1759
1887
|
],
|
|
1760
1888
|
exports: [
|
|
1761
1889
|
PuppeteerService,
|
|
@@ -1764,7 +1892,8 @@ let PuppeteerModule = _PuppeteerModule = class PuppeteerModule {
|
|
|
1764
1892
|
EjsService,
|
|
1765
1893
|
NunjucksService,
|
|
1766
1894
|
EtaService,
|
|
1767
|
-
MustacheService
|
|
1895
|
+
MustacheService,
|
|
1896
|
+
LiquidService
|
|
1768
1897
|
]
|
|
1769
1898
|
};
|
|
1770
1899
|
}
|
|
@@ -1779,7 +1908,8 @@ PuppeteerModule = _PuppeteerModule = __decorate([
|
|
|
1779
1908
|
EjsService,
|
|
1780
1909
|
NunjucksService,
|
|
1781
1910
|
EtaService,
|
|
1782
|
-
MustacheService
|
|
1911
|
+
MustacheService,
|
|
1912
|
+
LiquidService
|
|
1783
1913
|
],
|
|
1784
1914
|
exports: [
|
|
1785
1915
|
PuppeteerService,
|
|
@@ -1788,7 +1918,8 @@ PuppeteerModule = _PuppeteerModule = __decorate([
|
|
|
1788
1918
|
EjsService,
|
|
1789
1919
|
NunjucksService,
|
|
1790
1920
|
EtaService,
|
|
1791
|
-
MustacheService
|
|
1921
|
+
MustacheService,
|
|
1922
|
+
LiquidService
|
|
1792
1923
|
]
|
|
1793
1924
|
}),
|
|
1794
1925
|
__decorateParam(1, (0, _nestjs_common.Inject)(PDF_PARAMETERS)),
|
|
@@ -1838,6 +1969,12 @@ Object.defineProperty(exports, "HandlebarsService", {
|
|
|
1838
1969
|
return HandlebarsService;
|
|
1839
1970
|
}
|
|
1840
1971
|
});
|
|
1972
|
+
Object.defineProperty(exports, "LiquidService", {
|
|
1973
|
+
enumerable: true,
|
|
1974
|
+
get: function() {
|
|
1975
|
+
return LiquidService;
|
|
1976
|
+
}
|
|
1977
|
+
});
|
|
1841
1978
|
Object.defineProperty(exports, "MjmlService", {
|
|
1842
1979
|
enumerable: true,
|
|
1843
1980
|
get: function() {
|