@things-factory/integration-headless 7.0.39 → 7.0.41
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/dist-server/engine/connector/headless-connector.d.ts +1 -0
- package/dist-server/engine/connector/headless-connector.js +3 -0
- package/dist-server/engine/connector/headless-connector.js.map +1 -1
- package/dist-server/engine/task/headless-pdf-capture-board.d.ts +1 -0
- package/dist-server/engine/task/headless-pdf-capture-board.js +311 -0
- package/dist-server/engine/task/headless-pdf-capture-board.js.map +1 -0
- package/dist-server/engine/task/headless-pdf-capture.js +78 -19
- package/dist-server/engine/task/headless-pdf-capture.js.map +1 -1
- package/dist-server/engine/task/headless-pdf-open.js +246 -18
- package/dist-server/engine/task/headless-pdf-open.js.map +1 -1
- package/dist-server/engine/task/headless-pdf-save.js +43 -110
- package/dist-server/engine/task/headless-pdf-save.js.map +1 -1
- package/dist-server/engine/task/index.d.ts +1 -0
- package/dist-server/engine/task/index.js +1 -0
- package/dist-server/engine/task/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/integration/connector/headless-connector.ja.md +71 -0
- package/helps/integration/connector/headless-connector.ko.md +72 -0
- package/helps/integration/connector/headless-connector.md +71 -0
- package/helps/integration/connector/headless-connector.ms.md +73 -0
- package/helps/integration/connector/headless-connector.zh.md +71 -0
- package/helps/integration/task/headless-pdf-capture-board.ja.md +51 -0
- package/helps/integration/task/headless-pdf-capture-board.ko.md +51 -0
- package/helps/integration/task/headless-pdf-capture-board.md +51 -0
- package/helps/integration/task/headless-pdf-capture-board.ms.md +53 -0
- package/helps/integration/task/headless-pdf-capture-board.zh.md +51 -0
- package/helps/integration/task/headless-pdf-capture.ja.md +45 -0
- package/helps/integration/task/headless-pdf-capture.ko.md +45 -0
- package/helps/integration/task/headless-pdf-capture.md +45 -0
- package/helps/integration/task/headless-pdf-capture.ms.md +47 -0
- package/helps/integration/task/headless-pdf-capture.zh.md +45 -0
- package/helps/integration/task/headless-pdf-open.ja.md +55 -0
- package/helps/integration/task/headless-pdf-open.ko.md +55 -0
- package/helps/integration/task/headless-pdf-open.md +55 -0
- package/helps/integration/task/headless-pdf-open.ms.md +57 -0
- package/helps/integration/task/headless-pdf-open.zh.md +55 -0
- package/helps/integration/task/headless-pdf-save.ja.md +23 -0
- package/helps/integration/task/headless-pdf-save.ko.md +25 -0
- package/helps/integration/task/headless-pdf-save.md +23 -0
- package/helps/integration/task/headless-pdf-save.ms.md +23 -0
- package/helps/integration/task/headless-pdf-save.zh.md +23 -0
- package/package.json +5 -3
- package/server/engine/connector/headless-connector.ts +4 -0
- package/server/engine/task/headless-pdf-capture-board.ts +363 -0
- package/server/engine/task/headless-pdf-capture.ts +85 -20
- package/server/engine/task/headless-pdf-open.ts +277 -18
- package/server/engine/task/headless-pdf-save.ts +53 -124
- package/server/engine/task/index.ts +1 -0
- package/translations/en.json +1 -0
- package/translations/ko.json +1 -0
|
@@ -1,29 +1,168 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const ejs = tslib_1.__importStar(require("ejs"));
|
|
3
5
|
const pdf_lib_1 = require("pdf-lib");
|
|
4
6
|
const integration_base_1 = require("@things-factory/integration-base");
|
|
5
7
|
const integration_base_2 = require("@things-factory/integration-base");
|
|
8
|
+
const utils_1 = require("@things-factory/utils");
|
|
6
9
|
async function HeadlessPDFOpen(step, context) {
|
|
7
10
|
var { connection: connectionName, params: stepOptions } = step;
|
|
8
|
-
var { coverPage, lastPage, header, footer, watermark, fileName
|
|
9
|
-
|
|
10
|
-
const pdf = await pdf_lib_1.PDFDocument.create();
|
|
11
|
+
var { accessor, coverPage, lastPage, header, footer, watermark, fileName, format, width, height, marginTop, marginBottom, marginLeft, marginRight, scale, printBackground, landscape, preferCSSPageSize } = stepOptions || {};
|
|
12
|
+
const { data, logger } = context;
|
|
11
13
|
const headlessPool = integration_base_2.ConnectionManager.getConnectionInstanceByName(context.domain, connectionName);
|
|
12
14
|
let browser;
|
|
15
|
+
// Create a new PDF document using pdf-lib
|
|
16
|
+
const pdfDoc = await pdf_lib_1.PDFDocument.create();
|
|
13
17
|
try {
|
|
14
18
|
browser = await headlessPool.acquire();
|
|
15
19
|
const page = await browser.newPage();
|
|
16
|
-
|
|
20
|
+
const templateInput = (0, utils_1.access)(accessor, data);
|
|
21
|
+
const renderTemplateSafely = (template, data) => {
|
|
22
|
+
try {
|
|
23
|
+
return ejs.render(template, data);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
logger.warn(`Template rendering error: ${error.message}`);
|
|
27
|
+
return template;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
// Convert Cover Page to PDF and add it to the document (if provided)
|
|
17
31
|
if (coverPage) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
32
|
+
const renderedCoverPage = renderTemplateSafely(coverPage, templateInput);
|
|
33
|
+
await page.setContent(renderedCoverPage);
|
|
34
|
+
// Apply header, footer, and watermark using Puppeteer
|
|
35
|
+
// Apply header, footer, and watermark using Puppeteer
|
|
36
|
+
if (header || footer || watermark) {
|
|
37
|
+
await page.evaluate(({ header, footer, watermark, isLandscape }) => {
|
|
38
|
+
const setPositioning = (element, position) => {
|
|
39
|
+
element.style.position = 'fixed';
|
|
40
|
+
element.style.left = '0';
|
|
41
|
+
element.style.width = '100%';
|
|
42
|
+
element.style.textAlign = 'center';
|
|
43
|
+
element.style.fontSize = '12px';
|
|
44
|
+
if (position === 'header') {
|
|
45
|
+
element.style.top = '0';
|
|
46
|
+
}
|
|
47
|
+
else if (position === 'footer') {
|
|
48
|
+
element.style.bottom = '0';
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
// if (header) {
|
|
52
|
+
// const headerElement = document.createElement('div')
|
|
53
|
+
// headerElement.innerHTML = header
|
|
54
|
+
// setPositioning(headerElement, 'header')
|
|
55
|
+
// document.body.appendChild(headerElement)
|
|
56
|
+
// }
|
|
57
|
+
// if (footer) {
|
|
58
|
+
// const footerElement = document.createElement('div')
|
|
59
|
+
// footerElement.innerHTML = footer
|
|
60
|
+
// setPositioning(footerElement, 'footer')
|
|
61
|
+
// document.body.appendChild(footerElement)
|
|
62
|
+
// }
|
|
63
|
+
if (watermark) {
|
|
64
|
+
const watermarkElement = document.createElement('div');
|
|
65
|
+
watermarkElement.innerHTML = watermark;
|
|
66
|
+
watermarkElement.style.position = 'fixed';
|
|
67
|
+
watermarkElement.style.top = isLandscape ? '40%' : '50%';
|
|
68
|
+
watermarkElement.style.left = '50%';
|
|
69
|
+
watermarkElement.style.transform = 'translate(-50%, -50%) rotate(-45deg)';
|
|
70
|
+
watermarkElement.style.opacity = '0.2';
|
|
71
|
+
watermarkElement.style.fontSize = '50px';
|
|
72
|
+
watermarkElement.style.color = 'red';
|
|
73
|
+
watermarkElement.style.pointerEvents = 'none';
|
|
74
|
+
watermarkElement.style.zIndex = '9999';
|
|
75
|
+
document.body.appendChild(watermarkElement);
|
|
76
|
+
}
|
|
77
|
+
}, { header, footer, watermark, isLandscape: landscape });
|
|
78
|
+
}
|
|
79
|
+
const pageOptions = {
|
|
80
|
+
format,
|
|
81
|
+
width,
|
|
82
|
+
height,
|
|
83
|
+
margin: {
|
|
84
|
+
top: marginTop,
|
|
85
|
+
right: marginRight,
|
|
86
|
+
bottom: marginBottom,
|
|
87
|
+
left: marginLeft
|
|
88
|
+
},
|
|
89
|
+
scale,
|
|
90
|
+
printBackground,
|
|
91
|
+
landscape,
|
|
92
|
+
displayHeaderFooter: false, // Handled via Puppeteer directly
|
|
93
|
+
preferCSSPageSize
|
|
94
|
+
};
|
|
95
|
+
const coverPageBuffer = await page.pdf(pageOptions);
|
|
96
|
+
const coverPageDoc = await pdf_lib_1.PDFDocument.load(coverPageBuffer);
|
|
97
|
+
const coverPages = await pdfDoc.copyPages(coverPageDoc, coverPageDoc.getPageIndices());
|
|
98
|
+
coverPages.forEach(page => pdfDoc.addPage(page));
|
|
21
99
|
}
|
|
22
|
-
|
|
100
|
+
var lastPageBuffer;
|
|
101
|
+
// Process Last Page (if provided) but add it later in the save task
|
|
23
102
|
if (lastPage) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
103
|
+
const renderedLastPage = renderTemplateSafely(lastPage, templateInput);
|
|
104
|
+
await page.setContent(renderedLastPage);
|
|
105
|
+
// Apply header, footer, and watermark using Puppeteer
|
|
106
|
+
if (header || footer || watermark) {
|
|
107
|
+
await page.evaluate(({ header, footer, watermark, isLandscape }) => {
|
|
108
|
+
const setPositioning = (element, position) => {
|
|
109
|
+
element.style.position = 'fixed';
|
|
110
|
+
element.style.left = '0';
|
|
111
|
+
element.style.width = '100%';
|
|
112
|
+
element.style.textAlign = 'center';
|
|
113
|
+
element.style.fontSize = '12px';
|
|
114
|
+
if (position === 'header') {
|
|
115
|
+
element.style.top = '0';
|
|
116
|
+
}
|
|
117
|
+
else if (position === 'footer') {
|
|
118
|
+
element.style.bottom = '0';
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
// if (header) {
|
|
122
|
+
// const headerElement = document.createElement('div')
|
|
123
|
+
// headerElement.innerHTML = header
|
|
124
|
+
// setPositioning(headerElement, 'header')
|
|
125
|
+
// document.body.appendChild(headerElement)
|
|
126
|
+
// }
|
|
127
|
+
// if (footer) {
|
|
128
|
+
// const footerElement = document.createElement('div')
|
|
129
|
+
// footerElement.innerHTML = footer
|
|
130
|
+
// setPositioning(footerElement, 'footer')
|
|
131
|
+
// document.body.appendChild(footerElement)
|
|
132
|
+
// }
|
|
133
|
+
if (watermark) {
|
|
134
|
+
const watermarkElement = document.createElement('div');
|
|
135
|
+
watermarkElement.innerHTML = watermark;
|
|
136
|
+
watermarkElement.style.position = 'fixed';
|
|
137
|
+
watermarkElement.style.top = isLandscape ? '40%' : '50%';
|
|
138
|
+
watermarkElement.style.left = '50%';
|
|
139
|
+
watermarkElement.style.transform = 'translate(-50%, -50%) rotate(-45deg)';
|
|
140
|
+
watermarkElement.style.opacity = '0.2';
|
|
141
|
+
watermarkElement.style.fontSize = '50px';
|
|
142
|
+
watermarkElement.style.color = 'red';
|
|
143
|
+
watermarkElement.style.pointerEvents = 'none';
|
|
144
|
+
watermarkElement.style.zIndex = '9999';
|
|
145
|
+
document.body.appendChild(watermarkElement);
|
|
146
|
+
}
|
|
147
|
+
}, { header, footer, watermark, isLandscape: landscape });
|
|
148
|
+
}
|
|
149
|
+
const pageOptions = {
|
|
150
|
+
format,
|
|
151
|
+
width,
|
|
152
|
+
height,
|
|
153
|
+
margin: {
|
|
154
|
+
top: marginTop,
|
|
155
|
+
right: marginRight,
|
|
156
|
+
bottom: marginBottom,
|
|
157
|
+
left: marginLeft
|
|
158
|
+
},
|
|
159
|
+
scale,
|
|
160
|
+
printBackground,
|
|
161
|
+
landscape,
|
|
162
|
+
displayHeaderFooter: false, // Handled via Puppeteer directly
|
|
163
|
+
preferCSSPageSize
|
|
164
|
+
};
|
|
165
|
+
lastPageBuffer = await page.pdf(pageOptions);
|
|
27
166
|
}
|
|
28
167
|
await page.close();
|
|
29
168
|
headlessPool.release(browser);
|
|
@@ -34,22 +173,26 @@ async function HeadlessPDFOpen(step, context) {
|
|
|
34
173
|
}
|
|
35
174
|
throw error;
|
|
36
175
|
}
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
lastPage,
|
|
176
|
+
const pdfInfo = {
|
|
177
|
+
pdfDoc,
|
|
178
|
+
lastPageBuffer,
|
|
41
179
|
header,
|
|
42
180
|
footer,
|
|
43
181
|
watermark,
|
|
44
182
|
fileName,
|
|
45
|
-
pageCount:
|
|
183
|
+
pageCount: pdfDoc.getPageCount()
|
|
46
184
|
};
|
|
47
|
-
context.__headless_pdf =
|
|
185
|
+
context.__headless_pdf = pdfInfo;
|
|
48
186
|
return {
|
|
49
|
-
data
|
|
187
|
+
data: pdfInfo
|
|
50
188
|
};
|
|
51
189
|
}
|
|
52
190
|
HeadlessPDFOpen.parameterSpec = [
|
|
191
|
+
{
|
|
192
|
+
type: 'scenario-step-input',
|
|
193
|
+
name: 'accessor',
|
|
194
|
+
label: 'accessor'
|
|
195
|
+
},
|
|
53
196
|
{
|
|
54
197
|
type: 'textarea',
|
|
55
198
|
name: 'coverPage',
|
|
@@ -81,6 +224,91 @@ HeadlessPDFOpen.parameterSpec = [
|
|
|
81
224
|
type: 'string',
|
|
82
225
|
name: 'fileName',
|
|
83
226
|
label: 'filename'
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
type: 'select',
|
|
230
|
+
name: 'format',
|
|
231
|
+
label: 'page-format',
|
|
232
|
+
property: {
|
|
233
|
+
options: [
|
|
234
|
+
{ display: '', value: '' },
|
|
235
|
+
{ display: 'A4', value: 'A4' },
|
|
236
|
+
{ display: 'A3', value: 'A3' },
|
|
237
|
+
{ display: 'Letter', value: 'Letter' },
|
|
238
|
+
{ display: 'Legal', value: 'Legal' }
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
description: 'Select the paper format for the PDF'
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
type: 'string',
|
|
245
|
+
name: 'width',
|
|
246
|
+
label: 'page-width',
|
|
247
|
+
placeholder: '(e.g., "8.5in", "21cm", "600px")',
|
|
248
|
+
description: 'Specify the width of the page (e.g., "8.5in", "21cm", "600px")'
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
type: 'string',
|
|
252
|
+
name: 'height',
|
|
253
|
+
label: 'page-height',
|
|
254
|
+
placeholder: '(e.g., "11in", "29.7cm", "800px")',
|
|
255
|
+
description: 'Specify the height of the page (e.g., "11in", "29.7cm", "800px")'
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
type: 'string',
|
|
259
|
+
name: 'marginTop',
|
|
260
|
+
label: 'page-margin-top',
|
|
261
|
+
placeholder: '(e.g., "0.5in", "1cm", "100px")',
|
|
262
|
+
description: 'Set the top margin for the page'
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
type: 'string',
|
|
266
|
+
name: 'marginBottom',
|
|
267
|
+
label: 'page-margin-bottom',
|
|
268
|
+
placeholder: '(e.g., "0.5in", "1cm", "100px")',
|
|
269
|
+
description: 'Set the bottom margin for the page'
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
type: 'string',
|
|
273
|
+
name: 'marginLeft',
|
|
274
|
+
label: 'page-margin-left',
|
|
275
|
+
placeholder: '(e.g., "0.5in", "1cm", "100px")',
|
|
276
|
+
description: 'Set the left margin for the page'
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
type: 'string',
|
|
280
|
+
name: 'marginRight',
|
|
281
|
+
label: 'page-margin-right',
|
|
282
|
+
placeholder: '(e.g., "0.5in", "1cm", "100px")',
|
|
283
|
+
description: 'Set the right margin for the page'
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
type: 'number',
|
|
287
|
+
name: 'scale',
|
|
288
|
+
label: 'page-scale',
|
|
289
|
+
defaultValue: 1,
|
|
290
|
+
description: 'Set the scale of the page content (default is 1)'
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
type: 'boolean',
|
|
294
|
+
name: 'printBackground',
|
|
295
|
+
label: 'print-background',
|
|
296
|
+
defaultValue: true,
|
|
297
|
+
description: 'Include background graphics when printing the page'
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
type: 'boolean',
|
|
301
|
+
name: 'landscape',
|
|
302
|
+
label: 'landscape',
|
|
303
|
+
defaultValue: false,
|
|
304
|
+
description: 'Print the PDF in landscape orientation'
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
type: 'boolean',
|
|
308
|
+
name: 'preferCSSPageSize',
|
|
309
|
+
label: 'prefer-css-page-size',
|
|
310
|
+
defaultValue: false,
|
|
311
|
+
description: 'Whether to prefer the CSS-defined page size over the given width and height'
|
|
84
312
|
}
|
|
85
313
|
];
|
|
86
314
|
HeadlessPDFOpen.help = 'integration/task/headless-pdf-open';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless-pdf-open.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-open.ts"],"names":[],"mappings":";;AACA,qCAAqC;AACrC,uEAA+D;AAC/D,uEAAoE;AAEpE,KAAK,UAAU,eAAe,CAAC,IAAI,EAAE,OAAO;IAC1C,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAC9D,IAAI,EACF,SAAS,EACT,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,CAAC,YAAY;MACtB,GAAG,WAAW,IAAI,EAAE,CAAA;IAErB,MAAM,GAAG,GAAG,MAAM,qBAAW,CAAC,MAAM,EAAE,CAAA;IAEtC,MAAM,YAAY,GAAG,oCAAiB,CAAC,2BAA2B,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAClG,IAAI,OAAO,CAAA;IAEX,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,CAAA;QACtC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;QAEpC,sBAAsB;QACtB,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;YAChC,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,CAAA;YACxC,SAAS,GAAG,eAAe,CAAA;QAC7B,CAAC;QAED,qBAAqB;QACrB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;YAC/B,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,CAAA;YACvC,QAAQ,GAAG,cAAc,CAAA;QAC3B,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;QAClB,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG;QACH,SAAS;QACT,QAAQ;QACR,MAAM;QACN,MAAM;QACN,SAAS;QACT,QAAQ;QACR,SAAS,EAAE,CAAC;KACb,CAAA;IAED,OAAO,CAAC,cAAc,GAAG,IAAI,CAAA;IAE7B,OAAO;QACL,IAAI;KACL,CAAA;AACH,CAAC;AAED,eAAe,CAAC,aAAa,GAAG;IAC9B;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,gBAAgB;KACxB;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,eAAe;KACvB;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,6CAA6C;KAC3D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,6CAA6C;KAC3D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,WAAW;KACnB;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;CACF,CAAA;AACD,eAAe,CAAC,IAAI,GAAG,oCAAoC,CAAA;AAE3D,+BAAY,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA","sourcesContent":["import * as ejs from 'ejs'\nimport { PDFDocument } from 'pdf-lib'\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { ConnectionManager } from '@things-factory/integration-base'\n\nasync function HeadlessPDFOpen(step, context) {\n var { connection: connectionName, params: stepOptions } = step\n var {\n coverPage,\n lastPage,\n header,\n footer,\n watermark,\n fileName // 추가된 파일 이름\n } = stepOptions || {}\n\n const pdf = await PDFDocument.create()\n\n const headlessPool = ConnectionManager.getConnectionInstanceByName(context.domain, connectionName)\n let browser\n\n try {\n browser = await headlessPool.acquire()\n const page = await browser.newPage()\n\n // Cover Page를 PDF로 변환\n if (coverPage) {\n await page.setContent(coverPage)\n const coverPageBuffer = await page.pdf()\n coverPage = coverPageBuffer\n }\n\n // Last Page를 PDF로 변환\n if (lastPage) {\n await page.setContent(lastPage)\n const lastPageBuffer = await page.pdf()\n lastPage = lastPageBuffer\n }\n\n await page.close()\n headlessPool.release(browser)\n } catch (error) {\n if (browser) {\n await browser.close()\n }\n throw error\n }\n\n const data = {\n pdf,\n coverPage,\n lastPage,\n header,\n footer,\n watermark,\n fileName,\n pageCount: 0\n }\n\n context.__headless_pdf = data\n\n return {\n data\n }\n}\n\nHeadlessPDFOpen.parameterSpec = [\n {\n type: 'textarea',\n name: 'coverPage',\n label: 'pdf-cover-page'\n },\n {\n type: 'textarea',\n name: 'lastPage',\n label: 'pdf-last-page'\n },\n {\n type: 'string',\n name: 'header',\n label: 'header',\n placeholder: 'Page <%= pageNumber %> of <%= totalPages %>'\n },\n {\n type: 'string',\n name: 'footer',\n label: 'footer',\n placeholder: 'Page <%= pageNumber %> of <%= totalPages %>'\n },\n {\n type: 'string',\n name: 'watermark',\n label: 'watermark'\n },\n {\n type: 'string',\n name: 'fileName',\n label: 'filename'\n }\n]\nHeadlessPDFOpen.help = 'integration/task/headless-pdf-open'\n\nTaskRegistry.registerTaskHandler('headless-pdf-open', HeadlessPDFOpen)\n"]}
|
|
1
|
+
{"version":3,"file":"headless-pdf-open.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-open.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ejs from 'ejs'\nimport { PDFDocument } from 'pdf-lib'\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { ConnectionManager } from '@things-factory/integration-base'\nimport { access } from '@things-factory/utils'\n\nasync function HeadlessPDFOpen(step, context) {\n var { connection: connectionName, params: stepOptions } = step\n var {\n accessor,\n coverPage,\n lastPage,\n header,\n footer,\n watermark,\n fileName,\n format,\n width,\n height,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n scale,\n printBackground,\n landscape,\n preferCSSPageSize\n } = stepOptions || {}\n const { data, logger } = context\n\n const headlessPool = ConnectionManager.getConnectionInstanceByName(context.domain, connectionName)\n let browser\n\n // Create a new PDF document using pdf-lib\n const pdfDoc = await PDFDocument.create()\n\n try {\n browser = await headlessPool.acquire()\n const page = await browser.newPage()\n\n const templateInput = access(accessor, data)\n\n const renderTemplateSafely = (template, data) => {\n try {\n return ejs.render(template, data)\n } catch (error) {\n logger.warn(`Template rendering error: ${error.message}`)\n return template\n }\n }\n\n // Convert Cover Page to PDF and add it to the document (if provided)\n if (coverPage) {\n const renderedCoverPage = renderTemplateSafely(coverPage, templateInput)\n\n await page.setContent(renderedCoverPage)\n\n // Apply header, footer, and watermark using Puppeteer\n // Apply header, footer, and watermark using Puppeteer\n if (header || footer || watermark) {\n await page.evaluate(\n ({ header, footer, watermark, isLandscape }) => {\n const setPositioning = (element, position) => {\n element.style.position = 'fixed'\n element.style.left = '0'\n element.style.width = '100%'\n element.style.textAlign = 'center'\n element.style.fontSize = '12px'\n if (position === 'header') {\n element.style.top = '0'\n } else if (position === 'footer') {\n element.style.bottom = '0'\n }\n }\n\n // if (header) {\n // const headerElement = document.createElement('div')\n // headerElement.innerHTML = header\n // setPositioning(headerElement, 'header')\n // document.body.appendChild(headerElement)\n // }\n\n // if (footer) {\n // const footerElement = document.createElement('div')\n // footerElement.innerHTML = footer\n // setPositioning(footerElement, 'footer')\n // document.body.appendChild(footerElement)\n // }\n\n if (watermark) {\n const watermarkElement = document.createElement('div')\n watermarkElement.innerHTML = watermark\n watermarkElement.style.position = 'fixed'\n watermarkElement.style.top = isLandscape ? '40%' : '50%'\n watermarkElement.style.left = '50%'\n watermarkElement.style.transform = 'translate(-50%, -50%) rotate(-45deg)'\n watermarkElement.style.opacity = '0.2'\n watermarkElement.style.fontSize = '50px'\n watermarkElement.style.color = 'red'\n watermarkElement.style.pointerEvents = 'none'\n watermarkElement.style.zIndex = '9999'\n document.body.appendChild(watermarkElement)\n }\n },\n { header, footer, watermark, isLandscape: landscape }\n )\n }\n\n const pageOptions = {\n format,\n width,\n height,\n margin: {\n top: marginTop,\n right: marginRight,\n bottom: marginBottom,\n left: marginLeft\n },\n scale,\n printBackground,\n landscape,\n displayHeaderFooter: false, // Handled via Puppeteer directly\n preferCSSPageSize\n }\n\n const coverPageBuffer = await page.pdf(pageOptions)\n const coverPageDoc = await PDFDocument.load(coverPageBuffer)\n const coverPages = await pdfDoc.copyPages(coverPageDoc, coverPageDoc.getPageIndices())\n coverPages.forEach(page => pdfDoc.addPage(page))\n }\n\n var lastPageBuffer\n\n // Process Last Page (if provided) but add it later in the save task\n if (lastPage) {\n const renderedLastPage = renderTemplateSafely(lastPage, templateInput)\n await page.setContent(renderedLastPage)\n\n // Apply header, footer, and watermark using Puppeteer\n if (header || footer || watermark) {\n await page.evaluate(\n ({ header, footer, watermark, isLandscape }) => {\n const setPositioning = (element, position) => {\n element.style.position = 'fixed'\n element.style.left = '0'\n element.style.width = '100%'\n element.style.textAlign = 'center'\n element.style.fontSize = '12px'\n if (position === 'header') {\n element.style.top = '0'\n } else if (position === 'footer') {\n element.style.bottom = '0'\n }\n }\n\n // if (header) {\n // const headerElement = document.createElement('div')\n // headerElement.innerHTML = header\n // setPositioning(headerElement, 'header')\n // document.body.appendChild(headerElement)\n // }\n\n // if (footer) {\n // const footerElement = document.createElement('div')\n // footerElement.innerHTML = footer\n // setPositioning(footerElement, 'footer')\n // document.body.appendChild(footerElement)\n // }\n\n if (watermark) {\n const watermarkElement = document.createElement('div')\n watermarkElement.innerHTML = watermark\n watermarkElement.style.position = 'fixed'\n watermarkElement.style.top = isLandscape ? '40%' : '50%'\n watermarkElement.style.left = '50%'\n watermarkElement.style.transform = 'translate(-50%, -50%) rotate(-45deg)'\n watermarkElement.style.opacity = '0.2'\n watermarkElement.style.fontSize = '50px'\n watermarkElement.style.color = 'red'\n watermarkElement.style.pointerEvents = 'none'\n watermarkElement.style.zIndex = '9999'\n document.body.appendChild(watermarkElement)\n }\n },\n { header, footer, watermark, isLandscape: landscape }\n )\n }\n\n const pageOptions = {\n format,\n width,\n height,\n margin: {\n top: marginTop,\n right: marginRight,\n bottom: marginBottom,\n left: marginLeft\n },\n scale,\n printBackground,\n landscape,\n displayHeaderFooter: false, // Handled via Puppeteer directly\n preferCSSPageSize\n }\n\n lastPageBuffer = await page.pdf(pageOptions)\n }\n\n await page.close()\n headlessPool.release(browser)\n } catch (error) {\n if (browser) {\n await browser.close()\n }\n throw error\n }\n\n const pdfInfo = {\n pdfDoc,\n lastPageBuffer,\n header,\n footer,\n watermark,\n fileName,\n pageCount: pdfDoc.getPageCount()\n }\n\n context.__headless_pdf = pdfInfo\n\n return {\n data: pdfInfo\n }\n}\n\nHeadlessPDFOpen.parameterSpec = [\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n },\n {\n type: 'textarea',\n name: 'coverPage',\n label: 'pdf-cover-page'\n },\n {\n type: 'textarea',\n name: 'lastPage',\n label: 'pdf-last-page'\n },\n {\n type: 'string',\n name: 'header',\n label: 'header',\n placeholder: 'Page <%= pageNumber %> of <%= totalPages %>'\n },\n {\n type: 'string',\n name: 'footer',\n label: 'footer',\n placeholder: 'Page <%= pageNumber %> of <%= totalPages %>'\n },\n {\n type: 'string',\n name: 'watermark',\n label: 'watermark'\n },\n {\n type: 'string',\n name: 'fileName',\n label: 'filename'\n },\n {\n type: 'select',\n name: 'format',\n label: 'page-format',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'A4', value: 'A4' },\n { display: 'A3', value: 'A3' },\n { display: 'Letter', value: 'Letter' },\n { display: 'Legal', value: 'Legal' }\n ]\n },\n description: 'Select the paper format for the PDF'\n },\n {\n type: 'string',\n name: 'width',\n label: 'page-width',\n placeholder: '(e.g., \"8.5in\", \"21cm\", \"600px\")',\n description: 'Specify the width of the page (e.g., \"8.5in\", \"21cm\", \"600px\")'\n },\n {\n type: 'string',\n name: 'height',\n label: 'page-height',\n placeholder: '(e.g., \"11in\", \"29.7cm\", \"800px\")',\n description: 'Specify the height of the page (e.g., \"11in\", \"29.7cm\", \"800px\")'\n },\n {\n type: 'string',\n name: 'marginTop',\n label: 'page-margin-top',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the top margin for the page'\n },\n {\n type: 'string',\n name: 'marginBottom',\n label: 'page-margin-bottom',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the bottom margin for the page'\n },\n {\n type: 'string',\n name: 'marginLeft',\n label: 'page-margin-left',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the left margin for the page'\n },\n {\n type: 'string',\n name: 'marginRight',\n label: 'page-margin-right',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the right margin for the page'\n },\n {\n type: 'number',\n name: 'scale',\n label: 'page-scale',\n defaultValue: 1,\n description: 'Set the scale of the page content (default is 1)'\n },\n {\n type: 'boolean',\n name: 'printBackground',\n label: 'print-background',\n defaultValue: true,\n description: 'Include background graphics when printing the page'\n },\n {\n type: 'boolean',\n name: 'landscape',\n label: 'landscape',\n defaultValue: false,\n description: 'Print the PDF in landscape orientation'\n },\n {\n type: 'boolean',\n name: 'preferCSSPageSize',\n label: 'prefer-css-page-size',\n defaultValue: false,\n description: 'Whether to prefer the CSS-defined page size over the given width and height'\n }\n]\n\nHeadlessPDFOpen.help = 'integration/task/headless-pdf-open'\n\nTaskRegistry.registerTaskHandler('headless-pdf-open', HeadlessPDFOpen)\n"]}
|
|
@@ -1,125 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const fs = tslib_1.__importStar(require("fs"));
|
|
5
|
-
const path = tslib_1.__importStar(require("path"));
|
|
6
|
-
const ejs = tslib_1.__importStar(require("ejs"));
|
|
7
3
|
const pdf_lib_1 = require("pdf-lib");
|
|
4
|
+
const { Readable } = require('stream');
|
|
8
5
|
const integration_base_1 = require("@things-factory/integration-base");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
pages.forEach((page, index) => {
|
|
12
|
-
const pageNumber = index + 1;
|
|
13
|
-
const pageWidth = page.getWidth();
|
|
14
|
-
// 헤더와 푸터 렌더링 (페이지 번호 및 총 페이지 수 포함)
|
|
15
|
-
if (headerTemplate || footerTemplate) {
|
|
16
|
-
const renderedHeader = headerTemplate
|
|
17
|
-
? ejs.render(headerTemplate, {
|
|
18
|
-
pageNumber,
|
|
19
|
-
totalPages
|
|
20
|
-
})
|
|
21
|
-
: '';
|
|
22
|
-
const renderedFooter = footerTemplate
|
|
23
|
-
? ejs.render(footerTemplate, {
|
|
24
|
-
pageNumber,
|
|
25
|
-
totalPages
|
|
26
|
-
})
|
|
27
|
-
: '';
|
|
28
|
-
const fontSize = 12; // 폰트 크기 설정
|
|
29
|
-
const textWidthHeader = fontSize * renderedHeader.length * 0.5;
|
|
30
|
-
const textWidthFooter = fontSize * renderedFooter.length * 0.5;
|
|
31
|
-
// Header/Footer 그리기 (가운데 정렬)
|
|
32
|
-
if (renderedHeader) {
|
|
33
|
-
page.drawText(renderedHeader, {
|
|
34
|
-
x: (pageWidth - textWidthHeader) / 2,
|
|
35
|
-
y: page.getHeight() - 30,
|
|
36
|
-
size: fontSize,
|
|
37
|
-
color: (0, pdf_lib_1.rgb)(0, 0, 0)
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
if (renderedFooter) {
|
|
41
|
-
page.drawText(renderedFooter, {
|
|
42
|
-
x: (pageWidth - textWidthFooter) / 2,
|
|
43
|
-
y: 30,
|
|
44
|
-
size: fontSize,
|
|
45
|
-
color: (0, pdf_lib_1.rgb)(0, 0, 0)
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// 워터마크 추가
|
|
50
|
-
if (watermark) {
|
|
51
|
-
const fontSize = 50;
|
|
52
|
-
page.drawText(watermark, {
|
|
53
|
-
x: pageWidth / 2 - (fontSize * watermark.length) / 4,
|
|
54
|
-
y: page.getHeight() / 2 - fontSize / 2,
|
|
55
|
-
size: fontSize,
|
|
56
|
-
color: (0, pdf_lib_1.rgb)(0.75, 0.75, 0.75),
|
|
57
|
-
rotate: (0, pdf_lib_1.degrees)(-45),
|
|
58
|
-
opacity: 0.5
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}
|
|
6
|
+
const attachment_base_1 = require("@things-factory/attachment-base");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
63
8
|
async function HeadlessPDFSave(step, context) {
|
|
64
|
-
var {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
var { pdf, coverPage, lastPage, watermark, fileName } = __headless_pdf;
|
|
68
|
-
const totalPages = pdf.getPages().length;
|
|
69
|
-
await HeadlessPDFRenderHeadersAndFooters(pdf, __headless_pdf.header, __headless_pdf.footer, watermark, totalPages);
|
|
70
|
-
const finalFileName = fileName || `document-${Date.now()}.pdf`;
|
|
71
|
-
const savePath = path.join(outputPath || './attachments', finalFileName);
|
|
72
|
-
if (coverPage) {
|
|
73
|
-
const coverPageDoc = await pdf_lib_1.PDFDocument.load(coverPage);
|
|
74
|
-
const [cover] = await pdf.copyPages(coverPageDoc, [0]);
|
|
75
|
-
if (watermark) {
|
|
76
|
-
const fontSize = 50;
|
|
77
|
-
const pageWidth = cover.getWidth();
|
|
78
|
-
const pageHeight = cover.getHeight();
|
|
79
|
-
cover.drawText(watermark, {
|
|
80
|
-
x: pageWidth / 2 - (fontSize * watermark.length) / 4,
|
|
81
|
-
y: pageHeight / 2 - fontSize / 2,
|
|
82
|
-
size: fontSize,
|
|
83
|
-
color: (0, pdf_lib_1.rgb)(0.75, 0.75, 0.75),
|
|
84
|
-
rotate: (0, pdf_lib_1.degrees)(-45),
|
|
85
|
-
opacity: 0.5
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
pdf.insertPage(0, cover);
|
|
9
|
+
var { domain, user, __headless_pdf } = context;
|
|
10
|
+
if (!__headless_pdf || !__headless_pdf.pdfDoc) {
|
|
11
|
+
throw new Error('No PDF document found. Ensure that headless-pdf-open and headless-pdf-capture tasks are executed before saving.');
|
|
89
12
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const pageHeight = last.getHeight();
|
|
97
|
-
last.drawText(watermark, {
|
|
98
|
-
x: pageWidth / 2 - (fontSize * watermark.length) / 4,
|
|
99
|
-
y: pageHeight / 2 - fontSize / 2,
|
|
100
|
-
size: fontSize,
|
|
101
|
-
color: (0, pdf_lib_1.rgb)(0.75, 0.75, 0.75),
|
|
102
|
-
rotate: (0, pdf_lib_1.degrees)(-45),
|
|
103
|
-
opacity: 0.5
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
pdf.addPage(last);
|
|
13
|
+
const pdfDoc = __headless_pdf.pdfDoc;
|
|
14
|
+
// Add last page if it exists
|
|
15
|
+
if (__headless_pdf.lastPageBuffer) {
|
|
16
|
+
const lastPageDoc = await pdf_lib_1.PDFDocument.load(__headless_pdf.lastPageBuffer);
|
|
17
|
+
const copiedLastPages = await pdfDoc.copyPages(lastPageDoc, lastPageDoc.getPageIndices());
|
|
18
|
+
copiedLastPages.forEach(page => pdfDoc.addPage(page));
|
|
107
19
|
}
|
|
108
|
-
const pdfBytes = await
|
|
109
|
-
|
|
20
|
+
const pdfBytes = await pdfDoc.save();
|
|
21
|
+
const finalFileName = __headless_pdf.fileName || `document-${Date.now()}.pdf`;
|
|
22
|
+
const saved = await (0, attachment_base_1.createAttachment)(null, {
|
|
23
|
+
attachment: {
|
|
24
|
+
file: {
|
|
25
|
+
createReadStream: () => new Readable({
|
|
26
|
+
read() {
|
|
27
|
+
this.push(pdfBytes);
|
|
28
|
+
this.push(null);
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
filename: finalFileName,
|
|
32
|
+
mimetype: 'application/pdf',
|
|
33
|
+
encoding: 'binary'
|
|
34
|
+
},
|
|
35
|
+
refType: 'headless-pdf-save',
|
|
36
|
+
refBy: 'pdf-published'
|
|
37
|
+
}
|
|
38
|
+
}, {
|
|
39
|
+
state: { domain, user }
|
|
40
|
+
});
|
|
41
|
+
const attachment = await (0, shell_1.getRepository)(attachment_base_1.Attachment).findOne({
|
|
42
|
+
where: { id: saved.id }
|
|
43
|
+
});
|
|
110
44
|
return {
|
|
111
45
|
data: {
|
|
112
|
-
|
|
46
|
+
id: attachment.id,
|
|
47
|
+
name: attachment.name,
|
|
48
|
+
path: attachment.path,
|
|
49
|
+
mimetype: attachment.mimetype,
|
|
50
|
+
refBy: attachment.refBy,
|
|
51
|
+
fullpath: attachment.fullpath
|
|
113
52
|
}
|
|
114
53
|
};
|
|
115
54
|
}
|
|
116
|
-
HeadlessPDFSave.parameterSpec = [
|
|
117
|
-
{
|
|
118
|
-
type: 'string',
|
|
119
|
-
name: 'outputPath',
|
|
120
|
-
label: 'output-path'
|
|
121
|
-
}
|
|
122
|
-
];
|
|
55
|
+
HeadlessPDFSave.parameterSpec = [];
|
|
123
56
|
HeadlessPDFSave.help = 'integration/task/headless-pdf-save';
|
|
124
57
|
integration_base_1.TaskRegistry.registerTaskHandler('headless-pdf-save', HeadlessPDFSave);
|
|
125
58
|
//# sourceMappingURL=headless-pdf-save.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless-pdf-save.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-save.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"headless-pdf-save.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-save.ts"],"names":[],"mappings":";;AAAA,qCAAqC;AACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEtC,uEAA+D;AAC/D,qEAA8E;AAC9E,iDAAqD;AAErD,KAAK,UAAU,eAAe,CAAC,IAAI,EAAE,OAAO;IAC1C,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAA;IAE9C,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,iHAAiH,CAClH,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAA;IAEpC,6BAA6B;IAC7B,IAAI,cAAc,CAAC,cAAc,EAAE,CAAC;QAClC,MAAM,WAAW,GAAG,MAAM,qBAAW,CAAC,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,CAAA;QACzE,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC,cAAc,EAAE,CAAC,CAAA;QACzF,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IACvD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;IAEpC,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,IAAI,YAAY,IAAI,CAAC,GAAG,EAAE,MAAM,CAAA;IAE7E,MAAM,KAAK,GAAG,MAAM,IAAA,kCAAgB,EAClC,IAAI,EACJ;QACE,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,gBAAgB,EAAE,GAAG,EAAE,CACrB,IAAI,QAAQ,CAAC;oBACX,IAAI;wBACF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;wBACnB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;oBACjB,CAAC;iBACF,CAAC;gBACJ,QAAQ,EAAE,aAAa;gBACvB,QAAQ,EAAE,iBAAiB;gBAC3B,QAAQ,EAAE,QAAQ;aACnB;YACD,OAAO,EAAE,mBAAmB;YAC5B,KAAK,EAAE,eAAe;SACvB;KACF,EACD;QACE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;KACxB,CACF,CAAA;IAED,MAAM,UAAU,GAAG,MAAM,IAAA,qBAAa,EAAC,4BAAU,CAAC,CAAC,OAAO,CAAC;QACzD,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE;KACxB,CAAC,CAAA;IAEF,OAAO;QACL,IAAI,EAAE;YACJ,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,QAAQ,EAAE,UAAU,CAAC,QAAQ;SAC9B;KACF,CAAA;AACH,CAAC;AAED,eAAe,CAAC,aAAa,GAAG,EAAE,CAAA;AAElC,eAAe,CAAC,IAAI,GAAG,oCAAoC,CAAA;AAE3D,+BAAY,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA","sourcesContent":["import { PDFDocument } from 'pdf-lib'\nconst { Readable } = require('stream')\n\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { Attachment, createAttachment } from '@things-factory/attachment-base'\nimport { getRepository } from '@things-factory/shell'\n\nasync function HeadlessPDFSave(step, context) {\n var { domain, user, __headless_pdf } = context\n\n if (!__headless_pdf || !__headless_pdf.pdfDoc) {\n throw new Error(\n 'No PDF document found. Ensure that headless-pdf-open and headless-pdf-capture tasks are executed before saving.'\n )\n }\n\n const pdfDoc = __headless_pdf.pdfDoc\n\n // Add last page if it exists\n if (__headless_pdf.lastPageBuffer) {\n const lastPageDoc = await PDFDocument.load(__headless_pdf.lastPageBuffer)\n const copiedLastPages = await pdfDoc.copyPages(lastPageDoc, lastPageDoc.getPageIndices())\n copiedLastPages.forEach(page => pdfDoc.addPage(page))\n }\n\n const pdfBytes = await pdfDoc.save()\n\n const finalFileName = __headless_pdf.fileName || `document-${Date.now()}.pdf`\n\n const saved = await createAttachment(\n null,\n {\n attachment: {\n file: {\n createReadStream: () =>\n new Readable({\n read() {\n this.push(pdfBytes)\n this.push(null)\n }\n }),\n filename: finalFileName,\n mimetype: 'application/pdf',\n encoding: 'binary'\n },\n refType: 'headless-pdf-save',\n refBy: 'pdf-published'\n }\n },\n {\n state: { domain, user }\n }\n )\n\n const attachment = await getRepository(Attachment).findOne({\n where: { id: saved.id }\n })\n\n return {\n data: {\n id: attachment.id,\n name: attachment.name,\n path: attachment.path,\n mimetype: attachment.mimetype,\n refBy: attachment.refBy,\n fullpath: attachment.fullpath\n }\n }\n}\n\nHeadlessPDFSave.parameterSpec = []\n\nHeadlessPDFSave.help = 'integration/task/headless-pdf-save'\n\nTaskRegistry.registerTaskHandler('headless-pdf-save', HeadlessPDFSave)\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/task/index.ts"],"names":[],"mappings":";;AAAA,kCAA+B;AAC/B,+BAA4B;AAC5B,+BAA4B","sourcesContent":["import './headless-pdf-capture'\nimport './headless-pdf-open'\nimport './headless-pdf-save'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/task/index.ts"],"names":[],"mappings":";;AAAA,kCAA+B;AAC/B,wCAAqC;AACrC,+BAA4B;AAC5B,+BAA4B","sourcesContent":["import './headless-pdf-capture'\nimport './headless-pdf-capture-board'\nimport './headless-pdf-open'\nimport './headless-pdf-save'\n"]}
|