@spinajs/queue-templates-pdf 2.0.482

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.
Files changed (54) hide show
  1. package/README.md +101 -0
  2. package/lib/cjs/RenderPdfJob.d.ts +38 -0
  3. package/lib/cjs/RenderPdfJob.d.ts.map +1 -0
  4. package/lib/cjs/RenderPdfJob.js +114 -0
  5. package/lib/cjs/RenderPdfJob.js.map +1 -0
  6. package/lib/cjs/index.d.ts +5 -0
  7. package/lib/cjs/index.d.ts.map +1 -0
  8. package/lib/cjs/index.js +25 -0
  9. package/lib/cjs/index.js.map +1 -0
  10. package/lib/cjs/package.json +1 -0
  11. package/lib/cjs/protocol.d.ts +49 -0
  12. package/lib/cjs/protocol.d.ts.map +1 -0
  13. package/lib/cjs/protocol.js +3 -0
  14. package/lib/cjs/protocol.js.map +1 -0
  15. package/lib/cjs/render-worker.d.ts +2 -0
  16. package/lib/cjs/render-worker.d.ts.map +1 -0
  17. package/lib/cjs/render-worker.js +32 -0
  18. package/lib/cjs/render-worker.js.map +1 -0
  19. package/lib/cjs/render.d.ts +17 -0
  20. package/lib/cjs/render.d.ts.map +1 -0
  21. package/lib/cjs/render.js +67 -0
  22. package/lib/cjs/render.js.map +1 -0
  23. package/lib/cjs/schedule.d.ts +48 -0
  24. package/lib/cjs/schedule.d.ts.map +1 -0
  25. package/lib/cjs/schedule.js +37 -0
  26. package/lib/cjs/schedule.js.map +1 -0
  27. package/lib/mjs/RenderPdfJob.d.ts +38 -0
  28. package/lib/mjs/RenderPdfJob.d.ts.map +1 -0
  29. package/lib/mjs/RenderPdfJob.js +111 -0
  30. package/lib/mjs/RenderPdfJob.js.map +1 -0
  31. package/lib/mjs/index.d.ts +5 -0
  32. package/lib/mjs/index.d.ts.map +1 -0
  33. package/lib/mjs/index.js +9 -0
  34. package/lib/mjs/index.js.map +1 -0
  35. package/lib/mjs/package.json +1 -0
  36. package/lib/mjs/protocol.d.ts +49 -0
  37. package/lib/mjs/protocol.d.ts.map +1 -0
  38. package/lib/mjs/protocol.js +2 -0
  39. package/lib/mjs/protocol.js.map +1 -0
  40. package/lib/mjs/render-worker.d.ts +2 -0
  41. package/lib/mjs/render-worker.d.ts.map +1 -0
  42. package/lib/mjs/render-worker.js +30 -0
  43. package/lib/mjs/render-worker.js.map +1 -0
  44. package/lib/mjs/render.d.ts +17 -0
  45. package/lib/mjs/render.d.ts.map +1 -0
  46. package/lib/mjs/render.js +64 -0
  47. package/lib/mjs/render.js.map +1 -0
  48. package/lib/mjs/schedule.d.ts +48 -0
  49. package/lib/mjs/schedule.d.ts.map +1 -0
  50. package/lib/mjs/schedule.js +34 -0
  51. package/lib/mjs/schedule.js.map +1 -0
  52. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  53. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  54. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # @spinajs/queue-templates-pdf
2
+
3
+ A SpinaJS queue job that renders a PDF template in an **isolated worker process**
4
+ and reports render progress (percent + phase + message) back to the queue.
5
+
6
+ All heavy, crash-prone work — Chromium, template compilation, upload — runs in a
7
+ forked worker. The job in the queue consumer only supervises it, so a hung or
8
+ crashing render can never take down the worker, and memory is reclaimed per render.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @spinajs/queue-templates-pdf
14
+ ```
15
+
16
+ Requires a configured queue (transport + DB for the job model) and at least one
17
+ `@spinajs/fs` provider for the output.
18
+
19
+ ## Usage
20
+
21
+ ```ts
22
+ import { scheduleRenderPdf } from '@spinajs/queue-templates-pdf';
23
+
24
+ // render now
25
+ await scheduleRenderPdf({
26
+ input: 'invoices/invoice.pug', // a template (template: true) or raw HTML
27
+ template: true,
28
+ model: { total: 42 },
29
+ lang: 'en',
30
+ output: { provider: 's3', path: 'invoices/2026/1.pdf' }, // any @spinajs/fs provider
31
+ pdfOptions: { format: 'A4', printBackground: true },
32
+ });
33
+
34
+ // render in 5 minutes
35
+ await scheduleRenderPdf(payload, { delay: 5 * 60 * 1000 });
36
+
37
+ // recurring: every day at 06:00
38
+ await scheduleRenderPdf(payload, { cron: '0 6 * * *' });
39
+ ```
40
+
41
+ The job must be consumed by a queue worker:
42
+
43
+ ```ts
44
+ import { RenderPdfJob } from '@spinajs/queue-templates-pdf';
45
+ const queue = await DI.resolve(QueueService);
46
+ await queue.consume(RenderPdfJob);
47
+ ```
48
+
49
+ ## Output
50
+
51
+ `output: { provider, path }` names a configured `@spinajs/fs` provider (local,
52
+ temp, S3, ...) and a path relative to it. The worker renders to a local temp file
53
+ and uploads it to that provider, so the same job works for local disk or object
54
+ storage without change.
55
+
56
+ ## Progress
57
+
58
+ The worker streams progress; the supervisor forwards it to the queue job model:
59
+
60
+ - **percent** 0–100 (phase-weighted),
61
+ - **phase** — `starting` → `preparing` → `loading` → `rendering` → `done` (or `failed`),
62
+ - **message** — e.g. `Loading resources (12 done, 3 pending)`.
63
+
64
+ With `@spinajs/queue-http-progress` this is exposed at:
65
+
66
+ ```
67
+ GET jobs/v1/:jobId/status
68
+ -> { jobId, progress, phase, message, status, createdAt }
69
+ ```
70
+
71
+ `scheduleRenderPdf` (and `RenderPdfJob.emit`) return the generated `jobId`, so you
72
+ can hand it straight to the status endpoint:
73
+
74
+ ```ts
75
+ const jobId = await scheduleRenderPdf(payload);
76
+ // later: GET jobs/v1/${jobId}/status
77
+ ```
78
+
79
+ ## Worker configuration
80
+
81
+ The worker re-bootstraps the app configuration by default (it runs in the app's
82
+ config environment: same config sources / cwd, so it resolves the same
83
+ `templates.pdf` launch args and fs providers). For environments where that is not
84
+ possible, pass an inline `config` object in the payload and the worker will
85
+ bootstrap from it instead.
86
+
87
+ ## How it works
88
+
89
+ ```
90
+ scheduleRenderPdf ─► RenderPdfJob (queue consumer)
91
+ │ fork()
92
+
93
+ render-worker (separate process)
94
+ ├─ bootstrap config/DI
95
+ ├─ Templates.render (template mode) ─► HTML
96
+ ├─ PdfRenderer.renderHtmlToFile ──── onProgress ─┐
97
+ └─ fs provider.upload(tmp → output.path) │
98
+ ▲ │
99
+ progress(percent, {phase, message}) ◄── IPC ◄─────────────────────-─┘
100
+ (persisted to the job model, exposed over HTTP)
101
+ ```
@@ -0,0 +1,38 @@
1
+ import { ChildProcess } from 'child_process';
2
+ import { QueueJob, JobProgressCallback } from '@spinajs/queue';
3
+ import { Log } from '@spinajs/log';
4
+ import { IRenderRequest, IRenderOutput } from './protocol.js';
5
+ /**
6
+ * Queue job that renders a PDF in an isolated worker process and reports render
7
+ * progress (percent + phase + message) back to the queue. All heavy/crash-prone
8
+ * work (Chromium, template compile, fs upload) runs in the forked worker; this
9
+ * class only supervises it.
10
+ */
11
+ export declare class RenderPdfJob extends QueueJob {
12
+ protected Log: Log;
13
+ /** Template path (template mode) or raw HTML string. */
14
+ input: string;
15
+ /** When true, `input` is a template rendered by extension; otherwise raw HTML. */
16
+ template?: boolean;
17
+ model?: unknown;
18
+ lang?: string;
19
+ /** Destination @spinajs/fs provider + path. */
20
+ output: IRenderOutput;
21
+ pdfOptions?: Record<string, unknown>;
22
+ assetBasePath?: string;
23
+ /** Optional inline worker config; omit to re-bootstrap the ambient app config. */
24
+ config?: unknown;
25
+ /** Max render duration before the worker is killed (ms). */
26
+ timeoutMs?: number;
27
+ execute(progress: JobProgressCallback): Promise<unknown>;
28
+ /** Spawn the render worker process. Overridable in tests. */
29
+ protected spawnWorker(): ChildProcess;
30
+ protected buildRequest(): IRenderRequest;
31
+ /**
32
+ * Drive one worker to completion: relay progress to the queue, resolve on
33
+ * `done`, reject on `error` / unexpected exit, and force-kill on timeout.
34
+ * Every terminal path clears the timer and detaches listeners exactly once.
35
+ */
36
+ protected superviseChild(child: ChildProcess, progress: JobProgressCallback): Promise<IRenderOutput>;
37
+ }
38
+ //# sourceMappingURL=RenderPdfJob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RenderPdfJob.d.ts","sourceRoot":"","sources":["../../src/RenderPdfJob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,YAAY,EAAE,MAAM,eAAe,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAO,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAiB,MAAM,eAAe,CAAC;AAqB7E;;;;;GAKG;AACH,qBACa,YAAa,SAAQ,QAAQ;IAExC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB,wDAAwD;IACjD,KAAK,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IACxC,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IAC9B,kFAAkF;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;IACxB,4DAA4D;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEb,OAAO,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrE,6DAA6D;IAC7D,SAAS,CAAC,WAAW,IAAI,YAAY;IAIrC,SAAS,CAAC,YAAY,IAAI,cAAc;IAaxC;;;;OAIG;IACH,SAAS,CAAC,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;CA6CrG"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RenderPdfJob = void 0;
13
+ const child_process_1 = require("child_process");
14
+ const path_1 = require("path");
15
+ const url_1 = require("url");
16
+ const queue_1 = require("@spinajs/queue");
17
+ const log_1 = require("@spinajs/log");
18
+ /** Default max render duration before the worker is force-killed (ms). */
19
+ const DEFAULT_RENDER_TIMEOUT_MS = 120000;
20
+ /**
21
+ * This module's directory, resolved across the dual ESM/CJS build. Under CJS
22
+ * `__dirname` exists; under ESM it does not, so we fall back to `import.meta.url`
23
+ * - accessed via `eval` so the `import.meta` token never appears in the
24
+ * commonjs-compiled output (which would otherwise fail to compile).
25
+ */
26
+ function moduleDir() {
27
+ if (typeof __dirname !== 'undefined') {
28
+ return __dirname;
29
+ }
30
+ // eslint-disable-next-line no-eval
31
+ const url = eval('import.meta.url');
32
+ return (0, path_1.dirname)((0, url_1.fileURLToPath)(url));
33
+ }
34
+ /**
35
+ * Queue job that renders a PDF in an isolated worker process and reports render
36
+ * progress (percent + phase + message) back to the queue. All heavy/crash-prone
37
+ * work (Chromium, template compile, fs upload) runs in the forked worker; this
38
+ * class only supervises it.
39
+ */
40
+ let RenderPdfJob = class RenderPdfJob extends queue_1.QueueJob {
41
+ async execute(progress) {
42
+ const child = this.spawnWorker();
43
+ return this.superviseChild(child, progress);
44
+ }
45
+ /** Spawn the render worker process. Overridable in tests. */
46
+ spawnWorker() {
47
+ return (0, child_process_1.fork)((0, path_1.join)(moduleDir(), 'render-worker.js'));
48
+ }
49
+ buildRequest() {
50
+ return {
51
+ input: this.input,
52
+ template: this.template,
53
+ model: this.model,
54
+ lang: this.lang,
55
+ output: this.output,
56
+ pdfOptions: this.pdfOptions,
57
+ assetBasePath: this.assetBasePath,
58
+ config: this.config,
59
+ };
60
+ }
61
+ /**
62
+ * Drive one worker to completion: relay progress to the queue, resolve on
63
+ * `done`, reject on `error` / unexpected exit, and force-kill on timeout.
64
+ * Every terminal path clears the timer and detaches listeners exactly once.
65
+ */
66
+ superviseChild(child, progress) {
67
+ const timeoutMs = this.timeoutMs ?? DEFAULT_RENDER_TIMEOUT_MS;
68
+ return new Promise((resolve, reject) => {
69
+ let settled = false;
70
+ const settle = (action) => {
71
+ if (settled) {
72
+ return;
73
+ }
74
+ settled = true;
75
+ clearTimeout(timer);
76
+ child.removeAllListeners('message');
77
+ child.removeAllListeners('error');
78
+ child.removeAllListeners('exit');
79
+ action();
80
+ };
81
+ const timer = setTimeout(() => {
82
+ settle(() => reject(new Error(`Render worker timed out after ${timeoutMs}ms`)));
83
+ child.kill('SIGKILL');
84
+ }, timeoutMs);
85
+ child.on('message', (m) => {
86
+ switch (m.type) {
87
+ case 'progress':
88
+ // fire-and-forget: never block the worker on progress persistence
89
+ progress(m.percent, { phase: m.phase, message: m.message }).catch((err) => this.Log?.warn(`Failed to persist progress: ${err.message}`));
90
+ break;
91
+ case 'done':
92
+ settle(() => resolve(m.result));
93
+ break;
94
+ case 'error':
95
+ settle(() => reject(new Error(m.message)));
96
+ child.kill();
97
+ break;
98
+ }
99
+ });
100
+ child.on('error', (err) => settle(() => reject(err)));
101
+ child.on('exit', (code) => settle(() => reject(new Error(`Render worker exited unexpectedly with code ${code}`))));
102
+ child.send(this.buildRequest());
103
+ });
104
+ }
105
+ };
106
+ exports.RenderPdfJob = RenderPdfJob;
107
+ __decorate([
108
+ (0, log_1.Logger)('RenderPdfJob'),
109
+ __metadata("design:type", log_1.Log)
110
+ ], RenderPdfJob.prototype, "Log", void 0);
111
+ exports.RenderPdfJob = RenderPdfJob = __decorate([
112
+ (0, queue_1.Job)()
113
+ ], RenderPdfJob);
114
+ //# sourceMappingURL=RenderPdfJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RenderPdfJob.js","sourceRoot":"","sources":["../../src/RenderPdfJob.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export * from './protocol.js';
2
+ export * from './render.js';
3
+ export * from './RenderPdfJob.js';
4
+ export * from './schedule.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ // @spinajs/queue-templates-pdf
3
+ //
4
+ // A queue job that renders a PDF template in an isolated worker process and
5
+ // reports render progress (percent + phase + message) back to the queue.
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ __exportStar(require("./protocol.js"), exports);
22
+ __exportStar(require("./render.js"), exports);
23
+ __exportStar(require("./RenderPdfJob.js"), exports);
24
+ __exportStar(require("./schedule.js"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,+BAA+B;AAC/B,EAAE;AACF,4EAA4E;AAC5E,yEAAyE;;;;;;;;;;;;;;;;AAEzE,gDAA8B;AAC9B,8CAA4B;AAC5B,oDAAkC;AAClC,gDAA8B"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Where a rendered PDF is written - a named @spinajs/fs provider and a path
3
+ * relative to that provider's base.
4
+ */
5
+ export interface IRenderOutput {
6
+ /** Configured @spinajs/fs provider name (local / temp / s3 / ...). */
7
+ provider: string;
8
+ /** Destination path relative to the provider base. */
9
+ path: string;
10
+ }
11
+ /**
12
+ * A single PDF render request handed to the worker process.
13
+ */
14
+ export interface IRenderRequest {
15
+ /** Template path (template mode) or a raw HTML string. */
16
+ input: string;
17
+ /** When true, `input` is a template rendered via the text engine by extension; otherwise it is raw HTML. */
18
+ template?: boolean;
19
+ /** Model passed to the template (template mode). */
20
+ model?: unknown;
21
+ /** Optional language (template mode). */
22
+ lang?: string;
23
+ /** Where to write the resulting PDF. */
24
+ output: IRenderOutput;
25
+ /** Puppeteer PDF options (format, landscape, scale, ...). */
26
+ pdfOptions?: Record<string, unknown>;
27
+ /** Directory served over the local http server so relative asset URLs resolve (raw HTML mode). */
28
+ assetBasePath?: string;
29
+ /**
30
+ * Optional inline configuration for the worker. When present it is used to
31
+ * bootstrap the worker's Configuration; otherwise the worker resolves the
32
+ * ambient app Configuration (re-bootstrap model).
33
+ */
34
+ config?: unknown;
35
+ }
36
+ /** Messages the worker sends back to its parent over the IPC channel. */
37
+ export type WorkerMessage = {
38
+ type: 'progress';
39
+ percent: number;
40
+ phase: string;
41
+ message?: string;
42
+ } | {
43
+ type: 'done';
44
+ result: IRenderOutput;
45
+ } | {
46
+ type: 'error';
47
+ message: string;
48
+ };
49
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,4GAA4G;IAC5G,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,EAAE,aAAa,CAAC;IACtB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,kGAAkG;IAClG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,yEAAyE;AACzE,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=render-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-worker.d.ts","sourceRoot":"","sources":["../../src/render-worker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const di_1 = require("@spinajs/di");
4
+ const render_js_1 = require("./render.js");
5
+ /**
6
+ * Render worker entrypoint. Forked by {@link RenderPdfJob} with an IPC channel:
7
+ * the parent sends an {@link IRenderRequest}, the worker streams `progress`
8
+ * messages and finishes with `done` or `error`, then exits so its process (and
9
+ * the pooled Chromium) is fully reclaimed.
10
+ */
11
+ function send(message) {
12
+ process.send?.(message);
13
+ }
14
+ process.on('message', async (req) => {
15
+ try {
16
+ const result = await (0, render_js_1.renderPdfToProvider)(req, (m) => send(m));
17
+ send({ type: 'done', result });
18
+ await di_1.DI.dispose();
19
+ process.exit(0);
20
+ }
21
+ catch (err) {
22
+ send({ type: 'error', message: err?.message ?? String(err) });
23
+ try {
24
+ await di_1.DI.dispose();
25
+ }
26
+ catch {
27
+ /* best-effort cleanup on the error path */
28
+ }
29
+ process.exit(1);
30
+ }
31
+ });
32
+ //# sourceMappingURL=render-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-worker.js","sourceRoot":"","sources":["../../src/render-worker.ts"],"names":[],"mappings":";;AAAA,oCAAiC;AACjC,2CAAkD;AAGlD;;;;;GAKG;AACH,SAAS,IAAI,CAAC,OAAsB;IAClC,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAmB,EAAE,EAAE;IAClD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAmB,EAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/B,MAAM,OAAE,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,OAAE,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,2CAA2C;QAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { IRenderRequest, IRenderOutput, WorkerMessage } from './protocol.js';
2
+ import '@spinajs/templates-pdf';
3
+ import '@spinajs/fs';
4
+ type ProgressMessage = Extract<WorkerMessage, {
5
+ type: 'progress';
6
+ }>;
7
+ /**
8
+ * Render a PDF for `req` and upload it to the requested @spinajs/fs provider,
9
+ * reporting progress via `onProgress`. This is the testable core shared by the
10
+ * worker entrypoint - it performs the heavy work (template compile, Chromium
11
+ * render, upload) and cleans up its temp file.
12
+ *
13
+ * @returns the output descriptor (provider + path) on success.
14
+ */
15
+ export declare function renderPdfToProvider(req: IRenderRequest, onProgress: (m: ProgressMessage) => void): Promise<IRenderOutput>;
16
+ export {};
17
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/render.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG7E,OAAO,wBAAwB,CAAC;AAChC,OAAO,aAAa,CAAC;AAErB,KAAK,eAAe,GAAG,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AA4BpE;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,CA0B/H"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderPdfToProvider = renderPdfToProvider;
4
+ const di_1 = require("@spinajs/di");
5
+ const configuration_1 = require("@spinajs/configuration");
6
+ const templates_1 = require("@spinajs/templates");
7
+ const templates_pdf_1 = require("@spinajs/templates-pdf");
8
+ const fs_1 = require("@spinajs/fs");
9
+ const path_1 = require("path");
10
+ const os_1 = require("os");
11
+ const promises_1 = require("fs/promises");
12
+ // registers the PDF renderer (+ puppeteer/pug) and the fs providers as a side effect
13
+ require("@spinajs/templates-pdf");
14
+ require("@spinajs/fs");
15
+ let tmpCounter = 0;
16
+ /**
17
+ * Bootstrap the worker's DI/config. With an inline `config` a Configuration is
18
+ * registered from it; otherwise the ambient Configuration is resolved (the
19
+ * re-bootstrap model - the worker shares the app's config environment). The fs
20
+ * providers are then initialized.
21
+ */
22
+ async function bootstrap(config) {
23
+ if (config) {
24
+ class WorkerConfiguration extends configuration_1.FrameworkConfiguration {
25
+ onLoad() {
26
+ return config;
27
+ }
28
+ }
29
+ di_1.DI.register(WorkerConfiguration).as(configuration_1.Configuration);
30
+ }
31
+ await di_1.DI.resolve(configuration_1.Configuration);
32
+ // register the `__file_provider__` factory, then build the configured providers
33
+ const fsBootstrapper = await di_1.DI.resolve(fs_1.FsBootsrapper);
34
+ fsBootstrapper.bootstrap();
35
+ await di_1.DI.resolve(fs_1.fsService);
36
+ }
37
+ /**
38
+ * Render a PDF for `req` and upload it to the requested @spinajs/fs provider,
39
+ * reporting progress via `onProgress`. This is the testable core shared by the
40
+ * worker entrypoint - it performs the heavy work (template compile, Chromium
41
+ * render, upload) and cleans up its temp file.
42
+ *
43
+ * @returns the output descriptor (provider + path) on success.
44
+ */
45
+ async function renderPdfToProvider(req, onProgress) {
46
+ await bootstrap(req.config);
47
+ const templates = await di_1.DI.resolve(templates_1.Templates);
48
+ const renderer = await di_1.DI.resolve(templates_pdf_1.PdfRenderer, [req.pdfOptions ?? {}]);
49
+ const provider = await di_1.DI.resolve('__file_provider__', [req.output.provider]);
50
+ const html = req.template ? await templates.render(req.input, req.model, req.lang) : req.input;
51
+ const tmp = (0, path_1.join)((0, os_1.tmpdir)(), `spinajs-pdf-${process.pid}-${Date.now()}-${tmpCounter++}.pdf`);
52
+ try {
53
+ await renderer.renderHtmlToFile(html, tmp, {
54
+ assetBasePath: req.assetBasePath,
55
+ onProgress: (p) => onProgress({ type: 'progress', percent: p.percent, phase: p.phase, message: p.message }),
56
+ });
57
+ // push the locally-rendered temp file to the configured destination provider
58
+ await provider.upload(tmp, req.output.path);
59
+ return req.output;
60
+ }
61
+ finally {
62
+ await (0, promises_1.unlink)(tmp).catch(() => {
63
+ /* temp may not exist if the render failed before writing */
64
+ });
65
+ }
66
+ }
67
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render.ts"],"names":[],"mappings":";;AAkDA,kDA0BC;AA5ED,oCAAiC;AACjC,0DAA+E;AAC/E,kDAA+C;AAC/C,0DAAqD;AACrD,oCAA2D;AAC3D,+BAA4B;AAC5B,2BAA4B;AAC5B,0CAAqC;AAGrC,qFAAqF;AACrF,kCAAgC;AAChC,uBAAqB;AAIrB,IAAI,UAAU,GAAG,CAAC,CAAC;AAEnB;;;;;GAKG;AACH,KAAK,UAAU,SAAS,CAAC,MAAgB;IACvC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,mBAAoB,SAAQ,sCAAsB;YAC5C,MAAM;gBACd,OAAO,MAAM,CAAC;YAChB,CAAC;SACF;QACD,OAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,6BAAa,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,OAAE,CAAC,OAAO,CAAC,6BAAa,CAAC,CAAC;IAEhC,gFAAgF;IAChF,MAAM,cAAc,GAAG,MAAM,OAAE,CAAC,OAAO,CAAC,kBAAa,CAAC,CAAC;IACvD,cAAc,CAAC,SAAS,EAAE,CAAC;IAC3B,MAAM,OAAE,CAAC,OAAO,CAAC,cAAS,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,mBAAmB,CAAC,GAAmB,EAAE,UAAwC;IACrG,MAAM,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE5B,MAAM,SAAS,GAAG,MAAM,OAAE,CAAC,OAAO,CAAC,qBAAS,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,OAAE,CAAC,OAAO,CAAC,2BAAW,EAAE,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,MAAM,OAAE,CAAC,OAAO,CAAK,mBAAmB,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAElF,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;IAE/F,MAAM,GAAG,GAAG,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,eAAe,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,MAAM,CAAC,CAAC;IAE3F,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE;YACzC,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SAC5G,CAAC,CAAC;QAEH,6EAA6E;QAC7E,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE5C,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,IAAA,iBAAM,EAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YAC3B,4DAA4D;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { IRenderOutput } from './protocol.js';
2
+ /** Payload for a {@link RenderPdfJob} - the fields describing what to render and where. */
3
+ export interface IRenderPdfJobPayload {
4
+ /** Template path (template mode) or raw HTML string. */
5
+ input: string;
6
+ /** When true, `input` is a template rendered by extension; otherwise raw HTML. */
7
+ template?: boolean;
8
+ model?: unknown;
9
+ lang?: string;
10
+ /** Destination @spinajs/fs provider + path. */
11
+ output: IRenderOutput;
12
+ pdfOptions?: Record<string, unknown>;
13
+ assetBasePath?: string;
14
+ /** Optional inline worker config; omit to re-bootstrap the ambient app config. */
15
+ config?: unknown;
16
+ /** Max render duration before the worker is killed (ms). */
17
+ timeoutMs?: number;
18
+ }
19
+ /** Scheduling options for {@link scheduleRenderPdf}. */
20
+ export interface IScheduleRenderPdfOptions {
21
+ /** Delay before the job is delivered (ms). */
22
+ delay?: number;
23
+ /** Cron expression for recurring rendering (e.g. `0 6 * * *` for a daily report). */
24
+ cron?: string;
25
+ /** Period between repeats (ms), used with `repeat`. */
26
+ period?: number;
27
+ /** Number of times to repeat the schedule. */
28
+ repeat?: number;
29
+ }
30
+ /**
31
+ * Enqueue a PDF render job. With no options it runs as soon as a consumer picks
32
+ * it up; `delay` schedules it later; `cron` (or `period` + `repeat`) makes it
33
+ * recurring.
34
+ *
35
+ * Progress is tracked on the queue job model and exposed via
36
+ * `@spinajs/queue-http-progress` at `GET jobs/v1/:jobId/status`
37
+ * (percent + phase + message).
38
+ *
39
+ * @returns the JobId, for correlating the render with its progress/status endpoint.
40
+ *
41
+ * @example
42
+ * // render now, then poll GET jobs/v1/:jobId/status
43
+ * const jobId = await scheduleRenderPdf({ input: 'invoice.pug', template: true, model, output: { provider: 's3', path: 'invoices/1.pdf' } });
44
+ * // daily at 6am
45
+ * await scheduleRenderPdf({ input: 'report.pug', template: true, output: { provider: 'local', path: 'daily.pdf' } }, { cron: '0 6 * * *' });
46
+ */
47
+ export declare function scheduleRenderPdf(payload: IRenderPdfJobPayload, options?: IScheduleRenderPdfOptions): Promise<string | undefined>;
48
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/schedule.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,2FAA2F;AAC3F,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wDAAwD;AACxD,MAAM,WAAW,yBAAyB;IACxC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAWvI"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scheduleRenderPdf = scheduleRenderPdf;
4
+ const RenderPdfJob_js_1 = require("./RenderPdfJob.js");
5
+ /**
6
+ * Enqueue a PDF render job. With no options it runs as soon as a consumer picks
7
+ * it up; `delay` schedules it later; `cron` (or `period` + `repeat`) makes it
8
+ * recurring.
9
+ *
10
+ * Progress is tracked on the queue job model and exposed via
11
+ * `@spinajs/queue-http-progress` at `GET jobs/v1/:jobId/status`
12
+ * (percent + phase + message).
13
+ *
14
+ * @returns the JobId, for correlating the render with its progress/status endpoint.
15
+ *
16
+ * @example
17
+ * // render now, then poll GET jobs/v1/:jobId/status
18
+ * const jobId = await scheduleRenderPdf({ input: 'invoice.pug', template: true, model, output: { provider: 's3', path: 'invoices/1.pdf' } });
19
+ * // daily at 6am
20
+ * await scheduleRenderPdf({ input: 'report.pug', template: true, output: { provider: 'local', path: 'daily.pdf' } }, { cron: '0 6 * * *' });
21
+ */
22
+ async function scheduleRenderPdf(payload, options) {
23
+ // Only include schedule fields that are set. IMessageOptions declares all fields
24
+ // required, but emit() spreads options into the message, so absent fields behave
25
+ // exactly like calling emit with no options.
26
+ const scheduleOptions = {};
27
+ if (options?.delay !== undefined)
28
+ scheduleOptions.ScheduleDelay = options.delay;
29
+ if (options?.cron !== undefined)
30
+ scheduleOptions.ScheduleCron = options.cron;
31
+ if (options?.period !== undefined)
32
+ scheduleOptions.SchedulePeriod = options.period;
33
+ if (options?.repeat !== undefined)
34
+ scheduleOptions.ScheduleRepeat = options.repeat;
35
+ return RenderPdfJob_js_1.RenderPdfJob.emit(payload, scheduleOptions);
36
+ }
37
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/schedule.ts"],"names":[],"mappings":";;AAmDA,8CAWC;AA7DD,uDAAiD;AAiCjD;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,iBAAiB,CAAC,OAA6B,EAAE,OAAmC;IACxG,iFAAiF;IACjF,iFAAiF;IACjF,6CAA6C;IAC7C,MAAM,eAAe,GAA6B,EAAE,CAAC;IACrD,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS;QAAE,eAAe,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC;IAChF,IAAI,OAAO,EAAE,IAAI,KAAK,SAAS;QAAE,eAAe,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7E,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS;QAAE,eAAe,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IACnF,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS;QAAE,eAAe,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAEnF,OAAO,8BAAY,CAAC,IAAI,CAAC,OAAO,EAAE,eAAkC,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { ChildProcess } from 'child_process';
2
+ import { QueueJob, JobProgressCallback } from '@spinajs/queue';
3
+ import { Log } from '@spinajs/log';
4
+ import { IRenderRequest, IRenderOutput } from './protocol.js';
5
+ /**
6
+ * Queue job that renders a PDF in an isolated worker process and reports render
7
+ * progress (percent + phase + message) back to the queue. All heavy/crash-prone
8
+ * work (Chromium, template compile, fs upload) runs in the forked worker; this
9
+ * class only supervises it.
10
+ */
11
+ export declare class RenderPdfJob extends QueueJob {
12
+ protected Log: Log;
13
+ /** Template path (template mode) or raw HTML string. */
14
+ input: string;
15
+ /** When true, `input` is a template rendered by extension; otherwise raw HTML. */
16
+ template?: boolean;
17
+ model?: unknown;
18
+ lang?: string;
19
+ /** Destination @spinajs/fs provider + path. */
20
+ output: IRenderOutput;
21
+ pdfOptions?: Record<string, unknown>;
22
+ assetBasePath?: string;
23
+ /** Optional inline worker config; omit to re-bootstrap the ambient app config. */
24
+ config?: unknown;
25
+ /** Max render duration before the worker is killed (ms). */
26
+ timeoutMs?: number;
27
+ execute(progress: JobProgressCallback): Promise<unknown>;
28
+ /** Spawn the render worker process. Overridable in tests. */
29
+ protected spawnWorker(): ChildProcess;
30
+ protected buildRequest(): IRenderRequest;
31
+ /**
32
+ * Drive one worker to completion: relay progress to the queue, resolve on
33
+ * `done`, reject on `error` / unexpected exit, and force-kill on timeout.
34
+ * Every terminal path clears the timer and detaches listeners exactly once.
35
+ */
36
+ protected superviseChild(child: ChildProcess, progress: JobProgressCallback): Promise<IRenderOutput>;
37
+ }
38
+ //# sourceMappingURL=RenderPdfJob.d.ts.map