diff --git a/components/pdforge/actions/common/base.mjs b/components/pdforge/actions/common/base.mjs new file mode 100644 index 0000000000000..6ee73d9504022 --- /dev/null +++ b/components/pdforge/actions/common/base.mjs @@ -0,0 +1,134 @@ +import fs from "fs"; +import stream from "stream"; +import { promisify } from "util"; +import { + checkTmp, + clearObj, +} from "../../common/utils.mjs"; +import pdforge from "../../pdforge.app.mjs"; + +export default { + props: { + pdforge, + convertToImage: { + type: "boolean", + label: "Convert to Image", + description: "If true, will return a .PNG file instead of a .PDF file", + default: false, + }, + asyncMode: { + type: "boolean", + label: "Async Mode", + description: "If `true`, the request will be executed in the background and the response will be sent to the webhook URL.", + default: false, + reloadProps: true, + }, + saveS3: { + type: "boolean", + label: "Save to S3", + description: "If `true`, the generated file will be saved to the provided s3 bucket; if `false`, the generated file will be saved to the Pipedream `/tmp` directory.", + default: true, + reloadProps: true, + hidden: true, + }, + s3bucket: { + propDefinition: [ + pdforge, + "s3bucket", + ], + hidden: true, + }, + s3key: { + propDefinition: [ + pdforge, + "s3key", + ], + hidden: true, + }, + fileName: { + propDefinition: [ + pdforge, + "fileName", + ], + hidden: true, + }, + webhook: { + propDefinition: [ + pdforge, + "webhook", + ], + hidden: true, + }, + }, + async additionalProps(props) { + const isAsync = this.asyncMode; + const saveAtS3 = this.saveS3; + + props.webhook.hidden = !isAsync; + props.saveS3.hidden = isAsync; + + const showS3 = !isAsync && saveAtS3; + props.s3bucket.hidden = !showS3; + props.s3key.hidden = !showS3; + props.fileName.hidden = showS3; + return {}; + }, + async run({ $ }) { + let response; + + const data = { + ...this.getAdditionalData(), + convertToImage: this.convertToImage, + webhook: this.webhook, + }; + + if (this.saveS3) { + data.s3Bucked = this.s3Bucked; + data.s3Key = this.s3Key; + } + + if (this.asyncMode) { + data.webhook = this.webhook; + } + + const fn = this.getFunction(); + + const asyncResponse = await fn({ + $, + asyncMode: this.asyncMode, + data: clearObj(data), + }); + + response = asyncResponse; + + if (!this.saveS3 && !this.asyncMode) { + const fileStream = await this.pdforge._makeRequest({ + baseUrl: response.signedUrl, + responseType: "stream", + removeHeader: true, + }); + + const filePath = checkTmp( + `${this.fileName}.${this.convertToImage + ? "PNG" + : "PDF"}`, + ); + + const pipeline = promisify(stream.pipeline); + await pipeline(fileStream, fs.createWriteStream(filePath)); + + response = { + ...asyncResponse, + filePath, + }; + } + + if (this.asyncMode) { + $.export("$summary", "Asynchronous request initiated. Await the webhook callback for completion."); + } else { + $.export("$summary", this.getSummary(this)); + } + + return response; + }, +}; diff --git a/components/pdforge/actions/generate-pdf-from-html/generate-pdf-from-html.mjs b/components/pdforge/actions/generate-pdf-from-html/generate-pdf-from-html.mjs new file mode 100644 index 0000000000000..a233c4efc63a3 --- /dev/null +++ b/components/pdforge/actions/generate-pdf-from-html/generate-pdf-from-html.mjs @@ -0,0 +1,41 @@ +import { parseObject } from "../../common/utils.mjs"; +import common from "../common/base.mjs"; + +export default { + ...common, + key: "pdforge-generate-pdf-from-html", + name: "Generate PDF from HTML", + description: "Generate a PDF document from HTML content. [See the documentation](https://docs.pdforge.com/html-to-pdf-conversion/synchronous-request)", + version: "0.0.1", + type: "action", + props: { + ...common.props, + html: { + type: "string", + label: "HTML", + description: "The HTML content you want to render", + }, + pdfParams: { + type: "object", + label: "PDF Params", + description: "The object containing the parameters for your PDF. [See all the options here](https://docs.pdforge.com/options/pdf-params).", + optional: true, + }, + }, + methods: { + getAdditionalData() { + return { + html: this.html, + pdfParams: parseObject(this.pdfParams), + }; + }, + getFunction() { + return this.pdforge.generatePDFfromHTML; + }, + getSummary({ convertToImage }) { + return `${convertToImage + ? "PNG" + : "PDF"} successfully generated from provided HTML content.`; + }, + }, +}; diff --git a/components/pdforge/actions/generate-pdf-from-template/generate-pdf-from-template.mjs b/components/pdforge/actions/generate-pdf-from-template/generate-pdf-from-template.mjs new file mode 100644 index 0000000000000..b11f68c4e831d --- /dev/null +++ b/components/pdforge/actions/generate-pdf-from-template/generate-pdf-from-template.mjs @@ -0,0 +1,40 @@ +import { parseObject } from "../../common/utils.mjs"; +import common from "../common/base.mjs"; + +export default { + ...common, + key: "pdforge-generate-pdf-from-template", + name: "Generate PDF from Template", + description: "Generate a document from a selected template. [See the documentation](https://docs.pdforge.com/pdfs-from-templates/synchronous-request)", + version: "0.0.1", + type: "action", + props: { + ...common.props, + templateId: { + type: "string", + label: "Template ID", + description: "The ID of the template from which to generate the document", + }, + data: { + type: "object", + label: "Data", + description: "The object containing the variables for your PDF template", + }, + }, + methods: { + getAdditionalData() { + return { + templateId: this.templateId, + data: parseObject(this.data), + }; + }, + getFunction() { + return this.pdforge.generateDocumentFromTemplate; + }, + getSummary({ convertToImage }) { + return `${convertToImage + ? "PNG" + : "PDF"} generated successfully from template ID: ${this.templateId}`; + }, + }, +}; diff --git a/components/pdforge/common/utils.mjs b/components/pdforge/common/utils.mjs new file mode 100644 index 0000000000000..9420d92839d7d --- /dev/null +++ b/components/pdforge/common/utils.mjs @@ -0,0 +1,48 @@ +export const checkTmp = (filename) => { + if (!filename.startsWith("/tmp")) { + return `/tmp/${filename}`; + } + return filename; +}; + +export const parseObject = (obj) => { + if (!obj) return undefined; + + if (Array.isArray(obj)) { + return obj.map((item) => { + if (typeof item === "string") { + try { + return JSON.parse(item); + } catch (e) { + return item; + } + } + return item; + }); + } + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + return obj; +}; + +export const clearObj = (obj) => { + return Object.entries(obj) + .filter(([ + , + v, + ]) => (v != null && v != "" && JSON.stringify(v) != "{}")) + .reduce((acc, [ + k, + v, + ]) => ({ + ...acc, + [k]: (!Array.isArray(v) && v === Object(v)) + ? clearObj(v) + : v, + }), {}); +}; diff --git a/components/pdforge/package.json b/components/pdforge/package.json index 2eacebda43e22..58340b2703626 100644 --- a/components/pdforge/package.json +++ b/components/pdforge/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/pdforge", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream pdforge Components", "main": "pdforge.app.mjs", "keywords": [ @@ -11,5 +11,10 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3", + "stream": "^0.0.3", + "util": "^0.12.5" } -} \ No newline at end of file +} diff --git a/components/pdforge/pdforge.app.mjs b/components/pdforge/pdforge.app.mjs index 31a2f1a8c3883..e4a2e9f6deda9 100644 --- a/components/pdforge/pdforge.app.mjs +++ b/components/pdforge/pdforge.app.mjs @@ -1,11 +1,72 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "pdforge", - propDefinitions: {}, + propDefinitions: { + s3bucket: { + type: "string", + label: "S3 Bucket", + description: "The ID of the active S3 connection to store the generated file on", + }, + s3key: { + type: "string", + label: "S3 Key", + description: "The path and filename without extension for saving the file in the S3 bucket", + secret: true, + }, + fileName: { + type: "string", + label: "File Name", + description: "The filename without extension for saving the file in the `/tmp` direcrtory", + }, + webhook: { + type: "string", + label: "Webhook URL", + description: "The URL of your webhook endpoint", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl(baseUrl) { + return baseUrl || "https://api.pdforge.com/v1"; + }, + _headers(removeHeader = false) { + return removeHeader + ? {} + : { + Authorization: `Bearer ${this.$auth.api_key}`, + }; + }, + _makeRequest({ + $ = this, baseUrl, removeHeader, path = "", ...opts + }) { + return axios($, { + url: this._baseUrl(baseUrl) + path, + headers: this._headers(removeHeader), + ...opts, + }); + }, + generateDocumentFromTemplate({ + asyncMode, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/pdf/${asyncMode + ? "async" + : "sync"}`, + ...opts, + }); + }, + generatePDFfromHTML({ + asyncMode, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/html-to-pdf/${asyncMode + ? "async" + : "sync"}`, + ...opts, + }); }, }, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c1a50a7626a9..382bab8f38873 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9604,7 +9604,17 @@ importers: specifier: ^3.0.3 version: 3.0.3 - components/pdforge: {} + components/pdforge: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 + stream: + specifier: ^0.0.3 + version: 0.0.3 + util: + specifier: ^0.12.5 + version: 0.12.5 components/peach: dependencies: @@ -15404,14 +15414,6 @@ importers: specifier: ^6.0.0 version: 6.2.0 - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/cjs: {} - - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/esm: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/cjs: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/esm: {} - packages/ai: dependencies: '@pipedream/sdk':