@shad0wz7/nestjs-pdf 2.5.1 → 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 +19 -24
- 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 +19 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
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
|
@@ -39,6 +39,7 @@ mjml = __toESM(mjml);
|
|
|
39
39
|
let mustache = require("mustache");
|
|
40
40
|
mustache = __toESM(mustache);
|
|
41
41
|
let nunjucks = require("nunjucks");
|
|
42
|
+
nunjucks = __toESM(nunjucks);
|
|
42
43
|
let pug = require("pug");
|
|
43
44
|
//#region src/helpers/getRelativePath.helper.ts
|
|
44
45
|
/**
|
|
@@ -255,19 +256,23 @@ let BrowserService = class BrowserService {
|
|
|
255
256
|
totalJobs = 0;
|
|
256
257
|
recycleRequested = false;
|
|
257
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;
|
|
258
262
|
browserTag;
|
|
259
263
|
useLockedBrowser;
|
|
260
264
|
buildId;
|
|
261
265
|
constructor(pdfParams) {
|
|
262
266
|
this.cacheDir = (0, node_path.resolve)(".cache/puppeteer-browser");
|
|
263
267
|
this.options = pdfParams;
|
|
264
|
-
if (pdfParams.cleanupBrowserCacheOnExit) this.registerCleanupHooks();
|
|
265
268
|
this.loadBuildId();
|
|
266
269
|
this.loadBrowser();
|
|
267
270
|
this.loadBrowserTag();
|
|
268
271
|
this.loadUseLockedBrowser();
|
|
269
272
|
}
|
|
270
273
|
async onModuleDestroy() {
|
|
274
|
+
this.shuttingDown = true;
|
|
275
|
+
await this.waitForIdle(this.shutdownDrainTimeoutMs);
|
|
271
276
|
if (this._browserInstance?.connected) try {
|
|
272
277
|
await this._browserInstance.close();
|
|
273
278
|
} catch (error) {
|
|
@@ -275,6 +280,12 @@ let BrowserService = class BrowserService {
|
|
|
275
280
|
}
|
|
276
281
|
await this.cleanupCacheBestEffort();
|
|
277
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
|
+
}
|
|
278
289
|
async getBrowserInstance(args, headless, executablePathBin) {
|
|
279
290
|
if (!this._browserInstance?.connected) this._browserInstance = await this.launchBrowser(args, headless, executablePathBin);
|
|
280
291
|
return this._browserInstance;
|
|
@@ -291,6 +302,7 @@ let BrowserService = class BrowserService {
|
|
|
291
302
|
}
|
|
292
303
|
}
|
|
293
304
|
markJobStarted() {
|
|
305
|
+
if (this.shuttingDown) throw new Error("nestjs-pdf is shutting down, refusing new PDF jobs");
|
|
294
306
|
this.activeJobs += 1;
|
|
295
307
|
this.totalJobs += 1;
|
|
296
308
|
if (this.totalJobs >= 200) this.recycleRequested = true;
|
|
@@ -322,7 +334,7 @@ let BrowserService = class BrowserService {
|
|
|
322
334
|
const dir = this.cacheDir;
|
|
323
335
|
try {
|
|
324
336
|
if (!(0, node_fs.existsSync)(dir)) return;
|
|
325
|
-
logger.log(`Cleanup puppeteer cache
|
|
337
|
+
logger.log(`Cleanup puppeteer cache: ${dir}`);
|
|
326
338
|
await rmWithRetries(dir, 6);
|
|
327
339
|
if ((0, node_fs.existsSync)(dir)) {
|
|
328
340
|
await sleep(100);
|
|
@@ -371,23 +383,6 @@ let BrowserService = class BrowserService {
|
|
|
371
383
|
}
|
|
372
384
|
return null;
|
|
373
385
|
}
|
|
374
|
-
registerCleanupHooks() {
|
|
375
|
-
const cleanup = async (signal) => {
|
|
376
|
-
try {
|
|
377
|
-
_nestjs_common.Logger.log(`Received ${signal}, cleaning up puppeteer cache...`, "NestJsPdf");
|
|
378
|
-
await this.cleanupCacheBestEffort();
|
|
379
|
-
process.exit(0);
|
|
380
|
-
} catch {
|
|
381
|
-
process.exit(1);
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
const cleanupHandler = (signal) => {
|
|
385
|
-
cleanup(signal);
|
|
386
|
-
};
|
|
387
|
-
process.once("SIGTERM", cleanupHandler);
|
|
388
|
-
process.once("SIGINT", cleanupHandler);
|
|
389
|
-
process.once("exit", cleanupHandler);
|
|
390
|
-
}
|
|
391
386
|
loadBrowser() {
|
|
392
387
|
let browser;
|
|
393
388
|
if (this.options?.browser === void 0) browser = _puppeteer_browsers.Browser.CHROMIUM;
|
|
@@ -662,7 +657,7 @@ MustacheService = __decorate([(0, _nestjs_common.Injectable)()], MustacheService
|
|
|
662
657
|
//#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
663
658
|
let NunjucksService = class NunjucksService {
|
|
664
659
|
constructor() {
|
|
665
|
-
|
|
660
|
+
nunjucks.default.configure({
|
|
666
661
|
noCache: true,
|
|
667
662
|
trimBlocks: true,
|
|
668
663
|
lstripBlocks: true
|
|
@@ -678,9 +673,9 @@ let NunjucksService = class NunjucksService {
|
|
|
678
673
|
trimBlocks: options.trimBlocks ?? true,
|
|
679
674
|
lstripBlocks: options.lstripBlocks ?? true
|
|
680
675
|
};
|
|
681
|
-
|
|
676
|
+
nunjucks.default.configure(configOptions);
|
|
682
677
|
}
|
|
683
|
-
return
|
|
678
|
+
return nunjucks.default.renderString(template, data);
|
|
684
679
|
} catch (error) {
|
|
685
680
|
throw new Error(`Nunjucks rendering failed: ${String(error)}`, { cause: error });
|
|
686
681
|
}
|
|
@@ -695,9 +690,9 @@ let NunjucksService = class NunjucksService {
|
|
|
695
690
|
trimBlocks: options.trimBlocks ?? true,
|
|
696
691
|
lstripBlocks: options.lstripBlocks ?? true
|
|
697
692
|
};
|
|
698
|
-
|
|
693
|
+
nunjucks.default.configure(configOptions);
|
|
699
694
|
}
|
|
700
|
-
return
|
|
695
|
+
return nunjucks.default.render(filePath, data);
|
|
701
696
|
} catch (error) {
|
|
702
697
|
throw new Error(`Nunjucks file rendering failed: ${String(error)}`, { cause: error });
|
|
703
698
|
}
|
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":";;;;;;;;;;;;;;;;;;;;;iBAWgB,uBACd,mBACA;;;aCIU;EACV;EACA;EACA;EACA;EACA;;KAGU;cAqCC,0BAA0B;mBACpB;mBACA;UAET;UACA;EAED;EACA;UAEC;UACA;UAEA;;EAED;UAEC;UACA;UACA;EAE8B,YAAA,WAAW;EAU3C,mBAAe;;UAoBP;EAaR,mBACJ,MAAM,eACN,yCACA,wCAAqC,QAAA;EAajC,cACJ,MAAM,eACN,UAAU,UACV,0BACC,QAAQ;EA2BX;EAaM,mBAAe;EAKf,0BAAsB;UA6Bd;EA6BR,QAAQ,iBAAqB,wCAAA,yCAAA;UA2D3B;EAUD,WAAW,SAAS;EAIpB,cAAc;UAIb;UAcA;EAUD,cAAc,YAAY;EAI1B,iBAAiB;EAIxB;EAIA,WAAW;UAIH;EAUF,oBAAoB,SAAS,SAAa,kBAAe;EAWzD,qBAAqB;UA2Bb;UAwBN;EAYR,iBAAiB,SAAS;;;;UC/bX,mBAAmB,KAAK;EACvC;;cAIW;EACL,OAAO,kBAAkB,OAAM,MAAW,UAAU,aAAU;EAa9D,WAAW,kBAAkB,OAAM,MAAW,UAAU,aAAU;;;;UChBzD,mBAAmB,QAAQ;EAC1C;EACA;EACA;EACA;EACA;EACA,UAAU;;cAIC;mBACM;mBACA;mBACA;;;;;;;;;EAiBjB,OACE,kBACA,OAAM,yBACN,UAAU;;;;;;;;EA6BZ,WACE,kBACA,OAAM,yBACN,UAAU;;;;EA8BZ;;;;;EAQA;;;;UCvGe;EACf;EACA,SAAS;;cAIE;mBACM;mBACA;;;;;;;;EASjB,OACE,kBACA,OAAM,yBACN,UAAU;;;;;;;;EAsBZ,WACE,kBACA,OAAM,yBACN,UAAU;;;;EA4BZ;;;;;EAQA;;;;UCpFe,wBAAwB,QAAQ;EAC/C;EACA;EACA;EACA;EACA;;cAIW;;EAUX,OACE,kBACA,OAAM,yBACN,UAAU;EAqBZ,WACE,kBACA,OAAM,yBACN,UAAU;;;;KC5CF,aAAa;cAGZ;EACX,OACE,kBACA,OAAM,cACN,UAAU;EAcZ,WACE,kBACA,OAAM,cACN,UAAU;;;;UCjBG;EACf,aAAa;EAEb,aAAa;EACb,cAAc;EACd,aAAa;EACb,aAAa;EACb,kBAAkB;EAClB,aAAa;EACb,kBAAkB;EAClB;EACA;EACA;EACA,UAAU;EACV,aAAa;EACb;EACA;EACA,qBAAqB;EACrB;EACA;;;;UCzBe,iCAAiC,KAChD;EAGA,SAAS;EACT,gBAAgB,MAAM;;cAIX;SACJ,QAAQ,SAAS,sBAAsB;SASvC,aAAa,SAAS,2BAA2B;;;;cClB7C;EACL,OACJ,kBACA,UAAU,qBACT;EAKG,WACJ,kBACA,UAAU,qBACT;;;;cCCQ;mBAEQ;mBACwB;mBACZ;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;EARZ,YAAA,gBAAgB,gBACQ,SAAS,qBACrB,aAAa,+BACb,cAAc,yBACd,aAAa,wBACb,aAAa,wBACb,kBAAkB,6BAClB,aAAa,wBACb,kBAAkB;mBAGhC;EAEX,oBACJ,cACA,UAAU,sBACT,QAAQ;EA+FL,iCACJ,kBACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;EAOzB,+BACJ,cACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;EAOzB,0BACJ,kBACA,UAAU,sBAAmB,QAAA,WAAA;EAUzB,wBAAwB,cAAc,UAAU,sBAAmB,QAAA,WAAA;EASnE,yBACJ,kBACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,uBACJ,cACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,yBACJ,kBACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,uBACJ,cACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,8BACJ,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,4BACJ,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,yBACJ,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,uBACJ,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,8BACJ,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,4BACJ,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;cCtSpB;mBACkB;EAAA,YAAA,kBAAkB;;;;;;;EAQ/C,oBAAoB,cAAc,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAW/D,iCACE,kBACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,+BACE,cACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;;;;;;;EAe/B,0BAA0B,kBAAkB,UAAU,sBAAmB,QAAA,WAAA;;;;;;;EAUzE,wBAAwB,cAAc,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAWnE,yBACE,kBACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,uBACE,cACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAY/B,yBACE,kBACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,uBACE,cACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAY/B,8BACE,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,4BACE,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,yBACE,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,uBACE,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAY/B,8BACE,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,4BACE,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;;;;;;;;;;;;;;;;EA+BzB,oCACJ,KAAK,aAAa,QAClB,oBACA,sBAA4C,QAAA,WAAA;;;;UClQ/B,oCAAoC,KACnD;EAGA,SAAS,MAAM,iBAAiB;EAChC,gBACK,MAAM,eACN,QAAQ,uBAAuB;;cAwBzB,2BAA2B;mBAEnB;mBACwB;EADxB,YAAA,gBAAgB,gBACQ,WAAW;EAGhD,gBAAY;SAQX,QAAQ,eAAe,sBAAsB;SAmC7C,aAAa,SAAS,8BAA8B"}
|
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":";;;;;;;;;;;;;;;;;;;;;iBAWgB,uBACd,mBACA;;;aCIU;EACV;EACA;EACA;EACA;EACA;;KAGU;cAqCC,0BAA0B;mBACpB;mBACA;UAET;UACA;EAED;EACA;UAEC;UACA;UAEA;;EAED;UAEC;UACA;UACA;EAE8B,YAAA,WAAW;EAU3C,mBAAe;;UAoBP;EAaR,mBACJ,MAAM,eACN,yCACA,wCAAqC,QAAA;EAajC,cACJ,MAAM,eACN,UAAU,UACV,0BACC,QAAQ;EA2BX;EAaM,mBAAe;EAKf,0BAAsB;UA6Bd;EA6BR,QAAQ,iBAAqB,wCAAA,yCAAA;UA2D3B;EAUD,WAAW,SAAS;EAIpB,cAAc;UAIb;UAcA;EAUD,cAAc,YAAY;EAI1B,iBAAiB;EAIxB;EAIA,WAAW;UAIH;EAUF,oBAAoB,SAAS,SAAa,kBAAe;EAWzD,qBAAqB;UA2Bb;UAwBN;EAYR,iBAAiB,SAAS;;;;UC/bX,mBAAmB,KAAK;EACvC;;cAIW;EACL,OAAO,kBAAkB,OAAM,MAAW,UAAU,aAAU;EAa9D,WAAW,kBAAkB,OAAM,MAAW,UAAU,aAAU;;;;UChBzD,mBAAmB,QAAQ;EAC1C;EACA;EACA;EACA;EACA;EACA,UAAU;;cAIC;mBACM;mBACA;mBACA;;;;;;;;;EAiBjB,OACE,kBACA,OAAM,yBACN,UAAU;;;;;;;;EA6BZ,WACE,kBACA,OAAM,yBACN,UAAU;;;;EA8BZ;;;;;EAQA;;;;UCvGe;EACf;EACA,SAAS;;cAIE;mBACM;mBACA;;;;;;;;EASjB,OACE,kBACA,OAAM,yBACN,UAAU;;;;;;;;EAsBZ,WACE,kBACA,OAAM,yBACN,UAAU;;;;EA4BZ;;;;;EAQA;;;;UCpFe,wBAAwB,QAAQ;EAC/C;EACA;EACA;EACA;EACA;;cAIW;;EAUX,OACE,kBACA,OAAM,yBACN,UAAU;EAqBZ,WACE,kBACA,OAAM,yBACN,UAAU;;;;KC5CF,aAAa;cAGZ;EACX,OACE,kBACA,OAAM,cACN,UAAU;EAcZ,WACE,kBACA,OAAM,cACN,UAAU;;;;UCjBG;EACf,aAAa;EAEb,aAAa;EACb,cAAc;EACd,aAAa;EACb,aAAa;EACb,kBAAkB;EAClB,aAAa;EACb,kBAAkB;EAClB;EACA;EACA;EACA,UAAU;EACV,aAAa;EACb;EACA;EACA,qBAAqB;EACrB;EACA;;;;UCzBe,iCAAiC,KAChD;EAGA,SAAS;EACT,gBAAgB,MAAM;;cAIX;SACJ,QAAQ,SAAS,sBAAsB;SASvC,aAAa,SAAS,2BAA2B;;;;cClB7C;EACL,OACJ,kBACA,UAAU,qBACT;EAKG,WACJ,kBACA,UAAU,qBACT;;;;cCCQ;mBAEQ;mBACwB;mBACZ;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;EARZ,YAAA,gBAAgB,gBACQ,SAAS,qBACrB,aAAa,+BACb,cAAc,yBACd,aAAa,wBACb,aAAa,wBACb,kBAAkB,6BAClB,aAAa,wBACb,kBAAkB;mBAGhC;EAEX,oBACJ,cACA,UAAU,sBACT,QAAQ;EA+FL,iCACJ,kBACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;EAOzB,+BACJ,cACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;EAOzB,0BACJ,kBACA,UAAU,sBAAmB,QAAA,WAAA;EAUzB,wBAAwB,cAAc,UAAU,sBAAmB,QAAA,WAAA;EASnE,yBACJ,kBACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,uBACJ,cACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,yBACJ,kBACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,uBACJ,cACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,8BACJ,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,4BACJ,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,yBACJ,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,uBACJ,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,8BACJ,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;EAWzB,4BACJ,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;cCtSpB;mBACkB;EAAA,YAAA,kBAAkB;;;;;;;EAQ/C,oBAAoB,cAAc,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAW/D,iCACE,kBACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,+BACE,cACA,kBACA,UAAU,sBAAmB,QAAA,WAAA;;;;;;;EAe/B,0BAA0B,kBAAkB,UAAU,sBAAmB,QAAA,WAAA;;;;;;;EAUzE,wBAAwB,cAAc,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAWnE,yBACE,kBACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,uBACE,cACA,OAAM,MACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAY/B,yBACE,kBACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,uBACE,cACA,OAAM,cACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAY/B,8BACE,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,4BACE,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,yBACE,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,uBACE,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAY/B,8BACE,kBACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;EAgB/B,4BACE,cACA,OAAM,yBACN,UAAU,sBAAmB,QAAA,WAAA;;;;;;;;;;;;;;;;;;;;;;;EA+BzB,oCACJ,KAAK,aAAa,QAClB,oBACA,sBAA4C,QAAA,WAAA;;;;UClQ/B,oCAAoC,KACnD;EAGA,SAAS,MAAM,iBAAiB;EAChC,gBACK,MAAM,eACN,QAAQ,uBAAuB;;cAwBzB,2BAA2B;mBAEnB;mBACwB;EADxB,YAAA,gBAAgB,gBACQ,WAAW;EAGhD,gBAAY;SAQX,QAAQ,eAAe,sBAAsB;SAmC7C,aAAa,SAAS,8BAA8B"}
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { render, renderFile } from "ejs";
|
|
|
12
12
|
import { Eta } from "eta";
|
|
13
13
|
import mjml from "mjml";
|
|
14
14
|
import mustache from "mustache";
|
|
15
|
-
import
|
|
15
|
+
import nunjucks from "nunjucks";
|
|
16
16
|
import { compile } from "pug";
|
|
17
17
|
//#region \0rolldown/runtime.js
|
|
18
18
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
@@ -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;
|
|
@@ -640,7 +634,7 @@ MustacheService = __decorate([Injectable()], MustacheService);
|
|
|
640
634
|
//#region src/puppeteer/engines/nunjucks/nunjucks.service.ts
|
|
641
635
|
let NunjucksService = class NunjucksService {
|
|
642
636
|
constructor() {
|
|
643
|
-
configure({
|
|
637
|
+
nunjucks.configure({
|
|
644
638
|
noCache: true,
|
|
645
639
|
trimBlocks: true,
|
|
646
640
|
lstripBlocks: true
|
|
@@ -656,9 +650,9 @@ let NunjucksService = class NunjucksService {
|
|
|
656
650
|
trimBlocks: options.trimBlocks ?? true,
|
|
657
651
|
lstripBlocks: options.lstripBlocks ?? true
|
|
658
652
|
};
|
|
659
|
-
configure(configOptions);
|
|
653
|
+
nunjucks.configure(configOptions);
|
|
660
654
|
}
|
|
661
|
-
return renderString(template, data);
|
|
655
|
+
return nunjucks.renderString(template, data);
|
|
662
656
|
} catch (error) {
|
|
663
657
|
throw new Error(`Nunjucks rendering failed: ${String(error)}`, { cause: error });
|
|
664
658
|
}
|
|
@@ -673,9 +667,9 @@ let NunjucksService = class NunjucksService {
|
|
|
673
667
|
trimBlocks: options.trimBlocks ?? true,
|
|
674
668
|
lstripBlocks: options.lstripBlocks ?? true
|
|
675
669
|
};
|
|
676
|
-
configure(configOptions);
|
|
670
|
+
nunjucks.configure(configOptions);
|
|
677
671
|
}
|
|
678
|
-
return render
|
|
672
|
+
return nunjucks.render(filePath, data);
|
|
679
673
|
} catch (error) {
|
|
680
674
|
throw new Error(`Nunjucks file rendering failed: ${String(error)}`, { cause: error });
|
|
681
675
|
}
|