@things-factory/integration-headless 7.0.38 → 7.0.40

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.
@@ -1 +1 @@
1
- {"version":3,"file":"headless-pdf-capture.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-capture.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ejs from 'ejs'\nimport { PDFDocument, rgb, degrees } from 'pdf-lib'\n\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { ConnectionManager } from '@things-factory/integration-base'\n\nasync function HeadlessPDFCapture(step, context) {\n var { connection: connectionName, params: stepOptions } = step\n var {\n htmlContent,\n format,\n width,\n height,\n margin,\n scale,\n printBackground,\n landscape,\n displayHeaderFooter,\n headerTemplate,\n footerTemplate,\n preferCSSPageSize\n } = stepOptions || {}\n var { domain, data, __headless_pdf } = context\n\n if (!__headless_pdf) {\n throw new Error('it requires headless-pdf-open to be performed first')\n }\n\n var {\n pdf,\n header: headerTemplateFromContext,\n footer: footerTemplateFromContext,\n watermark,\n pageCount\n } = __headless_pdf\n\n var headlessPool = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n let browser\n\n try {\n // Puppeteer를 사용하여 브라우저와 페이지 인스턴스를 생성\n browser = await headlessPool.acquire()\n const page = await browser.newPage()\n\n // 설정된 HTML 콘텐츠를 페이지에 설정\n await page.setContent(htmlContent)\n\n // PDF 페이지 생성 옵션 설정\n if (preferCSSPageSize) {\n width = undefined\n height = undefined\n }\n\n const pageOptions = {\n format,\n width,\n height,\n margin,\n scale,\n printBackground,\n landscape,\n displayHeaderFooter,\n headerTemplate: displayHeaderFooter ? headerTemplate : undefined,\n footerTemplate: displayHeaderFooter ? footerTemplate : undefined,\n preferCSSPageSize\n }\n\n // 페이지를 PDF로 변환\n const pageBuffer = await page.pdf(pageOptions)\n\n // PDF-lib을 사용하여 PDF를 로드하고 추가 조작\n const pdfDoc = await PDFDocument.load(pageBuffer)\n const pages = await pdf.copyPages(pdfDoc, pdfDoc.getPageIndices())\n\n pages.forEach((newPage, index) => {\n const currentPageNumber = pageCount + index + 1\n\n // 헤더와 푸터 렌더링 (페이지 번호 및 총 페이지 수 포함)\n if (displayHeaderFooter && (headerTemplateFromContext || footerTemplateFromContext)) {\n const renderedHeader = headerTemplateFromContext\n ? ejs.render(headerTemplateFromContext, {\n ...data,\n pageNumber: currentPageNumber,\n totalPages: pageCount + pages.length\n })\n : ''\n const renderedFooter = footerTemplateFromContext\n ? ejs.render(footerTemplateFromContext, {\n ...data,\n pageNumber: currentPageNumber,\n totalPages: pageCount + pages.length\n })\n : ''\n\n // Header/Footer 그리기\n if (renderedHeader) {\n newPage.drawText(renderedHeader, { x: 50, y: newPage.getHeight() - 30, size: 12, color: rgb(0, 0, 0) })\n }\n if (renderedFooter) {\n newPage.drawText(renderedFooter, { x: 50, y: 30, size: 12, color: rgb(0, 0, 0) })\n }\n }\n\n // 워터마크 추가\n if (watermark) {\n const fontSize = 50\n const pageWidth = newPage.getWidth()\n const pageHeight = newPage.getHeight()\n\n newPage.drawText(watermark, {\n x: pageWidth / 2 - (fontSize * watermark.length) / 4,\n y: pageHeight / 2 - fontSize / 2,\n size: fontSize,\n color: rgb(0.75, 0.75, 0.75),\n rotate: degrees(-45),\n opacity: 0.5\n })\n }\n\n pdf.addPage(newPage)\n })\n\n // 페이지 카운트 업데이트\n __headless_pdf.pageCount += pages.length\n\n await page.close()\n headlessPool.release(browser)\n\n return {\n data: __headless_pdf\n }\n } catch (error) {\n if (browser) {\n await browser.close()\n }\n\n throw error\n }\n}\n\nHeadlessPDFCapture.parameterSpec = [\n {\n type: 'textarea',\n name: 'htmlContent',\n label: 'html-content'\n },\n {\n type: 'select',\n name: 'format',\n label: 'page-format',\n property: {\n options: [\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: 'json',\n name: 'margin',\n label: 'page-margins',\n fields: [\n { type: 'string', name: 'top', label: 'Top Margin', description: 'Top margin (e.g., \"1in\")' },\n { type: 'string', name: 'right', label: 'Right Margin', description: 'Right margin (e.g., \"1in\")' },\n { type: 'string', name: 'bottom', label: 'Bottom Margin', description: 'Bottom margin (e.g., \"1in\")' },\n { type: 'string', name: 'left', label: 'Left Margin', description: 'Left margin (e.g., \"1in\")' }\n ],\n description: 'Set the margins for the page'\n },\n {\n type: 'number',\n name: 'scale',\n label: '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: 'displayHeaderFooter',\n label: 'display-header/footer',\n defaultValue: false,\n description: 'Display header and footer in the PDF'\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\nHeadlessPDFCapture.help = 'integration/task/headless-pdf-capture'\n\nTaskRegistry.registerTaskHandler('headless-pdf-capture', HeadlessPDFCapture)\n"]}
1
+ {"version":3,"file":"headless-pdf-capture.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-capture.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ejs from 'ejs'\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { ConnectionManager } from '@things-factory/integration-base'\nimport { access } from '@things-factory/utils'\nimport { PDFDocument } from 'pdf-lib'\n\nasync function HeadlessPDFCapture(step, context) {\n var { connection: connectionName, params: stepOptions } = step\n var {\n accessor,\n htmlContent,\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 var { domain, data, logger, __headless_pdf } = context\n\n if (!__headless_pdf) {\n throw new Error('It requires headless-pdf-open to be performed first')\n }\n\n var { pdfDoc, header, footer, watermark } = __headless_pdf\n\n var headlessPool = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n let browser\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 const renderedHtmlContent = renderTemplateSafely(htmlContent, templateInput)\n await page.setContent(renderedHtmlContent)\n\n header = renderTemplateSafely(header, __headless_pdf)\n footer = renderTemplateSafely(footer, __headless_pdf)\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 element.style.margin = '0'\n element.style.padding = '0'\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 if (preferCSSPageSize) {\n width = undefined\n height = undefined\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 contentBuffer = await page.pdf(pageOptions)\n const contentPdfDoc = await PDFDocument.load(contentBuffer)\n const copiedPages = await pdfDoc.copyPages(contentPdfDoc, contentPdfDoc.getPageIndices())\n\n copiedPages.forEach(page => pdfDoc.addPage(page))\n\n __headless_pdf.pageCount += copiedPages.length\n\n await page.close()\n headlessPool.release(browser)\n\n return {\n data: __headless_pdf\n }\n } catch (error) {\n if (browser) {\n await browser.close()\n }\n\n throw error\n }\n}\n\nHeadlessPDFCapture.parameterSpec = [\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n },\n {\n type: 'textarea',\n name: 'htmlContent',\n label: 'html-content'\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\nHeadlessPDFCapture.help = 'integration/task/headless-pdf-capture'\n\nTaskRegistry.registerTaskHandler('headless-pdf-capture', HeadlessPDFCapture)\n"]}
@@ -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
- } = stepOptions || {};
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
- // Cover Page를 PDF로 변환
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
- await page.setContent(coverPage);
19
- const coverPageBuffer = await page.pdf();
20
- coverPage = coverPageBuffer;
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
- // Last Page를 PDF로 변환
100
+ var lastPageBuffer;
101
+ // Process Last Page (if provided) but add it later in the save task
23
102
  if (lastPage) {
24
- await page.setContent(lastPage);
25
- const lastPageBuffer = await page.pdf();
26
- lastPage = lastPageBuffer;
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 data = {
38
- pdf,
39
- coverPage,
40
- lastPage,
176
+ const pdfInfo = {
177
+ pdfDoc,
178
+ lastPageBuffer,
41
179
  header,
42
180
  footer,
43
181
  watermark,
44
182
  fileName,
45
- pageCount: 0
183
+ pageCount: pdfDoc.getPageCount()
46
184
  };
47
- context.__headless_pdf = data;
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',
@@ -61,24 +204,111 @@ HeadlessPDFOpen.parameterSpec = [
61
204
  label: 'pdf-last-page'
62
205
  },
63
206
  {
64
- type: 'textarea',
207
+ type: 'string',
65
208
  name: 'header',
66
- label: 'header' // header template
209
+ label: 'header',
210
+ placeholder: 'Page <%= pageNumber %> of <%= totalPages %>'
67
211
  },
68
212
  {
69
- type: 'textarea',
213
+ type: 'string',
70
214
  name: 'footer',
71
- label: 'footer' // footer template
215
+ label: 'footer',
216
+ placeholder: 'Page <%= pageNumber %> of <%= totalPages %>'
72
217
  },
73
218
  {
74
- type: 'textarea',
219
+ type: 'string',
75
220
  name: 'watermark',
76
- label: 'watermark' // watermark
221
+ label: 'watermark'
77
222
  },
78
223
  {
79
224
  type: 'string',
80
225
  name: 'fileName',
81
- label: 'filename' // 파일 이름 지정
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'
82
312
  }
83
313
  ];
84
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,UAAU;QAChB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ,CAAC,kBAAkB;KACnC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ,CAAC,kBAAkB;KACnC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,WAAW,CAAC,YAAY;KAChC;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU,CAAC,WAAW;KAC9B;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: 'textarea',\n name: 'header',\n label: 'header' // header template\n },\n {\n type: 'textarea',\n name: 'footer',\n label: 'footer' // footer template\n },\n {\n type: 'textarea',\n name: 'watermark',\n label: 'watermark' // 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"]}
@@ -3,61 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const fs = tslib_1.__importStar(require("fs"));
5
5
  const path = tslib_1.__importStar(require("path"));
6
- const pdf_lib_1 = require("pdf-lib");
7
6
  const integration_base_1 = require("@things-factory/integration-base");
7
+ const pdf_lib_1 = require("pdf-lib");
8
8
  async function HeadlessPDFSave(step, context) {
9
9
  var { params: stepOptions } = step;
10
10
  var { outputPath } = stepOptions || {};
11
- var { domain, data, __headless_pdf } = context;
12
- var { pdf, coverPage, lastPage, watermark, fileName } = __headless_pdf;
13
- // 파일 이름이 설정되지 않았을 경우 기본 파일 이름 생성
14
- const finalFileName = fileName || `document-${Date.now()}.pdf`;
15
- const savePath = path.join(outputPath || '/path/to/default/storage', finalFileName);
16
- // PDF 문서에 coverPage 및 lastPage 추가
17
- if (coverPage) {
18
- const coverPageDoc = await pdf_lib_1.PDFDocument.load(coverPage);
19
- const [cover] = await pdf.copyPages(coverPageDoc, [0]);
20
- // 커버 페이지에 워터마크 추가
21
- if (watermark) {
22
- const fontSize = 50;
23
- const pageWidth = cover.getWidth();
24
- const pageHeight = cover.getHeight();
25
- cover.drawText(watermark, {
26
- x: pageWidth / 2 - (fontSize * watermark.length) / 4,
27
- y: pageHeight / 2 - fontSize / 2,
28
- size: fontSize,
29
- color: (0, pdf_lib_1.rgb)(0.75, 0.75, 0.75),
30
- rotate: (0, pdf_lib_1.degrees)(-45),
31
- opacity: 0.5
32
- });
33
- }
34
- pdf.insertPage(0, cover);
11
+ var { __headless_pdf } = context;
12
+ if (!__headless_pdf || !__headless_pdf.pdfDoc) {
13
+ throw new Error('No PDF document found. Ensure that headless-pdf-open and headless-pdf-capture tasks are executed before saving.');
35
14
  }
36
- if (lastPage) {
37
- const lastPageDoc = await pdf_lib_1.PDFDocument.load(lastPage);
38
- const [last] = await pdf.copyPages(lastPageDoc, [0]);
39
- // 마지막 페이지에 워터마크 추가
40
- if (watermark) {
41
- const fontSize = 50;
42
- const pageWidth = last.getWidth();
43
- const pageHeight = last.getHeight();
44
- last.drawText(watermark, {
45
- x: pageWidth / 2 - (fontSize * watermark.length) / 4,
46
- y: pageHeight / 2 - fontSize / 2,
47
- size: fontSize,
48
- color: (0, pdf_lib_1.rgb)(0.75, 0.75, 0.75),
49
- rotate: (0, pdf_lib_1.degrees)(-45),
50
- opacity: 0.5
51
- });
52
- }
53
- pdf.addPage(last);
15
+ const pdfDoc = __headless_pdf.pdfDoc;
16
+ // Add last page if it exists
17
+ if (__headless_pdf.lastPageBuffer) {
18
+ const lastPageDoc = await pdf_lib_1.PDFDocument.load(__headless_pdf.lastPageBuffer);
19
+ const copiedLastPages = await pdfDoc.copyPages(lastPageDoc, lastPageDoc.getPageIndices());
20
+ copiedLastPages.forEach(page => pdfDoc.addPage(page));
54
21
  }
55
- // PDF 파일로 저장
56
- const pdfBytes = await pdf.save();
22
+ const pdfBytes = await pdfDoc.save();
23
+ const finalFileName = __headless_pdf.fileName || `document-${Date.now()}.pdf`;
24
+ const savePath = path.join(outputPath || './attachments', finalFileName);
25
+ // Save the final PDF to the specified path
57
26
  fs.writeFileSync(savePath, pdfBytes);
58
27
  return {
59
28
  data: {
60
- link: savePath // 저장된 PDF 파일의 경로를 반환
29
+ link: savePath
61
30
  }
62
31
  };
63
32
  }
@@ -65,7 +34,8 @@ HeadlessPDFSave.parameterSpec = [
65
34
  {
66
35
  type: 'string',
67
36
  name: 'outputPath',
68
- label: 'output-path' // PDF를 저장할 경로
37
+ label: 'output-path',
38
+ description: 'The directory path where the PDF should be saved. Defaults to "./attachments".'
69
39
  }
70
40
  ];
71
41
  HeadlessPDFSave.help = 'integration/task/headless-pdf-save';
@@ -1 +1 @@
1
- {"version":3,"file":"headless-pdf-save.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-save.ts"],"names":[],"mappings":";;;AAAA,+CAAwB;AACxB,mDAA4B;AAC5B,qCAAmD;AAEnD,uEAA+D;AAE/D,KAAK,UAAU,eAAe,CAAC,IAAI,EAAE,OAAO;IAC1C,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAClC,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IACtC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAA;IAE9C,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAA;IAEtE,iCAAiC;IACjC,MAAM,aAAa,GAAG,QAAQ,IAAI,YAAY,IAAI,CAAC,GAAG,EAAE,MAAM,CAAA;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,0BAA0B,EAAE,aAAa,CAAC,CAAA;IAEnF,kCAAkC;IAClC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,YAAY,GAAG,MAAM,qBAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACtD,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAEtD,kBAAkB;QAClB,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,EAAE,CAAA;YACnB,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAA;YAClC,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;YAEpC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE;gBACxB,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;gBACpD,CAAC,EAAE,UAAU,GAAG,CAAC,GAAG,QAAQ,GAAG,CAAC;gBAChC,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,IAAA,aAAG,EAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;gBAC5B,MAAM,EAAE,IAAA,iBAAO,EAAC,CAAC,EAAE,CAAC;gBACpB,OAAO,EAAE,GAAG;aACb,CAAC,CAAA;QACJ,CAAC;QAED,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IAC1B,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,WAAW,GAAG,MAAM,qBAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpD,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAEpD,mBAAmB;QACnB,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,EAAE,CAAA;YACnB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;YACjC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;YAEnC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;gBACvB,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;gBACpD,CAAC,EAAE,UAAU,GAAG,CAAC,GAAG,QAAQ,GAAG,CAAC;gBAChC,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,IAAA,aAAG,EAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;gBAC5B,MAAM,EAAE,IAAA,iBAAO,EAAC,CAAC,EAAE,CAAC;gBACpB,OAAO,EAAE,GAAG;aACb,CAAC,CAAA;QACJ,CAAC;QAED,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC;IAED,aAAa;IACb,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;IACjC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAEpC,OAAO;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ,CAAC,qBAAqB;SACrC;KACF,CAAA;AACH,CAAC;AAED,eAAe,CAAC,aAAa,GAAG;IAC9B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,aAAa,CAAC,cAAc;KACpC;CACF,CAAA;AAED,eAAe,CAAC,IAAI,GAAG,oCAAoC,CAAA;AAE3D,+BAAY,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA","sourcesContent":["import * as fs from 'fs'\nimport * as path from 'path'\nimport { PDFDocument, rgb, degrees } from 'pdf-lib'\n\nimport { TaskRegistry } from '@things-factory/integration-base'\n\nasync function HeadlessPDFSave(step, context) {\n var { params: stepOptions } = step\n var { outputPath } = stepOptions || {}\n var { domain, data, __headless_pdf } = context\n\n var { pdf, coverPage, lastPage, watermark, fileName } = __headless_pdf\n\n // 파일 이름이 설정되지 않았을 경우 기본 파일 이름 생성\n const finalFileName = fileName || `document-${Date.now()}.pdf`\n const savePath = path.join(outputPath || '/path/to/default/storage', finalFileName)\n\n // PDF 문서에 coverPage lastPage 추가\n if (coverPage) {\n const coverPageDoc = await PDFDocument.load(coverPage)\n const [cover] = await pdf.copyPages(coverPageDoc, [0])\n\n // 커버 페이지에 워터마크 추가\n if (watermark) {\n const fontSize = 50\n const pageWidth = cover.getWidth()\n const pageHeight = cover.getHeight()\n\n cover.drawText(watermark, {\n x: pageWidth / 2 - (fontSize * watermark.length) / 4,\n y: pageHeight / 2 - fontSize / 2,\n size: fontSize,\n color: rgb(0.75, 0.75, 0.75),\n rotate: degrees(-45),\n opacity: 0.5\n })\n }\n\n pdf.insertPage(0, cover)\n }\n\n if (lastPage) {\n const lastPageDoc = await PDFDocument.load(lastPage)\n const [last] = await pdf.copyPages(lastPageDoc, [0])\n\n // 마지막 페이지에 워터마크 추가\n if (watermark) {\n const fontSize = 50\n const pageWidth = last.getWidth()\n const pageHeight = last.getHeight()\n\n last.drawText(watermark, {\n x: pageWidth / 2 - (fontSize * watermark.length) / 4,\n y: pageHeight / 2 - fontSize / 2,\n size: fontSize,\n color: rgb(0.75, 0.75, 0.75),\n rotate: degrees(-45),\n opacity: 0.5\n })\n }\n\n pdf.addPage(last)\n }\n\n // PDF 파일로 저장\n const pdfBytes = await pdf.save()\n fs.writeFileSync(savePath, pdfBytes)\n\n return {\n data: {\n link: savePath // 저장된 PDF 파일의 경로를 반환\n }\n }\n}\n\nHeadlessPDFSave.parameterSpec = [\n {\n type: 'string',\n name: 'outputPath',\n label: 'output-path' // PDF 저장할 경로\n }\n]\n\nHeadlessPDFSave.help = 'integration/task/headless-pdf-save'\n\nTaskRegistry.registerTaskHandler('headless-pdf-save', HeadlessPDFSave)\n"]}
1
+ {"version":3,"file":"headless-pdf-save.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-save.ts"],"names":[],"mappings":";;;AAAA,+CAAwB;AACxB,mDAA4B;AAC5B,uEAA+D;AAC/D,qCAAqC;AAErC,KAAK,UAAU,eAAe,CAAC,IAAI,EAAE,OAAO;IAC1C,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAClC,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IACtC,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAA;IAEhC,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;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,eAAe,EAAE,aAAa,CAAC,CAAA;IAExE,2CAA2C;IAC3C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAEpC,OAAO;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;SACf;KACF,CAAA;AACH,CAAC;AAED,eAAe,CAAC,aAAa,GAAG;IAC9B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,aAAa;QACpB,WAAW,EAAE,gFAAgF;KAC9F;CACF,CAAA;AAED,eAAe,CAAC,IAAI,GAAG,oCAAoC,CAAA;AAE3D,+BAAY,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA","sourcesContent":["import * as fs from 'fs'\nimport * as path from 'path'\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { PDFDocument } from 'pdf-lib'\n\nasync function HeadlessPDFSave(step, context) {\n var { params: stepOptions } = step\n var { outputPath } = stepOptions || {}\n var { __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 const savePath = path.join(outputPath || './attachments', finalFileName)\n\n // Save the final PDF to the specified path\n fs.writeFileSync(savePath, pdfBytes)\n\n return {\n data: {\n link: savePath\n }\n }\n}\n\nHeadlessPDFSave.parameterSpec = [\n {\n type: 'string',\n name: 'outputPath',\n label: 'output-path',\n description: 'The directory path where the PDF should be saved. Defaults to \"./attachments\".'\n }\n]\n\nHeadlessPDFSave.help = 'integration/task/headless-pdf-save'\n\nTaskRegistry.registerTaskHandler('headless-pdf-save', HeadlessPDFSave)\n"]}
@@ -1,3 +1,4 @@
1
1
  import './headless-pdf-capture';
2
+ import './headless-pdf-capture-board';
2
3
  import './headless-pdf-open';
3
4
  import './headless-pdf-save';
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  require("./headless-pdf-capture");
4
+ require("./headless-pdf-capture-board");
4
5
  require("./headless-pdf-open");
5
6
  require("./headless-pdf-save");
6
7
  //# sourceMappingURL=index.js.map
@@ -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"]}