@things-factory/integration-headless 7.0.53 → 7.0.55

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.
@@ -55,7 +55,7 @@ async function HeadlessPDFCaptureBoard(step, context) {
55
55
  const pageOptions = pdfUtil.buildPageOptions(Object.assign(Object.assign({}, step.params), { width: width ? `${width}px` : undefined, height: height ? `${height}px` : undefined }));
56
56
  // PDF 생성 및 추가
57
57
  const htmlContent = ''; // 보드에서 직접 렌더링되므로 HTML 컨텐츠가 비어있음
58
- await pdfUtil.processPageAndGeneratePDF(Object.assign(Object.assign({}, step.params), { width, height }), htmlContent);
58
+ await pdfUtil.processPageAndGeneratePDF(pageOptions, htmlContent); // pageOptions 사용
59
59
  return {
60
60
  data: context.__headless_pdf
61
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"headless-pdf-capture-board.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-capture-board.ts"],"names":[],"mappings":";;AAcA,0DA0EC;AAxFD,uEAA+D;AAE/D,yDAA2E;AAC3E,iEAAyD;AAEzD,MAAM,YAAY,GAAG;IACnB,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACrC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IACtC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACnC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;CACpC,CAAA;AAIM,KAAK,UAAU,uBAAuB,CAAC,IAAI,EAAE,OAAO;;IACzD,MAAM,OAAO,GAAG,IAAI,iCAAc,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAE1C,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAEjF,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACnD,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,yBAAS,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;QACtG,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,yBAAS,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAEtE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAA;QACxB,KAAK,CAAC,UAAU,GAAG,UAAU,CAAA;QAE7B,IAAI,KAAK,GAAuB,MAAA,YAAY,CAAC,MAAoB,CAAC,0CAAE,KAAK,CAAA;QACzE,IAAI,MAAM,GAAuB,MAAA,YAAY,CAAC,MAAoB,CAAC,0CAAE,MAAM,CAAA;QAE3E,IAAI,iBAAiB,EAAE,CAAC;YACtB,KAAK,GAAG,SAAS,CAAA;YACjB,MAAM,GAAG,SAAS,CAAA;QACpB,CAAC;QAED,IAAI,SAAS,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,CAAC;YAAA,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACpC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,CAAA;QACvB,MAAM,IAAI,GAAG,WAAW,CAAA;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3D,MAAM,IAAI,GAAG,8BAA8B,CAAA;QAC3C,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAA;QAEjD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAQ,CAAC,OAAO,EAAE,CAAA;QAE7C,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,oCAAoC;YACrE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,qCAAqC;SACxE,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAEpB,MAAM,IAAI,CAAC,QAAQ,CACjB,IAAI,CAAC,EAAE;YACL,YAAY;YACZ,CAAC,CAAC,IAAI,GAAG,IAAI,CAAA;YACb,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,qBAAqB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;YACzC,CAAC,CAAC,CAAA;QACJ,CAAC,EACD,EAAE,KAAK,EAAE,IAAI,EAAE,CAChB,CAAA;QAED,YAAY;QACZ,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,iCACvC,IAAI,CAAC,MAAM,KACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,EACvC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,IAC1C,CAAA;QAEF,cAAc;QACd,MAAM,WAAW,GAAG,EAAE,CAAA,CAAC,gCAAgC;QACvD,MAAM,OAAO,CAAC,yBAAyB,iCAAM,IAAI,CAAC,MAAM,KAAE,KAAK,EAAE,MAAM,KAAI,WAAW,CAAC,CAAA;QAEvF,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,cAAc;SAC7B,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,uBAAuB,CAAC,aAAa,GAAG;IACtC,GAAG,IAAA,yCAAsB,GAAE;IAC3B;QACE,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,SAAS,EAAE,QAAQ;SACpB;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,aAAa;QACpB,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,6EAA6E;KAC3F;CACF,CAAA;AAED,uBAAuB,CAAC,IAAI,GAAG,6CAA6C,CAAA;AAE5E,+BAAY,CAAC,mBAAmB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '@things-factory/integration-base'\n\nimport { PDFCaptureUtil, getCommonParameterSpec } from './pdf-capture-util'\nimport { BoardFunc } from '@things-factory/board-service'\n\nconst PAGE_FORMATS = {\n A4: { width: 595.28, height: 841.89 },\n A3: { width: 841.89, height: 1190.55 },\n Letter: { width: 612, height: 792 },\n Legal: { width: 612, height: 1008 }\n}\n\ntype PageFormat = keyof typeof PAGE_FORMATS\n\nexport async function HeadlessPDFCaptureBoard(step, context) {\n const pdfUtil = new PDFCaptureUtil(context)\n await pdfUtil.initBrowser(step.connection)\n\n try {\n const { board, draft, format = 'A4', landscape, preferCSSPageSize } = step.params\n\n if (!board || !board.id) {\n throw new Error('The board property must be set')\n }\n\n const { model, base } = await BoardFunc.headlessModel({ domain: context.domain, id: board.id }, draft)\n const [fontsToUse, fontStyles] = await BoardFunc.fonts(context.domain)\n\n model.fonts = fontsToUse\n model.fontStyles = fontStyles\n\n let width: number | undefined = PAGE_FORMATS[format as PageFormat]?.width\n let height: number | undefined = PAGE_FORMATS[format as PageFormat]?.height\n\n if (preferCSSPageSize) {\n width = undefined\n height = undefined\n }\n\n if (landscape && width && height) {\n ;[width, height] = [height, width]\n }\n\n const protocol = 'http'\n const host = 'localhost'\n const port = process.env.PORT ? `:${process.env.PORT}` : ''\n const path = '/internal-board-service-view'\n const url = `${protocol}://${host}${port}${path}`\n\n const page = await pdfUtil.browser!.newPage()\n\n await page.setViewport({\n width: Math.round(width || 800), // Fallback for width if not defined\n height: Math.round(height || 600) // Fallback for height if not defined\n })\n\n await page.goto(url)\n\n await page.evaluate(\n data => {\n //@ts-ignore\n s.data = data\n return new Promise(resolve => {\n requestAnimationFrame(() => resolve(0))\n })\n },\n { model, base }\n )\n\n // 페이지 옵션 설정\n const pageOptions = pdfUtil.buildPageOptions({\n ...step.params,\n width: width ? `${width}px` : undefined,\n height: height ? `${height}px` : undefined\n })\n\n // PDF 생성 및 추가\n const htmlContent = '' // 보드에서 직접 렌더링되므로 HTML 컨텐츠가 비어있음\n await pdfUtil.processPageAndGeneratePDF({ ...step.params, width, height }, htmlContent)\n\n return {\n data: context.__headless_pdf\n }\n } catch (error) {\n throw error\n } finally {\n await pdfUtil.closeBrowser()\n }\n}\n\nHeadlessPDFCaptureBoard.parameterSpec = [\n ...getCommonParameterSpec(),\n {\n type: 'resource-object',\n name: 'board',\n label: 'board',\n property: {\n queryName: 'boards'\n }\n },\n {\n type: 'boolean',\n name: 'draft',\n label: 'board-draft',\n defaultValue: false,\n description: 'Set whether to get the current working version or the last released version'\n }\n]\n\nHeadlessPDFCaptureBoard.help = 'integration/task/headless-pdf-capture-board'\n\nTaskRegistry.registerTaskHandler('headless-pdf-capture-board', HeadlessPDFCaptureBoard)\n"]}
1
+ {"version":3,"file":"headless-pdf-capture-board.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-capture-board.ts"],"names":[],"mappings":";;AAaA,0DA0EC;AAvFD,uEAA+D;AAC/D,yDAA2E;AAC3E,iEAAyD;AAEzD,MAAM,YAAY,GAAG;IACnB,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACrC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IACtC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACnC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;CACpC,CAAA;AAIM,KAAK,UAAU,uBAAuB,CAAC,IAAI,EAAE,OAAO;;IACzD,MAAM,OAAO,GAAG,IAAI,iCAAc,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAE1C,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAEjF,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACnD,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,yBAAS,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;QACtG,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,yBAAS,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAEtE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAA;QACxB,KAAK,CAAC,UAAU,GAAG,UAAU,CAAA;QAE7B,IAAI,KAAK,GAAuB,MAAA,YAAY,CAAC,MAAoB,CAAC,0CAAE,KAAK,CAAA;QACzE,IAAI,MAAM,GAAuB,MAAA,YAAY,CAAC,MAAoB,CAAC,0CAAE,MAAM,CAAA;QAE3E,IAAI,iBAAiB,EAAE,CAAC;YACtB,KAAK,GAAG,SAAS,CAAA;YACjB,MAAM,GAAG,SAAS,CAAA;QACpB,CAAC;QAED,IAAI,SAAS,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,CAAC;YAAA,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACpC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,CAAA;QACvB,MAAM,IAAI,GAAG,WAAW,CAAA;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3D,MAAM,IAAI,GAAG,8BAA8B,CAAA;QAC3C,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAA;QAEjD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAQ,CAAC,OAAO,EAAE,CAAA;QAE7C,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,oCAAoC;YACrE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,qCAAqC;SACxE,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAEpB,MAAM,IAAI,CAAC,QAAQ,CACjB,IAAI,CAAC,EAAE;YACL,YAAY;YACZ,CAAC,CAAC,IAAI,GAAG,IAAI,CAAA;YACb,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,qBAAqB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;YACzC,CAAC,CAAC,CAAA;QACJ,CAAC,EACD,EAAE,KAAK,EAAE,IAAI,EAAE,CAChB,CAAA;QAED,YAAY;QACZ,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,iCACvC,IAAI,CAAC,MAAM,KACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,EACvC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,IAC1C,CAAA;QAEF,cAAc;QACd,MAAM,WAAW,GAAG,EAAE,CAAA,CAAC,gCAAgC;QACvD,MAAM,OAAO,CAAC,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA,CAAC,iBAAiB;QAEnF,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,cAAc;SAC7B,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,uBAAuB,CAAC,aAAa,GAAG;IACtC,GAAG,IAAA,yCAAsB,GAAE;IAC3B;QACE,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,SAAS,EAAE,QAAQ;SACpB;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,aAAa;QACpB,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,6EAA6E;KAC3F;CACF,CAAA;AAED,uBAAuB,CAAC,IAAI,GAAG,6CAA6C,CAAA;AAE5E,+BAAY,CAAC,mBAAmB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '@things-factory/integration-base'\nimport { PDFCaptureUtil, getCommonParameterSpec } from './pdf-capture-util'\nimport { BoardFunc } from '@things-factory/board-service'\n\nconst PAGE_FORMATS = {\n A4: { width: 595.28, height: 841.89 },\n A3: { width: 841.89, height: 1190.55 },\n Letter: { width: 612, height: 792 },\n Legal: { width: 612, height: 1008 }\n}\n\ntype PageFormat = keyof typeof PAGE_FORMATS\n\nexport async function HeadlessPDFCaptureBoard(step, context) {\n const pdfUtil = new PDFCaptureUtil(context)\n await pdfUtil.initBrowser(step.connection)\n\n try {\n const { board, draft, format = 'A4', landscape, preferCSSPageSize } = step.params\n\n if (!board || !board.id) {\n throw new Error('The board property must be set')\n }\n\n const { model, base } = await BoardFunc.headlessModel({ domain: context.domain, id: board.id }, draft)\n const [fontsToUse, fontStyles] = await BoardFunc.fonts(context.domain)\n\n model.fonts = fontsToUse\n model.fontStyles = fontStyles\n\n let width: number | undefined = PAGE_FORMATS[format as PageFormat]?.width\n let height: number | undefined = PAGE_FORMATS[format as PageFormat]?.height\n\n if (preferCSSPageSize) {\n width = undefined\n height = undefined\n }\n\n if (landscape && width && height) {\n ;[width, height] = [height, width]\n }\n\n const protocol = 'http'\n const host = 'localhost'\n const port = process.env.PORT ? `:${process.env.PORT}` : ''\n const path = '/internal-board-service-view'\n const url = `${protocol}://${host}${port}${path}`\n\n const page = await pdfUtil.browser!.newPage()\n\n await page.setViewport({\n width: Math.round(width || 800), // Fallback for width if not defined\n height: Math.round(height || 600) // Fallback for height if not defined\n })\n\n await page.goto(url)\n\n await page.evaluate(\n data => {\n //@ts-ignore\n s.data = data\n return new Promise(resolve => {\n requestAnimationFrame(() => resolve(0))\n })\n },\n { model, base }\n )\n\n // 페이지 옵션 설정\n const pageOptions = pdfUtil.buildPageOptions({\n ...step.params,\n width: width ? `${width}px` : undefined,\n height: height ? `${height}px` : undefined\n })\n\n // PDF 생성 및 추가\n const htmlContent = '' // 보드에서 직접 렌더링되므로 HTML 컨텐츠가 비어있음\n await pdfUtil.processPageAndGeneratePDF(pageOptions, htmlContent) // pageOptions 사용\n\n return {\n data: context.__headless_pdf\n }\n } catch (error) {\n throw error\n } finally {\n await pdfUtil.closeBrowser()\n }\n}\n\nHeadlessPDFCaptureBoard.parameterSpec = [\n ...getCommonParameterSpec(),\n {\n type: 'resource-object',\n name: 'board',\n label: 'board',\n property: {\n queryName: 'boards'\n }\n },\n {\n type: 'boolean',\n name: 'draft',\n label: 'board-draft',\n defaultValue: false,\n description: 'Set whether to get the current working version or the last released version'\n }\n]\n\nHeadlessPDFCaptureBoard.help = 'integration/task/headless-pdf-capture-board'\n\nTaskRegistry.registerTaskHandler('headless-pdf-capture-board', HeadlessPDFCaptureBoard)\n"]}
@@ -1,198 +1,53 @@
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"));
5
3
  const pdf_lib_1 = require("pdf-lib");
6
4
  const integration_base_1 = require("@things-factory/integration-base");
7
- const integration_base_2 = require("@things-factory/integration-base");
8
5
  const utils_1 = require("@things-factory/utils");
6
+ const pdf_capture_util_1 = require("./pdf-capture-util");
9
7
  async function HeadlessPDFOpen(step, context) {
10
- var { connection: connectionName, params: stepOptions } = step;
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;
13
- const headlessPool = integration_base_2.ConnectionManager.getConnectionInstanceByName(context.domain, connectionName);
14
- let browser;
8
+ const { connection: connectionName, params: stepOptions } = step;
9
+ const { accessor, coverPage, lastPage, header, footer, watermark, fileName } = stepOptions || {};
10
+ const { data } = context;
15
11
  // Create a new PDF document using pdf-lib
16
12
  const pdfDoc = await pdf_lib_1.PDFDocument.create();
13
+ const pdfInfo = {
14
+ pdfDoc,
15
+ watermark,
16
+ fileName,
17
+ pageCount: 0
18
+ };
19
+ context.__headless_pdf = pdfInfo;
20
+ const pdfUtil = new pdf_capture_util_1.PDFCaptureUtil(context);
21
+ await pdfUtil.initBrowser(connectionName);
17
22
  try {
18
- browser = await headlessPool.acquire();
19
- const page = await browser.newPage();
20
23
  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
24
  // Convert Cover Page to PDF and add it to the document (if provided)
31
25
  if (coverPage) {
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));
26
+ const renderedCoverPage = pdfUtil.renderTemplate(coverPage, templateInput);
27
+ await pdfUtil.processPageAndGeneratePDF(stepOptions, renderedCoverPage);
99
28
  }
100
29
  var lastPageBuffer;
101
30
  // Process Last Page (if provided) but add it later in the save task
102
31
  if (lastPage) {
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);
32
+ const renderedLastPage = pdfUtil.renderTemplate(lastPage, templateInput);
33
+ lastPageBuffer = await pdfUtil.generateLastPageBuffer(stepOptions, renderedLastPage);
166
34
  }
167
- await page.close();
168
- headlessPool.release(browser);
35
+ await pdfUtil.closeBrowser();
36
+ pdfInfo.lastPageBuffer = lastPageBuffer;
37
+ pdfInfo.pageCount = pdfDoc.getPageCount();
38
+ pdfInfo.header = header;
39
+ pdfInfo.footer = footer;
40
+ return {
41
+ data: pdfInfo
42
+ };
169
43
  }
170
44
  catch (error) {
171
- if (browser) {
172
- await browser.close();
173
- }
45
+ await pdfUtil.closeBrowser();
174
46
  throw error;
175
47
  }
176
- const pdfInfo = {
177
- pdfDoc,
178
- lastPageBuffer,
179
- header,
180
- footer,
181
- watermark,
182
- fileName,
183
- pageCount: pdfDoc.getPageCount()
184
- };
185
- context.__headless_pdf = pdfInfo;
186
- return {
187
- data: pdfInfo
188
- };
189
48
  }
190
49
  HeadlessPDFOpen.parameterSpec = [
191
- {
192
- type: 'scenario-step-input',
193
- name: 'accessor',
194
- label: 'accessor'
195
- },
50
+ ...(0, pdf_capture_util_1.getCommonParameterSpec)(),
196
51
  {
197
52
  type: 'textarea',
198
53
  name: 'coverPage',
@@ -224,91 +79,6 @@ HeadlessPDFOpen.parameterSpec = [
224
79
  type: 'string',
225
80
  name: 'fileName',
226
81
  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'
312
82
  }
313
83
  ];
314
84
  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":"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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
+ {"version":3,"file":"headless-pdf-open.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-open.ts"],"names":[],"mappings":";;AAAA,qCAAqC;AACrC,uEAA+D;AAC/D,iDAA8C;AAC9C,yDAA2E;AAE3E,KAAK,UAAU,eAAe,CAAC,IAAI,EAAE,OAAO;IAC1C,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAEhG,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;IAExB,0CAA0C;IAC1C,MAAM,MAAM,GAAG,MAAM,qBAAW,CAAC,MAAM,EAAE,CAAA;IAEzC,MAAM,OAAO,GAAG;QACd,MAAM;QACN,SAAS;QACT,QAAQ;QACR,SAAS,EAAE,CAAC;KACN,CAAA;IAER,OAAO,CAAC,cAAc,GAAG,OAAO,CAAA;IAEhC,MAAM,OAAO,GAAG,IAAI,iCAAc,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,CAAC,WAAW,CAAC,cAAc,CAAC,CAAA;IAEzC,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAA,cAAM,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAE5C,qEAAqE;QACrE,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;YAC1E,MAAM,OAAO,CAAC,yBAAyB,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAA;QACzE,CAAC;QAED,IAAI,cAAc,CAAA;QAElB,oEAAoE;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;YACxE,cAAc,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;QACtF,CAAC;QAED,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;QAE5B,OAAO,CAAC,cAAc,GAAG,cAAc,CAAA;QACvC,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAA;QACzC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAA;QACvB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAA;QAEvB,OAAO;YACL,IAAI,EAAE,OAAO;SACd,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;QAC5B,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,eAAe,CAAC,aAAa,GAAG;IAC9B,GAAG,IAAA,yCAAsB,GAAE;IAC3B;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;AAED,eAAe,CAAC,IAAI,GAAG,oCAAoC,CAAA;AAE3D,+BAAY,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAA","sourcesContent":["import { PDFDocument } from 'pdf-lib'\nimport { TaskRegistry } from '@things-factory/integration-base'\nimport { access } from '@things-factory/utils'\nimport { PDFCaptureUtil, getCommonParameterSpec } from './pdf-capture-util'\n\nasync function HeadlessPDFOpen(step, context) {\n const { connection: connectionName, params: stepOptions } = step\n const { accessor, coverPage, lastPage, header, footer, watermark, fileName } = stepOptions || {}\n\n const { data } = context\n\n // Create a new PDF document using pdf-lib\n const pdfDoc = await PDFDocument.create()\n\n const pdfInfo = {\n pdfDoc,\n watermark,\n fileName,\n pageCount: 0\n } as any\n\n context.__headless_pdf = pdfInfo\n\n const pdfUtil = new PDFCaptureUtil(context)\n await pdfUtil.initBrowser(connectionName)\n\n try {\n const templateInput = access(accessor, data)\n\n // Convert Cover Page to PDF and add it to the document (if provided)\n if (coverPage) {\n const renderedCoverPage = pdfUtil.renderTemplate(coverPage, templateInput)\n await pdfUtil.processPageAndGeneratePDF(stepOptions, renderedCoverPage)\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 = pdfUtil.renderTemplate(lastPage, templateInput)\n lastPageBuffer = await pdfUtil.generateLastPageBuffer(stepOptions, renderedLastPage)\n }\n\n await pdfUtil.closeBrowser()\n\n pdfInfo.lastPageBuffer = lastPageBuffer\n pdfInfo.pageCount = pdfDoc.getPageCount()\n pdfInfo.header = header\n pdfInfo.footer = footer\n\n return {\n data: pdfInfo\n }\n } catch (error) {\n await pdfUtil.closeBrowser()\n throw error\n }\n}\n\nHeadlessPDFOpen.parameterSpec = [\n ...getCommonParameterSpec(),\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\nHeadlessPDFOpen.help = 'integration/task/headless-pdf-open'\n\nTaskRegistry.registerTaskHandler('headless-pdf-open', HeadlessPDFOpen)\n"]}
@@ -1,28 +1,48 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const pdf_lib_1 = require("pdf-lib");
4
- const { Readable } = require('stream');
4
+ const stream_1 = require("stream");
5
5
  const integration_base_1 = require("@things-factory/integration-base");
6
6
  const attachment_base_1 = require("@things-factory/attachment-base");
7
7
  const shell_1 = require("@things-factory/shell");
8
8
  async function HeadlessPDFSave(step, context) {
9
- var { domain, user, __headless_pdf } = context;
9
+ const { domain, user, __headless_pdf } = context;
10
10
  if (!__headless_pdf || !__headless_pdf.pdfDoc) {
11
11
  throw new Error('No PDF document found. Ensure that headless-pdf-open and headless-pdf-capture tasks are executed before saving.');
12
12
  }
13
13
  const pdfDoc = __headless_pdf.pdfDoc;
14
14
  // Add last page if it exists
15
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));
16
+ await appendLastPageToPDF(pdfDoc, __headless_pdf.lastPageBuffer);
19
17
  }
20
18
  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, {
19
+ const finalFileName = generateFileName(__headless_pdf.fileName);
20
+ const savedAttachment = await savePDFToFile(pdfBytes, finalFileName, domain, user);
21
+ const attachment = await getAttachmentDetails(savedAttachment.id);
22
+ return {
23
+ data: {
24
+ id: attachment.id,
25
+ name: attachment.name,
26
+ path: attachment.path,
27
+ mimetype: attachment.mimetype,
28
+ refBy: attachment.refBy,
29
+ fullpath: attachment.fullpath
30
+ }
31
+ };
32
+ }
33
+ async function appendLastPageToPDF(pdfDoc, lastPageBuffer) {
34
+ const lastPageDoc = await pdf_lib_1.PDFDocument.load(lastPageBuffer);
35
+ const copiedLastPages = await pdfDoc.copyPages(lastPageDoc, lastPageDoc.getPageIndices());
36
+ copiedLastPages.forEach(page => pdfDoc.addPage(page));
37
+ }
38
+ function generateFileName(fileName) {
39
+ return fileName || `document-${Date.now()}.pdf`;
40
+ }
41
+ async function savePDFToFile(pdfBytes, finalFileName, domain, user) {
42
+ return await (0, attachment_base_1.createAttachment)(null, {
23
43
  attachment: {
24
44
  file: {
25
- createReadStream: () => new Readable({
45
+ createReadStream: () => new stream_1.Readable({
26
46
  read() {
27
47
  this.push(pdfBytes);
28
48
  this.push(null);
@@ -38,19 +58,11 @@ async function HeadlessPDFSave(step, context) {
38
58
  }, {
39
59
  state: { domain, user }
40
60
  });
41
- const attachment = await (0, shell_1.getRepository)(attachment_base_1.Attachment).findOne({
42
- where: { id: saved.id }
61
+ }
62
+ async function getAttachmentDetails(attachmentId) {
63
+ return await (0, shell_1.getRepository)(attachment_base_1.Attachment).findOne({
64
+ where: { id: attachmentId }
43
65
  });
44
- return {
45
- data: {
46
- id: attachment.id,
47
- name: attachment.name,
48
- path: attachment.path,
49
- mimetype: attachment.mimetype,
50
- refBy: attachment.refBy,
51
- fullpath: attachment.fullpath
52
- }
53
- };
54
66
  }
55
67
  HeadlessPDFSave.parameterSpec = [];
56
68
  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,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
+ {"version":3,"file":"headless-pdf-save.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-save.ts"],"names":[],"mappings":"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","sourcesContent":["import { PDFDocument } from 'pdf-lib'\nimport { Readable } from 'stream'\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 const { 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 await appendLastPageToPDF(pdfDoc, __headless_pdf.lastPageBuffer)\n }\n\n const pdfBytes = await pdfDoc.save()\n const finalFileName = generateFileName(__headless_pdf.fileName)\n\n const savedAttachment = await savePDFToFile(pdfBytes, finalFileName, domain, user)\n const attachment = await getAttachmentDetails(savedAttachment.id)\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\nasync function appendLastPageToPDF(pdfDoc, lastPageBuffer) {\n const lastPageDoc = await PDFDocument.load(lastPageBuffer)\n const copiedLastPages = await pdfDoc.copyPages(lastPageDoc, lastPageDoc.getPageIndices())\n copiedLastPages.forEach(page => pdfDoc.addPage(page))\n}\n\nfunction generateFileName(fileName) {\n return fileName || `document-${Date.now()}.pdf`\n}\n\nasync function savePDFToFile(pdfBytes, finalFileName, domain, user) {\n return 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\nasync function getAttachmentDetails(attachmentId) {\n return await getRepository(Attachment).findOne({\n where: { id: attachmentId }\n })\n}\n\nHeadlessPDFSave.parameterSpec = []\n\nHeadlessPDFSave.help = 'integration/task/headless-pdf-save'\n\nTaskRegistry.registerTaskHandler('headless-pdf-save', HeadlessPDFSave)\n"]}
@@ -28,16 +28,24 @@ export declare class PDFCaptureUtil {
28
28
  initBrowser(connectionName: string): Promise<void>;
29
29
  closeBrowser(): Promise<void>;
30
30
  renderTemplate(template: string, data: any): string;
31
- generatePDFContent(page: Page, htmlContent: string, pageOptions: any): Promise<PDFDocument>;
31
+ generatePDFContent(page: Page, pageOptions: any): Promise<PDFDocument>;
32
32
  appendPDFContentToDocument(pdfDoc: PDFDocument, contentPdfDoc: PDFDocument): Promise<void>;
33
33
  processPageAndGeneratePDF(stepOptions: StepOptions, htmlContent: string): Promise<void>;
34
34
  buildPageOptions({ format, width, height, marginTop, marginBottom, marginLeft, marginRight, scale, printBackground, landscape, preferCSSPageSize }: StepOptions): any;
35
- applyHeaderFooterWatermark(page: Page, { header, footer, watermark, landscape }: {
35
+ applyHeaderFooterWatermark(page: Page, { header, footer, watermark, landscape, data }: {
36
36
  header: string;
37
37
  footer: string;
38
38
  watermark: string;
39
39
  landscape: boolean;
40
+ data: any;
40
41
  }): Promise<void>;
42
+ /**
43
+ * Generates a PDF buffer for the last page.
44
+ * @param stepOptions - Options used for generating the PDF.
45
+ * @param htmlContent - HTML content to be converted to PDF.
46
+ * @returns {Promise<Uint8Array>} - The generated PDF as a buffer.
47
+ */
48
+ generateLastPageBuffer(stepOptions: StepOptions, htmlContent: string): Promise<Uint8Array>;
41
49
  }
42
50
  export declare function getCommonParameterSpec(): ({
43
51
  type: string;
@@ -32,8 +32,7 @@ class PDFCaptureUtil {
32
32
  return template;
33
33
  }
34
34
  }
35
- async generatePDFContent(page, htmlContent, pageOptions) {
36
- await page.setContent(htmlContent);
35
+ async generatePDFContent(page, pageOptions) {
37
36
  const contentBuffer = await page.pdf(pageOptions);
38
37
  const contentPdfDoc = await pdf_lib_1.PDFDocument.load(contentBuffer);
39
38
  return contentPdfDoc;
@@ -47,13 +46,16 @@ class PDFCaptureUtil {
47
46
  if (!this.browser)
48
47
  throw new Error('Browser not initialized. Call initBrowser() first.');
49
48
  const page = await this.browser.newPage();
49
+ // 페이지 컨텐츠 설정
50
+ await page.setContent(htmlContent, { waitUntil: 'networkidle0' }); // HTML 컨텐츠가 완전히 로드될 때까지 대기
51
+ // 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용
50
52
  const { __headless_pdf } = this.context;
51
53
  const { header, footer, watermark, landscape } = __headless_pdf;
52
54
  if (header || footer || watermark) {
53
- await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape });
55
+ await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data: __headless_pdf });
54
56
  }
55
57
  const pageOptions = this.buildPageOptions(stepOptions);
56
- const contentPdfDoc = await this.generatePDFContent(page, htmlContent, pageOptions);
58
+ const contentPdfDoc = await this.generatePDFContent(page, pageOptions);
57
59
  await this.appendPDFContentToDocument(__headless_pdf.pdfDoc, contentPdfDoc);
58
60
  await page.close();
59
61
  }
@@ -79,8 +81,8 @@ class PDFCaptureUtil {
79
81
  preferCSSPageSize
80
82
  };
81
83
  }
82
- async applyHeaderFooterWatermark(page, { header, footer, watermark, landscape }) {
83
- await page.evaluate(({ header, footer, watermark, landscape }) => {
84
+ async applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data }) {
85
+ await page.evaluate(({ header, footer, watermark, landscape, data }) => {
84
86
  const setPositioning = (element, position) => {
85
87
  element.style.position = 'fixed';
86
88
  element.style.left = '0';
@@ -89,6 +91,7 @@ class PDFCaptureUtil {
89
91
  element.style.fontSize = '12px';
90
92
  element.style.margin = '0';
91
93
  element.style.padding = '0';
94
+ element.style.zIndex = '1000';
92
95
  if (position === 'header') {
93
96
  element.style.top = '0';
94
97
  }
@@ -122,7 +125,39 @@ class PDFCaptureUtil {
122
125
  watermarkElement.style.zIndex = '9999';
123
126
  document.body.appendChild(watermarkElement);
124
127
  }
125
- }, { header, footer, watermark, landscape });
128
+ }, {
129
+ header: header && this.renderTemplate(header, data),
130
+ footer: footer && this.renderTemplate(footer, data),
131
+ watermark: watermark && this.renderTemplate(watermark, data),
132
+ landscape,
133
+ data
134
+ });
135
+ }
136
+ /**
137
+ * Generates a PDF buffer for the last page.
138
+ * @param stepOptions - Options used for generating the PDF.
139
+ * @param htmlContent - HTML content to be converted to PDF.
140
+ * @returns {Promise<Uint8Array>} - The generated PDF as a buffer.
141
+ */
142
+ async generateLastPageBuffer(stepOptions, htmlContent) {
143
+ if (!this.browser)
144
+ throw new Error('Browser not initialized. Call initBrowser() first.');
145
+ const page = await this.browser.newPage();
146
+ // 페이지에 HTML 콘텐츠를 설정합니다.
147
+ await page.setContent(htmlContent, { waitUntil: 'networkidle0' });
148
+ // 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용
149
+ const { __headless_pdf } = this.context;
150
+ const { header, footer, watermark, landscape } = __headless_pdf;
151
+ if (header || footer || watermark) {
152
+ await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data: __headless_pdf });
153
+ }
154
+ // 페이지 옵션 설정
155
+ const pageOptions = this.buildPageOptions(stepOptions);
156
+ // PDF를 생성하고 버퍼를 반환합니다.
157
+ const lastPageBuffer = await page.pdf(pageOptions);
158
+ // 페이지 닫기
159
+ await page.close();
160
+ return lastPageBuffer;
126
161
  }
127
162
  }
128
163
  exports.PDFCaptureUtil = PDFCaptureUtil;