@shad0wz7/nestjs-pdf 2.5.2 → 2.5.3
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 +15 -3
- package/dist/index.cjs +13 -19
- package/dist/index.d.cts +5 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +13 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# nestjs-pdf
|
|
2
2
|
|
|
3
|
+
> **⚠️ Maintenance branch — NestJS 11 / CommonJS (v2.x).**
|
|
4
|
+
> This is the `v2` line: CommonJS-only, built for **NestJS 11**. It's kept for
|
|
5
|
+
> maintenance/security fixes only — no new features land here.
|
|
6
|
+
>
|
|
7
|
+
> Active development has moved to **v3**, on the `main` branch: ESM-first with
|
|
8
|
+
> a dual CJS/ESM build, and requires **NestJS 12+**. See its
|
|
9
|
+
> [README](https://github.com/ShadowZ11/nestjs-pdf/blob/main/README.md) for
|
|
10
|
+
> details, and pin this line explicitly if you need it:
|
|
11
|
+
>
|
|
12
|
+
> ```bash
|
|
13
|
+
> npm install @shad0wz7/nestjs-pdf@^2
|
|
14
|
+
> ```
|
|
15
|
+
|
|
3
16
|
[](https://www.npmjs.com/package/%40shad0wz7%2Fnestjs-pdf)
|
|
4
17
|
[](https://github.com/ShadowZ11/nestjs-pdf?tab=MIT-1-ov-file)
|
|
5
18
|
[](https://www.npmjs.com/package/%40shad0wz7%2Fnestjs-pdf)
|
|
@@ -7,7 +20,6 @@
|
|
|
7
20
|
[](https://codecov.io/github/ShadowZ11/nestjs-pdf)
|
|
8
21
|
[](https://www.typescriptlang.org/)
|
|
9
22
|
|
|
10
|
-
|
|
11
23
|
A NestJS library to generate and manipulate PDFs using Puppeteer and multiple template engines, including Handlebars, EJS, Pug, MJML, Nunjucks, Eta and Mustache.
|
|
12
24
|
|
|
13
25
|
Main features:
|
|
@@ -117,9 +129,8 @@ If the anchor is not found, the signature field will be added at a default posit
|
|
|
117
129
|
|
|
118
130
|
The library exposes Puppeteer options via the `PuppeteerParameters` interface (see `src/puppeteer/puppeteer-parameters.interface.ts`). You can configure:
|
|
119
131
|
|
|
120
|
-
|
|
121
132
|
| | Description |
|
|
122
|
-
|
|
133
|
+
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
134
|
| `pdfOptions` | The pdf options can be found on: https://pptr.dev/api/puppeteer.pdfoptions. Native Puppeteer options for `page.pdf` |
|
|
124
135
|
| `hbsOptions` | The handlebars can be found on [@gboutte/nestjs-hbs](https://github.com/gboutte/nestjs-hbs) as it use a peer dependency and not handlebars directly |
|
|
125
136
|
| `ejsOptions` | The ejs options can be found on [EJS documentation](https://ejs.co/#options) |
|
|
@@ -139,6 +150,7 @@ The library exposes Puppeteer options via the `PuppeteerParameters` interface (s
|
|
|
139
150
|
| `executablePath` | The path to the browser executable to use. If not specified, Puppeteer will install Chromium in cache dir. (useLockedBrowser is useless with this param specified) |
|
|
140
151
|
|
|
141
152
|
these are the default extra arguments passed to Puppeteer:
|
|
153
|
+
|
|
142
154
|
```ts
|
|
143
155
|
[
|
|
144
156
|
'--autoplay-policy=user-gesture-required',
|
package/dist/index.cjs
CHANGED
|
@@ -256,19 +256,23 @@ let BrowserService = class BrowserService {
|
|
|
256
256
|
totalJobs = 0;
|
|
257
257
|
recycleRequested = false;
|
|
258
258
|
recycling = false;
|
|
259
|
+
shuttingDown = false;
|
|
260
|
+
/** Max time to wait for in-flight PDF jobs to finish before closing the browser on shutdown. */
|
|
261
|
+
shutdownDrainTimeoutMs = 15e3;
|
|
259
262
|
browserTag;
|
|
260
263
|
useLockedBrowser;
|
|
261
264
|
buildId;
|
|
262
265
|
constructor(pdfParams) {
|
|
263
266
|
this.cacheDir = (0, node_path.resolve)(".cache/puppeteer-browser");
|
|
264
267
|
this.options = pdfParams;
|
|
265
|
-
if (pdfParams.cleanupBrowserCacheOnExit) this.registerCleanupHooks();
|
|
266
268
|
this.loadBuildId();
|
|
267
269
|
this.loadBrowser();
|
|
268
270
|
this.loadBrowserTag();
|
|
269
271
|
this.loadUseLockedBrowser();
|
|
270
272
|
}
|
|
271
273
|
async onModuleDestroy() {
|
|
274
|
+
this.shuttingDown = true;
|
|
275
|
+
await this.waitForIdle(this.shutdownDrainTimeoutMs);
|
|
272
276
|
if (this._browserInstance?.connected) try {
|
|
273
277
|
await this._browserInstance.close();
|
|
274
278
|
} catch (error) {
|
|
@@ -276,6 +280,12 @@ let BrowserService = class BrowserService {
|
|
|
276
280
|
}
|
|
277
281
|
await this.cleanupCacheBestEffort();
|
|
278
282
|
}
|
|
283
|
+
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
284
|
+
async waitForIdle(timeoutMs) {
|
|
285
|
+
const start = Date.now();
|
|
286
|
+
while (this.activeJobs > 0 && Date.now() - start < timeoutMs) await sleep(50);
|
|
287
|
+
if (this.activeJobs > 0) _nestjs_common.Logger.warn(`Shutdown: ${this.activeJobs} PDF job(s) still running after ${timeoutMs}ms, closing the browser anyway`);
|
|
288
|
+
}
|
|
279
289
|
async getBrowserInstance(args, headless, executablePathBin) {
|
|
280
290
|
if (!this._browserInstance?.connected) this._browserInstance = await this.launchBrowser(args, headless, executablePathBin);
|
|
281
291
|
return this._browserInstance;
|
|
@@ -292,6 +302,7 @@ let BrowserService = class BrowserService {
|
|
|
292
302
|
}
|
|
293
303
|
}
|
|
294
304
|
markJobStarted() {
|
|
305
|
+
if (this.shuttingDown) throw new Error("nestjs-pdf is shutting down, refusing new PDF jobs");
|
|
295
306
|
this.activeJobs += 1;
|
|
296
307
|
this.totalJobs += 1;
|
|
297
308
|
if (this.totalJobs >= 200) this.recycleRequested = true;
|
|
@@ -323,7 +334,7 @@ let BrowserService = class BrowserService {
|
|
|
323
334
|
const dir = this.cacheDir;
|
|
324
335
|
try {
|
|
325
336
|
if (!(0, node_fs.existsSync)(dir)) return;
|
|
326
|
-
logger.log(`Cleanup puppeteer cache
|
|
337
|
+
logger.log(`Cleanup puppeteer cache: ${dir}`);
|
|
327
338
|
await rmWithRetries(dir, 6);
|
|
328
339
|
if ((0, node_fs.existsSync)(dir)) {
|
|
329
340
|
await sleep(100);
|
|
@@ -372,23 +383,6 @@ let BrowserService = class BrowserService {
|
|
|
372
383
|
}
|
|
373
384
|
return null;
|
|
374
385
|
}
|
|
375
|
-
registerCleanupHooks() {
|
|
376
|
-
const cleanup = async (signal) => {
|
|
377
|
-
try {
|
|
378
|
-
_nestjs_common.Logger.log(`Received ${signal}, cleaning up puppeteer cache...`, "NestJsPdf");
|
|
379
|
-
await this.cleanupCacheBestEffort();
|
|
380
|
-
process.exit(0);
|
|
381
|
-
} catch {
|
|
382
|
-
process.exit(1);
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
const cleanupHandler = (signal) => {
|
|
386
|
-
cleanup(signal);
|
|
387
|
-
};
|
|
388
|
-
process.once("SIGTERM", cleanupHandler);
|
|
389
|
-
process.once("SIGINT", cleanupHandler);
|
|
390
|
-
process.once("exit", cleanupHandler);
|
|
391
|
-
}
|
|
392
386
|
loadBrowser() {
|
|
393
387
|
let browser;
|
|
394
388
|
if (this.options?.browser === void 0) browser = _puppeteer_browsers.Browser.CHROMIUM;
|
package/dist/index.d.cts
CHANGED
|
@@ -39,11 +39,16 @@ declare class BrowserService implements OnModuleDestroy {
|
|
|
39
39
|
totalJobs: number;
|
|
40
40
|
private recycleRequested;
|
|
41
41
|
private recycling;
|
|
42
|
+
private shuttingDown;
|
|
43
|
+
/** Max time to wait for in-flight PDF jobs to finish before closing the browser on shutdown. */
|
|
44
|
+
shutdownDrainTimeoutMs: number;
|
|
42
45
|
private browserTag;
|
|
43
46
|
private useLockedBrowser;
|
|
44
47
|
private buildId;
|
|
45
48
|
constructor(pdfParams: PuppeteerParameters);
|
|
46
49
|
onModuleDestroy(): Promise<void>;
|
|
50
|
+
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
51
|
+
private waitForIdle;
|
|
47
52
|
getBrowserInstance(args: Array<string>, headless: boolean | 'shell' | undefined, executablePathBin: string | undefined): Promise<Browser$1>;
|
|
48
53
|
createContext(args: Array<string>, headless: Headless, executablePath?: string): Promise<BrowserContext>;
|
|
49
54
|
markJobStarted(): void;
|
|
@@ -51,7 +56,6 @@ declare class BrowserService implements OnModuleDestroy {
|
|
|
51
56
|
recycleBrowserIfNeeded(): Promise<void>;
|
|
52
57
|
private cleanupCacheBestEffort;
|
|
53
58
|
install(lock?: boolean): Promise<import("@puppeteer/browsers", { with: { "resolution-mode": "import" } }).InstalledBrowser | null | undefined>;
|
|
54
|
-
private registerCleanupHooks;
|
|
55
59
|
private loadBrowser;
|
|
56
60
|
setBrowser(browser: Browser): void;
|
|
57
61
|
getBrowser(): Browser;
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/helpers/getRelativePath.helper.ts","../src/puppeteer/browser/browser.service.ts","../src/puppeteer/engines/ejs/ejs.service.ts","../src/puppeteer/engines/eta/eta.service.ts","../src/puppeteer/engines/mustache/mustache.service.ts","../src/puppeteer/engines/nunjucks/nunjucks.service.ts","../src/puppeteer/engines/pug/pug.service.ts","../src/puppeteer/puppeteer-parameters.interface.ts","../src/nestjs-pdf.module.ts","../src/puppeteer/engines/mjml/mjml.service.ts","../src/puppeteer/puppeteer.service.ts","../src/nestjs-pdf.service.ts","../src/puppeteer/puppeteer.module.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;iBAWgB,uBACd,mBACA;;;aCIU;EACV;EACA;EACA;EACA;EACA;;KAGU;cAqCC,0BAA0B;mBACpB;mBACA;UAET;UACA;EAED;EACA;UAEC;UACA;UAEA;UACA;UACA;EAE8B,YAAA,WAAW;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/helpers/getRelativePath.helper.ts","../src/puppeteer/browser/browser.service.ts","../src/puppeteer/engines/ejs/ejs.service.ts","../src/puppeteer/engines/eta/eta.service.ts","../src/puppeteer/engines/mustache/mustache.service.ts","../src/puppeteer/engines/nunjucks/nunjucks.service.ts","../src/puppeteer/engines/pug/pug.service.ts","../src/puppeteer/puppeteer-parameters.interface.ts","../src/nestjs-pdf.module.ts","../src/puppeteer/engines/mjml/mjml.service.ts","../src/puppeteer/puppeteer.service.ts","../src/nestjs-pdf.service.ts","../src/puppeteer/puppeteer.module.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -39,11 +39,16 @@ declare class BrowserService implements OnModuleDestroy {
|
|
|
39
39
|
totalJobs: number;
|
|
40
40
|
private recycleRequested;
|
|
41
41
|
private recycling;
|
|
42
|
+
private shuttingDown;
|
|
43
|
+
/** Max time to wait for in-flight PDF jobs to finish before closing the browser on shutdown. */
|
|
44
|
+
shutdownDrainTimeoutMs: number;
|
|
42
45
|
private browserTag;
|
|
43
46
|
private useLockedBrowser;
|
|
44
47
|
private buildId;
|
|
45
48
|
constructor(pdfParams: PuppeteerParameters);
|
|
46
49
|
onModuleDestroy(): Promise<void>;
|
|
50
|
+
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
51
|
+
private waitForIdle;
|
|
47
52
|
getBrowserInstance(args: Array<string>, headless: boolean | 'shell' | undefined, executablePathBin: string | undefined): Promise<Browser$1>;
|
|
48
53
|
createContext(args: Array<string>, headless: Headless, executablePath?: string): Promise<BrowserContext>;
|
|
49
54
|
markJobStarted(): void;
|
|
@@ -51,7 +56,6 @@ declare class BrowserService implements OnModuleDestroy {
|
|
|
51
56
|
recycleBrowserIfNeeded(): Promise<void>;
|
|
52
57
|
private cleanupCacheBestEffort;
|
|
53
58
|
install(lock?: boolean): Promise<import("@puppeteer/browsers", { with: { "resolution-mode": "import" } }).InstalledBrowser | null | undefined>;
|
|
54
|
-
private registerCleanupHooks;
|
|
55
59
|
private loadBrowser;
|
|
56
60
|
setBrowser(browser: Browser): void;
|
|
57
61
|
getBrowser(): Browser;
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/helpers/getRelativePath.helper.ts","../src/puppeteer/browser/browser.service.ts","../src/puppeteer/engines/ejs/ejs.service.ts","../src/puppeteer/engines/eta/eta.service.ts","../src/puppeteer/engines/mustache/mustache.service.ts","../src/puppeteer/engines/nunjucks/nunjucks.service.ts","../src/puppeteer/engines/pug/pug.service.ts","../src/puppeteer/puppeteer-parameters.interface.ts","../src/nestjs-pdf.module.ts","../src/puppeteer/engines/mjml/mjml.service.ts","../src/puppeteer/puppeteer.service.ts","../src/nestjs-pdf.service.ts","../src/puppeteer/puppeteer.module.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;iBAWgB,uBACd,mBACA;;;aCIU;EACV;EACA;EACA;EACA;EACA;;KAGU;cAqCC,0BAA0B;mBACpB;mBACA;UAET;UACA;EAED;EACA;UAEC;UACA;UAEA;UACA;UACA;EAE8B,YAAA,WAAW;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/helpers/getRelativePath.helper.ts","../src/puppeteer/browser/browser.service.ts","../src/puppeteer/engines/ejs/ejs.service.ts","../src/puppeteer/engines/eta/eta.service.ts","../src/puppeteer/engines/mustache/mustache.service.ts","../src/puppeteer/engines/nunjucks/nunjucks.service.ts","../src/puppeteer/engines/pug/pug.service.ts","../src/puppeteer/puppeteer-parameters.interface.ts","../src/nestjs-pdf.module.ts","../src/puppeteer/engines/mjml/mjml.service.ts","../src/puppeteer/puppeteer.service.ts","../src/nestjs-pdf.service.ts","../src/puppeteer/puppeteer.module.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -233,19 +233,23 @@ let BrowserService = class BrowserService {
|
|
|
233
233
|
totalJobs = 0;
|
|
234
234
|
recycleRequested = false;
|
|
235
235
|
recycling = false;
|
|
236
|
+
shuttingDown = false;
|
|
237
|
+
/** Max time to wait for in-flight PDF jobs to finish before closing the browser on shutdown. */
|
|
238
|
+
shutdownDrainTimeoutMs = 15e3;
|
|
236
239
|
browserTag;
|
|
237
240
|
useLockedBrowser;
|
|
238
241
|
buildId;
|
|
239
242
|
constructor(pdfParams) {
|
|
240
243
|
this.cacheDir = resolve(".cache/puppeteer-browser");
|
|
241
244
|
this.options = pdfParams;
|
|
242
|
-
if (pdfParams.cleanupBrowserCacheOnExit) this.registerCleanupHooks();
|
|
243
245
|
this.loadBuildId();
|
|
244
246
|
this.loadBrowser();
|
|
245
247
|
this.loadBrowserTag();
|
|
246
248
|
this.loadUseLockedBrowser();
|
|
247
249
|
}
|
|
248
250
|
async onModuleDestroy() {
|
|
251
|
+
this.shuttingDown = true;
|
|
252
|
+
await this.waitForIdle(this.shutdownDrainTimeoutMs);
|
|
249
253
|
if (this._browserInstance?.connected) try {
|
|
250
254
|
await this._browserInstance.close();
|
|
251
255
|
} catch (error) {
|
|
@@ -253,6 +257,12 @@ let BrowserService = class BrowserService {
|
|
|
253
257
|
}
|
|
254
258
|
await this.cleanupCacheBestEffort();
|
|
255
259
|
}
|
|
260
|
+
/** Wait until no PDF job is in flight, or until the timeout elapses. */
|
|
261
|
+
async waitForIdle(timeoutMs) {
|
|
262
|
+
const start = Date.now();
|
|
263
|
+
while (this.activeJobs > 0 && Date.now() - start < timeoutMs) await sleep(50);
|
|
264
|
+
if (this.activeJobs > 0) Logger.warn(`Shutdown: ${this.activeJobs} PDF job(s) still running after ${timeoutMs}ms, closing the browser anyway`);
|
|
265
|
+
}
|
|
256
266
|
async getBrowserInstance(args, headless, executablePathBin) {
|
|
257
267
|
if (!this._browserInstance?.connected) this._browserInstance = await this.launchBrowser(args, headless, executablePathBin);
|
|
258
268
|
return this._browserInstance;
|
|
@@ -269,6 +279,7 @@ let BrowserService = class BrowserService {
|
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
281
|
markJobStarted() {
|
|
282
|
+
if (this.shuttingDown) throw new Error("nestjs-pdf is shutting down, refusing new PDF jobs");
|
|
272
283
|
this.activeJobs += 1;
|
|
273
284
|
this.totalJobs += 1;
|
|
274
285
|
if (this.totalJobs >= 200) this.recycleRequested = true;
|
|
@@ -300,7 +311,7 @@ let BrowserService = class BrowserService {
|
|
|
300
311
|
const dir = this.cacheDir;
|
|
301
312
|
try {
|
|
302
313
|
if (!existsSync(dir)) return;
|
|
303
|
-
logger.log(`Cleanup puppeteer cache
|
|
314
|
+
logger.log(`Cleanup puppeteer cache: ${dir}`);
|
|
304
315
|
await rmWithRetries(dir, 6);
|
|
305
316
|
if (existsSync(dir)) {
|
|
306
317
|
await sleep(100);
|
|
@@ -349,23 +360,6 @@ let BrowserService = class BrowserService {
|
|
|
349
360
|
}
|
|
350
361
|
return null;
|
|
351
362
|
}
|
|
352
|
-
registerCleanupHooks() {
|
|
353
|
-
const cleanup = async (signal) => {
|
|
354
|
-
try {
|
|
355
|
-
Logger.log(`Received ${signal}, cleaning up puppeteer cache...`, "NestJsPdf");
|
|
356
|
-
await this.cleanupCacheBestEffort();
|
|
357
|
-
process.exit(0);
|
|
358
|
-
} catch {
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
const cleanupHandler = (signal) => {
|
|
363
|
-
cleanup(signal);
|
|
364
|
-
};
|
|
365
|
-
process.once("SIGTERM", cleanupHandler);
|
|
366
|
-
process.once("SIGINT", cleanupHandler);
|
|
367
|
-
process.once("exit", cleanupHandler);
|
|
368
|
-
}
|
|
369
363
|
loadBrowser() {
|
|
370
364
|
let browser;
|
|
371
365
|
if (this.options?.browser === void 0) browser = Browser.CHROMIUM;
|