@shad0wz7/nestjs-pdf 3.2.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -30
- package/dist/index.cjs +723 -243
- package/dist/index.d.cts +320 -88
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +320 -88
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +702 -201
- package/dist/index.mjs.map +1 -1
- package/package.json +100 -50
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,12 +7,13 @@
|
|
|
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
|
|
10
|
+
A NestJS library to generate and manipulate PDFs from multiple template engines (Handlebars, EJS, Pug, MJML, Nunjucks, Eta, Mustache and Liquid), printed by a local Puppeteer browser, a [Gotenberg](https://gotenberg.dev) server or the [Api2Pdf](https://www.api2pdf.com) API.
|
|
24
11
|
|
|
25
12
|
Main features:
|
|
26
13
|
|
|
27
|
-
- Generate PDFs from HTML, Handlebars, EJS, Pug, MJML, Nunjucks, Eta or
|
|
28
|
-
-
|
|
14
|
+
- Generate PDFs from HTML, Handlebars, EJS, Pug, MJML, Nunjucks, Eta, Mustache or Liquid templates
|
|
15
|
+
- Pluggable PDF providers: local Puppeteer (default), Gotenberg or Api2Pdf, behind the same service API
|
|
16
|
+
- Concurrency limiting for PDF jobs (p-limit)
|
|
29
17
|
- Add signature fields based on a text anchor in an existing PDF
|
|
30
18
|
- Text or image watermarks (centered or tiled) on generated or existing PDFs
|
|
31
19
|
- Simple API (module and service) to integrate easily into a Nest application
|
|
@@ -50,19 +38,53 @@ yarn add @shad0wz7/nestjs-pdf
|
|
|
50
38
|
pnpm add ../path/to/nestjs-pdf
|
|
51
39
|
```
|
|
52
40
|
|
|
53
|
-
|
|
41
|
+
### PDF provider
|
|
54
42
|
|
|
55
|
-
|
|
43
|
+
Pick who prints the PDFs and install what it needs:
|
|
44
|
+
|
|
45
|
+
| Provider | Install | Notes |
|
|
46
|
+
| --------------------- | ------------------------------------------- | -------------------------------------------------------------------- |
|
|
47
|
+
| `puppeteer` (default) | `npm install puppeteer @puppeteer/browsers` | Local Chromium, downloaded on startup unless `executablePath` is set |
|
|
48
|
+
| `gotenberg` | nothing | Needs a [Gotenberg 8](https://gotenberg.dev) server |
|
|
49
|
+
| `api2pdf` | nothing | Needs an [Api2Pdf](https://www.api2pdf.com) API key |
|
|
50
|
+
|
|
51
|
+
`puppeteer` and `@puppeteer/browsers` are **optional peer dependencies**: with a remote provider, no browser is installed nor downloaded. The `puppeteer` provider needs **both** packages: if either is missing, the application fails on startup with an `EngineNotAvailableException` telling you what to install. With `executablePath`, the browser is not downloaded, so only `puppeteer` is needed. See [PDF providers](#pdf-providers) to configure Gotenberg or Api2Pdf.
|
|
52
|
+
|
|
53
|
+
### Template engines
|
|
54
|
+
|
|
55
|
+
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:
|
|
56
|
+
|
|
57
|
+
| Engine | Package to install |
|
|
58
|
+
| ---------- | ------------------ |
|
|
59
|
+
| Handlebars | `handlebars` |
|
|
60
|
+
| EJS | `ejs` |
|
|
61
|
+
| Pug | `pug` |
|
|
62
|
+
| MJML | `mjml` |
|
|
63
|
+
| Nunjucks | `nunjucks` |
|
|
64
|
+
| Eta | `eta` |
|
|
65
|
+
| Mustache | `mustache` |
|
|
66
|
+
| Liquid | `liquidjs` |
|
|
56
67
|
|
|
57
|
-
|
|
68
|
+
```bash
|
|
69
|
+
# e.g. to render Handlebars templates
|
|
70
|
+
npm install handlebars
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
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:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
Pug engine is not available: the 'pug' package is not installed. Run `npm install pug` to use it.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
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
80
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
81
|
+
> **Upgrading from v3:** engines used to be installed automatically. If you relied on that, add the engines you use to your project's dependencies.
|
|
82
|
+
|
|
83
|
+
> **Upgrading from v4:** Puppeteer is no longer installed with the library. If you keep the default provider, add it to your project: `npm install puppeteer @puppeteer/browsers`. `NestjsPdfErrorCode` also gained a `RENDERER_CONFIGURATION_ERROR` member: update any exhaustive `Record<NestjsPdfErrorCode, …>` map. `pdfOptions` is now typed by the library's own `PdfOptions` (same shape as Puppeteer's `PDFOptions`) and `browser` accepts plain strings (`'chromium'`) as well as the `Browser` enum, so the published types no longer depend on Puppeteer.
|
|
84
|
+
|
|
85
|
+
## Quick start
|
|
86
|
+
|
|
87
|
+
Import the module and configure it in your Nest application:
|
|
66
88
|
|
|
67
89
|
```ts
|
|
68
90
|
import { Module } from '@nestjs/common';
|
|
@@ -227,16 +249,92 @@ Good to know:
|
|
|
227
249
|
- Names are checked by resolving them before the request, so a domain that changes its address between the check and the request (DNS rebinding) can slip through. Use `allowedHosts` (or `javascriptEnabled: false`) when the content is fully untrusted.
|
|
228
250
|
- `window.open` pop-ups are blocked: the library no longer passes `--disable-popup-blocking` to Chrome. If you set `extraPuppeteerArgs`, do not add it back.
|
|
229
251
|
|
|
252
|
+
## PDF providers
|
|
253
|
+
|
|
254
|
+
Templates, watermarks and signatures always run in your application; the provider only turns the rendered HTML into a PDF. Choose it with `provider` in `forRoot` / `forRootAsync` (it is ignored in per-call options):
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
// Gotenberg (self-hosted): docker run --rm -p 3000:3000 gotenberg/gotenberg:8
|
|
258
|
+
NestjsPdfModule.forRoot({
|
|
259
|
+
provider: {
|
|
260
|
+
type: 'gotenberg',
|
|
261
|
+
url: 'http://localhost:3000',
|
|
262
|
+
// optional: when Gotenberg runs with --api-enable-basic-auth
|
|
263
|
+
basicAuth: { username: 'user', password: 'pass' },
|
|
264
|
+
// optional: extra headers, e.g. for an authenticating proxy
|
|
265
|
+
headers: { 'X-Api-Key': '...' },
|
|
266
|
+
},
|
|
267
|
+
pdfOptions: { format: 'A4', printBackground: true },
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Api2Pdf (SaaS)
|
|
271
|
+
NestjsPdfModule.forRootAsync({
|
|
272
|
+
inject: [ConfigService],
|
|
273
|
+
useFactory: (config: ConfigService) => ({
|
|
274
|
+
provider: { type: 'api2pdf', apiKey: config.getOrThrow('API2PDF_KEY') },
|
|
275
|
+
}),
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The service API does not change: `generatePdfFromHtml`, every `generatePdfFrom<Engine>*` method, `watermark` and `signal` work the same with every provider. A missing `url` / `apiKey` or an unknown `type` throws a `RendererConfigurationException` on startup.
|
|
280
|
+
|
|
281
|
+
### Page options
|
|
282
|
+
|
|
283
|
+
Keep using `pdfOptions` (Puppeteer's format). For Gotenberg and Api2Pdf, these fields are translated: `format`, `width`, `height`, `margin` (numbers are pixels; strings in `px`, `in`, `cm` or `mm`), `landscape`, `printBackground`, `omitBackground`, `scale`, `pageRanges`, `displayHeaderFooter` with `headerTemplate` / `footerTemplate`, plus `preferCSSPageSize`, `tagged` and `outline` for Gotenberg. The other fields are ignored. Like the Puppeteer provider, the page is rendered with the `screen` media type, and with zero margins unless you set them.
|
|
284
|
+
|
|
285
|
+
Provider-specific options, per call or in `forRoot`:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
await pdfService.generatePdfFromHtml(
|
|
289
|
+
'<img src="logo.png"><link rel="stylesheet" href="style.css">',
|
|
290
|
+
{
|
|
291
|
+
gotenbergOptions: {
|
|
292
|
+
// files the HTML references by relative name, sent next to index.html
|
|
293
|
+
assets: [
|
|
294
|
+
{
|
|
295
|
+
filename: 'logo.png',
|
|
296
|
+
content: await readFile('logo.png'),
|
|
297
|
+
contentType: 'image/png',
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
filename: 'style.css',
|
|
301
|
+
content: 'body { font-family: sans-serif; }',
|
|
302
|
+
contentType: 'text/css',
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
// any Gotenberg Chromium form field (PDF/A, wait...), wins over the derived ones
|
|
306
|
+
formFields: { pdfa: 'PDF/A-2b', waitDelay: '500ms' },
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
await pdfService.generatePdfFromHtml(html, {
|
|
312
|
+
// any Api2Pdf Chrome option, merged over the derived ones
|
|
313
|
+
api2pdfOptions: { fileName: 'invoice.pdf', options: { delay: 500 } },
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Good to know
|
|
318
|
+
|
|
319
|
+
- **Local files:** a remote provider cannot read your disk. With Gotenberg, send images, fonts and CSS as `assets`; with Api2Pdf, use public URLs or inline them (`data:` URIs).
|
|
320
|
+
- **`security` is Puppeteer-only:** the request filter runs in the local browser, so with a remote provider it throws a `RendererConfigurationException` instead of being silently skipped. With Gotenberg, restrict outbound requests on the server (`--chromium-allow-list`, `--chromium-deny-list`); with Api2Pdf, only render HTML you trust.
|
|
321
|
+
- **With Api2Pdf, data leaves your infrastructure:** the HTML is sent to a third-party service, which matters for personal data (GDPR). Gotenberg stays on your own servers.
|
|
322
|
+
- **Errors:** an HTTP error from the provider becomes a `PdfGenerationException` whose message holds the status and the start of the response body.
|
|
323
|
+
- **Browser options** (`headless`, `browser`, `browserTag`, `buildId`, `useLockedBrowser`, `executablePath`, `extraPuppeteerArgs`, `browserInstallBaseUrl`, `cleanupBrowserCacheOnExit`) only apply to the `puppeteer` provider.
|
|
324
|
+
|
|
230
325
|
## Options and configuration
|
|
231
326
|
|
|
232
|
-
The library exposes
|
|
327
|
+
The library exposes its options via the `PuppeteerParameters` interface (see `src/puppeteer/puppeteer-parameters.interface.ts`). You can configure:
|
|
233
328
|
|
|
234
329
|
| | Description |
|
|
235
330
|
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
236
|
-
| `
|
|
331
|
+
| `provider` | Who prints the PDF: `{ type: 'puppeteer' }` (default), `{ type: 'gotenberg', url, basicAuth?, headers? }` or `{ type: 'api2pdf', apiKey, baseUrl?, headers? }`. Module-level only. See [PDF providers](#pdf-providers) |
|
|
332
|
+
| `pdfOptions` | The pdf options can be found on: https://pptr.dev/api/puppeteer.pdfoptions. Native Puppeteer options for `page.pdf`. Remote providers translate the main ones, see [Page options](#page-options) |
|
|
333
|
+
| `gotenbergOptions` | Gotenberg provider only: `assets` (files sent next to `index.html`) and raw `formFields` |
|
|
334
|
+
| `api2pdfOptions` | Api2Pdf provider only: `fileName` and raw Chrome `options` |
|
|
237
335
|
| `watermark` | Stamps a text or image watermark on the generated PDF: `text` or `image`, `opacity`, `rotation`, `fontSize`, `font`, `color`, `imageWidth`, `position`, `tileSpacing`, `pages`. See [Watermark](#watermark) |
|
|
238
336
|
| `signal` | An `AbortSignal` that cancels the generation, including while it waits for a free slot. The promise rejects with `signal.reason`; use `AbortSignal.timeout(ms)` for a timeout. See [Cancellation and timeout](#cancellation-and-timeout) |
|
|
239
|
-
| `security` | Filters what the rendered HTML may load (SSRF protection): `blockPrivateNetworks`, `allowedHosts`, `allowedFileRoots`, `javascriptEnabled`. Disabled unless set; pass `{}` for the defaults. See [Restricting what the HTML can load](#restricting-what-the-html-can-load-ssrf-protection)
|
|
337
|
+
| `security` | Puppeteer provider only. Filters what the rendered HTML may load (SSRF protection): `blockPrivateNetworks`, `allowedHosts`, `allowedFileRoots`, `javascriptEnabled`. Disabled unless set; pass `{}` for the defaults. See [Restricting what the HTML can load](#restricting-what-the-html-can-load-ssrf-protection) |
|
|
240
338
|
| `hbsOptions` | Handlebars configuration: `templateDirectory` (base dir for `renderFile`), `partialDirectory` (files registered as partials), `compileOptions`, `templateOptions`, and `helpers` (`{ name, fn }[]`). Like the other engines it can be set globally here or overridden per call (`generatePdfFromTemplateHbs*(..., { hbsOptions })`). Helpers/partials run on an isolated Handlebars environment (no global leakage). |
|
|
241
339
|
| `ejsOptions` | The ejs options can be found on [EJS documentation](https://ejs.co/#options) |
|
|
242
340
|
| `pugOptions` | The pug options can be found on [Pug documentation](https://pugjs.org/api/reference.html#options) |
|
|
@@ -244,6 +342,7 @@ The library exposes Puppeteer options via the `PuppeteerParameters` interface (s
|
|
|
244
342
|
| `nunjucksOptions` | The nunjucks options can be found on [Nunjucks documentation](https://mozilla.github.io/nunjucks/api.html#configure) |
|
|
245
343
|
| `etaOptions` | The eta options can be found on [Eta documentation](https://eta.js.org/docs/4.x.x/api/configuration) |
|
|
246
344
|
| `mustacheOptions` | The mustache options can be found on [Mustache documentation](https://mustache.github.io/mustache.5.html) |
|
|
345
|
+
| `liquidOptions` | The liquid options can be found on [LiquidJS documentation](https://liquidjs.com/tutorials/options.html) |
|
|
247
346
|
| `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
347
|
| `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
348
|
| `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 +399,7 @@ You can use `forRootAsync(...)` if you need to provide configuration asynchronou
|
|
|
300
399
|
|
|
301
400
|
## Error handling
|
|
302
401
|
|
|
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:
|
|
402
|
+
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
403
|
|
|
305
404
|
```typescript
|
|
306
405
|
import {
|