diff --git a/components/documerge/actions/combine-files/combine-files.mjs b/components/documerge/actions/combine-files/combine-files.mjs new file mode 100644 index 0000000000000..944177fd8af30 --- /dev/null +++ b/components/documerge/actions/combine-files/combine-files.mjs @@ -0,0 +1,53 @@ +import documerge from "../../documerge.app.mjs"; +import fs from "fs"; + +export default { + key: "documerge-combine-files", + name: "Combine Files", + description: "Merges multiple user-specified files into a single PDF or DOCX. [See the documentation](https://app.documerge.ai/api-docs/#tools-POSTapi-tools-combine)", + version: "0.0.1", + type: "action", + props: { + documerge, + name: { + type: "string", + label: "Name", + description: "Name of the new file", + }, + output: { + type: "string", + label: "Output", + description: "The output file type", + options: [ + "pdf", + "docx", + ], + }, + urls: { + type: "string[]", + label: "URLs", + description: "Array of URLs to combine", + }, + }, + async run({ $ }) { + const fileContent = await this.documerge.combineFiles({ + $, + data: { + output: this.output, + files: this.urls.map((url) => ({ + name: this.name, + url, + })), + }, + }); + + const filename = this.name.includes(".pdf") || this.name.includes(".docx") + ? this.name + : `${this.name}.${this.output}`; + const path = `/tmp/${filename}`; + await fs.writeFileSync(path, Buffer.from(fileContent)); + + $.export("$summary", "Successfully combined files"); + return path; + }, +}; diff --git a/components/documerge/actions/convert-file-to-pdf/convert-file-to-pdf.mjs b/components/documerge/actions/convert-file-to-pdf/convert-file-to-pdf.mjs new file mode 100644 index 0000000000000..c5751f6fc93ba --- /dev/null +++ b/components/documerge/actions/convert-file-to-pdf/convert-file-to-pdf.mjs @@ -0,0 +1,44 @@ +import documerge from "../../documerge.app.mjs"; +import fs from "fs"; + +export default { + key: "documerge-convert-file-to-pdf", + name: "Convert File to PDF", + description: "Converts a specified file into a PDF. [See the documentation](https://app.documerge.ai/api-docs/#tools-POSTapi-tools-pdf-convert)", + version: "0.0.1", + type: "action", + props: { + documerge, + name: { + type: "string", + label: "Name", + description: "Name of the new file", + }, + url: { + type: "string", + label: "URL", + description: "The URL of the file to convert", + optional: true, + }, + }, + async run({ $ }) { + const fileContent = await this.documerge.convertToPdf({ + $, + data: { + file: { + name: this.name, + url: this.url, + }, + }, + }); + + const filename = this.name.includes(".pdf") + ? this.name + : `${this.name}.pdf`; + const path = `/tmp/${filename}`; + await fs.writeFileSync(path, Buffer.from(fileContent)); + + $.export("$summary", "Successfully converted file to PDF"); + return path; + }, +}; diff --git a/components/documerge/actions/get-document-fields/get-document-fields.mjs b/components/documerge/actions/get-document-fields/get-document-fields.mjs new file mode 100644 index 0000000000000..2cde3e238e5a9 --- /dev/null +++ b/components/documerge/actions/get-document-fields/get-document-fields.mjs @@ -0,0 +1,26 @@ +import documerge from "../../documerge.app.mjs"; + +export default { + key: "documerge-get-document-fields", + name: "Get Document Fields", + description: "Extracts and returns data from fields in a given document. [See the documentation](https://app.documerge.ai/api-docs/#documents-GETapi-documents-fields--document_id-)", + version: "0.0.1", + type: "action", + props: { + documerge, + documentId: { + propDefinition: [ + documerge, + "documentId", + ], + }, + }, + async run({ $ }) { + const response = await this.documerge.getDocumentFields({ + $, + documentId: this.documentId, + }); + $.export("$summary", `Successfully extracted field values from document with ID: ${this.documentId}`); + return response; + }, +}; diff --git a/components/documerge/documerge.app.mjs b/components/documerge/documerge.app.mjs index 9baf44c69ad57..7ce530e34725f 100644 --- a/components/documerge/documerge.app.mjs +++ b/components/documerge/documerge.app.mjs @@ -1,11 +1,129 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "documerge", - propDefinitions: {}, + propDefinitions: { + documentId: { + type: "string", + label: "Document ID", + description: "Identifier of a document", + async options() { + const { data } = await this.listDocuments(); + return data?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + routeId: { + type: "string", + label: "Routet ID", + description: "Identifier of a route", + async options() { + const { data } = await this.listRoutes(); + return data?.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://app.documerge.ai/api"; + }, + _makeRequest(opts = {}) { + const { + $ = this, + path, + ...otherOpts + } = opts; + return axios($, { + ...otherOpts, + url: `${this._baseUrl()}${path}`, + headers: { + "Authorization": `Bearer ${this.$auth.api_token}`, + "Content-Type": "application/json", + "Accept": "application/json", + }, + }); + }, + listDocuments(opts = {}) { + return this._makeRequest({ + path: "/documents", + ...opts, + }); + }, + listRoutes(opts = {}) { + return this._makeRequest({ + path: "/routes", + ...opts, + }); + }, + getDocumentFields({ + documentId, ...opts + }) { + return this._makeRequest({ + path: `/documents/fields/${documentId}`, + ...opts, + }); + }, + combineFiles(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/tools/combine", + responseType: "arraybuffer", + ...opts, + }); + }, + convertToPdf(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/tools/pdf/convert", + responseType: "arraybuffer", + ...opts, + }); + }, + createDocumentDeliveryMethod({ + documentId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/documents/delivery-methods/${documentId}`, + ...opts, + }); + }, + deleteDocumentDeliveryMethod({ + documentId, deliveryMethodId, ...opts + }) { + return this._makeRequest({ + method: "DELETE", + path: `/documents/delivery-methods/${documentId}/${deliveryMethodId}`, + ...opts, + }); + }, + createRouteDeliveryMethod({ + routeId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/routes/delivery-methods/${routeId}`, + ...opts, + }); + }, + deleteRouteDeliveryMethod({ + routeId, deliveryMethodId, ...opts + }) { + return this._makeRequest({ + method: "DELETE", + path: `/routes/delivery-methods/${routeId}/${deliveryMethodId}`, + ...opts, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/documerge/package.json b/components/documerge/package.json index 453ca0dc85e9c..70633a3ac5936 100644 --- a/components/documerge/package.json +++ b/components/documerge/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/documerge", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream DocuMerge Components", "main": "documerge.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.0" } -} \ No newline at end of file +} diff --git a/components/documerge/sources/common/base.mjs b/components/documerge/sources/common/base.mjs new file mode 100644 index 0000000000000..4a785fb20d30d --- /dev/null +++ b/components/documerge/sources/common/base.mjs @@ -0,0 +1,44 @@ +import documerge from "../../documerge.app.mjs"; + +export default { + props: { + documerge, + http: "$.interface.http", + db: "$.service.db", + }, + methods: { + _getDeliveryMethodIds() { + return this.db.get("deliveryMethodIds") || {}; + }, + _setDeliveryMethodIds(deliveryMethodIds) { + this.db.set("deliveryMethodIds", deliveryMethodIds); + }, + getWebhookSettings() { + return { + type: "webhook", + settings: { + url: this.http.endpoint, + always_send: true, + send_temporary_download_url: true, + send_data_using_json: true, + send_merge_data: true, + }, + }; + }, + generateMeta(body) { + return { + id: body.merge_id, + summary: this.getSummary(body), + ts: Date.now(), + }; + }, + getSummary() { + throw new Error("getSummary is not implemented"); + }, + }, + async run(event) { + const { body } = event; + const meta = this.generateMeta(body); + this.$emit(body, meta); + }, +}; diff --git a/components/documerge/sources/new-merged-document-instant/new-merged-document-instant.mjs b/components/documerge/sources/new-merged-document-instant/new-merged-document-instant.mjs new file mode 100644 index 0000000000000..41acdc38923cb --- /dev/null +++ b/components/documerge/sources/new-merged-document-instant/new-merged-document-instant.mjs @@ -0,0 +1,54 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "documerge-new-merged-document-instant", + name: "New Merged Document (Instant)", + description: "Emit new event when a merged document is created in documerge.", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + documentIds: { + propDefinition: [ + common.props.documerge, + "documentId", + ], + type: "string[]", + label: "Document IDs", + description: "An array of document identifiers of the documents to watch", + }, + }, + hooks: { + async activate() { + const deliveryMethodIds = {}; + for (const documentId of this.documentIds) { + const { data: { id } } = await this.documerge.createDocumentDeliveryMethod({ + documentId, + data: this.getWebhookSettings(), + }); + deliveryMethodIds[documentId] = id; + } + this._setDeliveryMethodIds(deliveryMethodIds); + }, + async deactivate() { + const deliveryMethodIds = this._getDeliveryMethodIds(); + for (const documentId of this.documentIds) { + await this.documerge.deleteDocumentDeliveryMethod({ + documentId, + deliveryMethodId: deliveryMethodIds[documentId], + }); + } + this._setDeliveryMethodIds({}); + }, + }, + methods: { + ...common.methods, + getSummary(body) { + return `Merged Document: ${body.file_name}`; + }, + }, + sampleEmit, +}; diff --git a/components/documerge/sources/new-merged-document-instant/test-event.mjs b/components/documerge/sources/new-merged-document-instant/test-event.mjs new file mode 100644 index 0000000000000..95c5d8f8ee835 --- /dev/null +++ b/components/documerge/sources/new-merged-document-instant/test-event.mjs @@ -0,0 +1,12 @@ +export default { + "file_url": "https://documerge.blob.core.windows.net/documerge/documentMerges/408/294186/doc1_-_test.pdf?sv=2017-11-09&sr=b&se=2024-07-18T17:16:51Z&sp=r&spr=https&sig=%2F02yOVeuTEB66AihSptlTg7a7GYfxz3JGkxKE2kt94Y%3D", + "file_name": "doc1 - test.pdf", + "merge_id": 320214, + "fields": { + "field1": "test", + "_date": "2024-07-18", + "_datetime": "2024-07-18 12:16 pm", + "_ip": "10.1.0.4", + "_auto_number": null + } +} \ No newline at end of file diff --git a/components/documerge/sources/new-merged-route-instant/new-merged-route-instant.mjs b/components/documerge/sources/new-merged-route-instant/new-merged-route-instant.mjs new file mode 100644 index 0000000000000..5da9b0a2c7041 --- /dev/null +++ b/components/documerge/sources/new-merged-route-instant/new-merged-route-instant.mjs @@ -0,0 +1,54 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "documerge-new-merged-route-instant", + name: "New Merged Route (Instant)", + description: "Emit new event when a merged route is created in documerge.", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ...common.props, + routeIds: { + propDefinition: [ + common.props.documerge, + "routeId", + ], + type: "string[]", + label: "Route IDs", + description: "An array of route identifiers of the routes to watch", + }, + }, + hooks: { + async activate() { + const deliveryMethodIds = {}; + for (const routeId of this.routeIds) { + const { data: { id } } = await this.documerge.createRouteDeliveryMethod({ + routeId, + data: this.getWebhookSettings(), + }); + deliveryMethodIds[routeId] = id; + } + this._setDeliveryMethodIds(deliveryMethodIds); + }, + async deactivate() { + const deliveryMethodIds = this.getDeliveryMethodIds(); + for (const routeId of this.routeIds) { + await this.documerge.deleteRoutetDeliveryMethod({ + routeId, + deliveryMethodId: deliveryMethodIds[routeId], + }); + } + this._setDeliveryMethodIds({}); + }, + }, + methods: { + ...common.methods, + getSummary(body) { + return `Merged Route: ${body.file_name}`; + }, + }, + sampleEmit, +}; diff --git a/components/documerge/sources/new-merged-route-instant/test-event.mjs b/components/documerge/sources/new-merged-route-instant/test-event.mjs new file mode 100644 index 0000000000000..75e75ebe5b59b --- /dev/null +++ b/components/documerge/sources/new-merged-route-instant/test-event.mjs @@ -0,0 +1,13 @@ +export default { + "file_url": "https://documerge.blob.core.windows.net/documerge/combinedFiles/294339/route1_-_test.pdf?sv=2017-11-09&sr=b&se=2024-07-18T17:42:40Z&sp=r&spr=https&sig=6jsL2yYs3URH3g193%2Fvc1AK66vAdx7G8q5hOn1gmPVg%3D", + "file_name": "route1 - test.pdf", + "merge_id": 320379, + "fields": { + "field1": "abc", + "_date": "2024-07-18", + "_datetime": "2024-07-18 12:42 pm", + "_ip": "10.1.0.4", + "_auto_number": null, + "_route_auto_number": null + } +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69256d1d4feeb..8d176ce698002 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2451,7 +2451,10 @@ importers: form-data: 4.0.0 components/documerge: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.0 + dependencies: + '@pipedream/platform': 3.0.0 components/documint: specifiers: