@shad0wz7/nestjs-pdf 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -6
- package/dist/index.cjs +384 -1307
- package/dist/index.d.cts +93 -8
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +93 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +390 -1338
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# nestjs-pdf
|
|
2
2
|
|
|
3
|
-
> **v3 — ESM-first, NestJS 12.** This is the active `main` line: authored
|
|
4
|
-
> ESM, published as a dual CJS/ESM package, and
|
|
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
5
|
>
|
|
6
|
-
>
|
|
7
|
-
> `v2` branch instead:
|
|
6
|
+
> Need a pure CommonJS package or a Node.js version older than `20.19`? Use the
|
|
7
|
+
> maintenance `v2` branch instead:
|
|
8
8
|
>
|
|
9
9
|
> ```bash
|
|
10
10
|
> npm install @shad0wz7/nestjs-pdf@^2
|
|
@@ -27,12 +27,13 @@ Main features:
|
|
|
27
27
|
- Generate PDFs from HTML, Handlebars, EJS, Pug, MJML, Nunjucks, Eta or Mustache templates
|
|
28
28
|
- Concurrency limiting for Puppeteer jobs (p-limit)
|
|
29
29
|
- Add signature fields based on a text anchor in an existing PDF
|
|
30
|
+
- Text or image watermarks (centered or tiled) on generated or existing PDFs
|
|
30
31
|
- Simple API (module and service) to integrate easily into a Nest application
|
|
31
32
|
|
|
32
33
|
## Requirements
|
|
33
34
|
|
|
34
35
|
- **Node.js** `^20.19.0`, `^22.12.0` or `>=24.0.0` (aligned with NestJS 12)
|
|
35
|
-
- **NestJS** `^12.0.0` (`@nestjs/common`, `@nestjs/core`) and `rxjs ^7.8.0` as peer dependencies
|
|
36
|
+
- **NestJS** `^10.0.0`, `^11.0.0` or `^12.0.0` (`@nestjs/common`, `@nestjs/core`) and `rxjs ^7.8.0` as peer dependencies
|
|
36
37
|
|
|
37
38
|
## Installation
|
|
38
39
|
|
|
@@ -139,6 +140,93 @@ If the anchor is not found, the signature field will be added at a default posit
|
|
|
139
140
|
|
|
140
141
|
**Warning:** if you encounter issues like "Failed to load pdfjs-dist." Make sure to install `@napi-rs/canvas` as a dependency in your project, as it's required by the library for PDF manipulation.
|
|
141
142
|
|
|
143
|
+
### Watermark
|
|
144
|
+
|
|
145
|
+
Stamp a text or image watermark while generating a PDF, with the `watermark` option (per call or in `forRoot`):
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const pdf = await pdfService.generatePdfFromHtml(html, {
|
|
149
|
+
watermark: { text: 'CONFIDENTIAL', color: '#ff0000', opacity: 0.2 },
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
or on an existing PDF:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
const stamped = await pdfService.addWatermark(pdf, {
|
|
157
|
+
image: logoPngBytes, // PNG or JPEG
|
|
158
|
+
imageWidth: 200,
|
|
159
|
+
position: 'tile',
|
|
160
|
+
pages: [1, 2],
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
| Option | Default | Description |
|
|
165
|
+
| ------------- | --------------- | ------------------------------------------------------------ |
|
|
166
|
+
| `text` | | Text to stamp (`text` or `image` is required) |
|
|
167
|
+
| `image` | | PNG or JPEG bytes |
|
|
168
|
+
| `opacity` | `0.15` | 0 to 1 |
|
|
169
|
+
| `rotation` | `45` | Degrees, counter-clockwise |
|
|
170
|
+
| `fontSize` | `60` | Text only |
|
|
171
|
+
| `font` | `HelveticaBold` | A PDF standard font (`StandardFonts` key, WinAnsi text only) |
|
|
172
|
+
| `color` | `#808080` | `#rgb` or `#rrggbb`, text only |
|
|
173
|
+
| `imageWidth` | 50% of page | In points, aspect ratio preserved |
|
|
174
|
+
| `position` | `center` | `center` or `tile` |
|
|
175
|
+
| `tileSpacing` | `100` | Gap in points between tiles |
|
|
176
|
+
| `pages` | all | 1-based page numbers |
|
|
177
|
+
|
|
178
|
+
Invalid options or unreadable PDFs throw a `WatermarkException` (`WATERMARK_ERROR`).
|
|
179
|
+
|
|
180
|
+
### Cancellation and timeout
|
|
181
|
+
|
|
182
|
+
Pass an `AbortSignal` in the options to cancel a generation, for example when the HTTP client disconnects, or use `AbortSignal.timeout()` for a timeout:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
const controller = new AbortController();
|
|
186
|
+
req.on('close', () => controller.abort());
|
|
187
|
+
|
|
188
|
+
const pdf = await pdfService.generatePdfFromHtml(html, {
|
|
189
|
+
signal: AbortSignal.any([controller.signal, AbortSignal.timeout(20_000)]),
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The promise rejects with the signal's `reason` (an `AbortError` by default, a `TimeoutError` for `AbortSignal.timeout()`). A job aborted while it waits for a free slot is dropped without starting a browser context; a running job closes its context.
|
|
194
|
+
|
|
195
|
+
### Restricting what the HTML can load (SSRF protection)
|
|
196
|
+
|
|
197
|
+
If the HTML you render contains content you do not control, it can make the browser call internal services (`http://169.254.169.254/`, `http://localhost:…`, …). Enable the request filter with the `security` option, per call or in `forRoot`. It is **off unless you set it**, so existing setups are unchanged:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
NestjsPdfModule.forRoot({
|
|
201
|
+
security: {}, // defaults: private networks and file: URLs are blocked
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// or, stricter / with exceptions
|
|
205
|
+
await pdfService.generatePdfFromHtml(html, {
|
|
206
|
+
security: {
|
|
207
|
+
allowedHosts: ['cdn.example.com', '*.static.example.com'],
|
|
208
|
+
allowedFileRoots: ['/app/templates/assets'],
|
|
209
|
+
javascriptEnabled: false,
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
| Option | Default | Description |
|
|
215
|
+
| ---------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
216
|
+
| `blockPrivateNetworks` | `true` | Refuse http(s) requests to loopback, private, link-local (cloud metadata) and other non-public addresses, redirects included |
|
|
217
|
+
| `allowedHosts` | | Only allow http(s) requests to these hosts (`example.com` or `*.example.com`). Listed hosts are trusted even if they are private |
|
|
218
|
+
| `allowedFileRoots` | `[]` | `file:` requests are refused unless the file is inside one of these directories (symbolic links are resolved) |
|
|
219
|
+
| `javascriptEnabled` | `true` | Set to `false` to stop scripts from running in the page |
|
|
220
|
+
|
|
221
|
+
`data:`, `blob:` and `about:` are always allowed; every other protocol is refused. A blocked request is dropped (the PDF is still generated, without that resource) and logged without its query string.
|
|
222
|
+
|
|
223
|
+
Good to know:
|
|
224
|
+
|
|
225
|
+
- Plain links (`<a href="file:///…">`) are not requests, so they are never affected.
|
|
226
|
+
- Chrome already refuses to load `file:` resources from generated HTML, unless you launch it with `--allow-file-access-from-files`; `allowedFileRoots` is there for that case.
|
|
227
|
+
- 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
|
+
- `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
|
+
|
|
142
230
|
## Options and configuration
|
|
143
231
|
|
|
144
232
|
The library exposes Puppeteer options via the `PuppeteerParameters` interface (see `src/puppeteer/puppeteer-parameters.interface.ts`). You can configure:
|
|
@@ -146,6 +234,9 @@ The library exposes Puppeteer options via the `PuppeteerParameters` interface (s
|
|
|
146
234
|
| | Description |
|
|
147
235
|
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
148
236
|
| `pdfOptions` | The pdf options can be found on: https://pptr.dev/api/puppeteer.pdfoptions. Native Puppeteer options for `page.pdf` |
|
|
237
|
+
| `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
|
+
| `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) |
|
|
149
240
|
| `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). |
|
|
150
241
|
| `ejsOptions` | The ejs options can be found on [EJS documentation](https://ejs.co/#options) |
|
|
151
242
|
| `pugOptions` | The pug options can be found on [Pug documentation](https://pugjs.org/api/reference.html#options) |
|
|
@@ -183,7 +274,6 @@ these are the default extra arguments passed to Puppeteer:
|
|
|
183
274
|
'--disable-ipc-flooding-protection',
|
|
184
275
|
'--disable-notifications',
|
|
185
276
|
'--disable-offer-store-unmasked-wallet-cards',
|
|
186
|
-
'--disable-popup-blocking',
|
|
187
277
|
'--disable-print-preview',
|
|
188
278
|
'--disable-prompt-on-repost',
|
|
189
279
|
'--disable-renderer-backgrounding',
|