diff --git a/components/lumin_pdf/actions/cancel-signature-request/cancel-signature-request.mjs b/components/lumin_pdf/actions/cancel-signature-request/cancel-signature-request.mjs new file mode 100644 index 0000000000000..d51e244d38b92 --- /dev/null +++ b/components/lumin_pdf/actions/cancel-signature-request/cancel-signature-request.mjs @@ -0,0 +1,32 @@ +import luminPdf from "../../lumin_pdf.app.mjs"; + +export default { + key: "lumin_pdf-cancel-signature-request", + name: "Cancel Signature Request", + description: "Cancel a signature request. [See the documentation](https://developers.luminpdf.com/api/cancel-signature-request/)", + version: "0.0.1", + type: "action", + props: { + luminPdf, + alert: { + type: "alert", + alertType: "info", + content: "This action only works for signature requests that were created via API.", + }, + signatureRequestId: { + propDefinition: [ + luminPdf, + "signatureRequestId", + ], + }, + }, + async run({ $ }) { + const response = await this.luminPdf.cancelSignatureRequest({ + $, + signatureRequestId: this.signatureRequestId, + }); + + $.export("$summary", `Successfully cancelled signature request with ID: ${this.signatureRequestId}`); + return response; + }, +}; diff --git a/components/lumin_pdf/actions/download-file-as-file-url/download-file-as-file-url.mjs b/components/lumin_pdf/actions/download-file-as-file-url/download-file-as-file-url.mjs new file mode 100644 index 0000000000000..0df2ca17bee44 --- /dev/null +++ b/components/lumin_pdf/actions/download-file-as-file-url/download-file-as-file-url.mjs @@ -0,0 +1,27 @@ +import luminPdf from "../../lumin_pdf.app.mjs"; + +export default { + name: "Download File as File URL", + version: "0.0.1", + key: "lumin_pdf-download-file-as-file-url", + description: "Get a download URL for a file. [See the documentation](https://developers.luminpdf.com/api/download-file-as-file-url/)", + type: "action", + props: { + luminPdf, + signatureRequestId: { + propDefinition: [ + luminPdf, + "signatureRequestId", + ], + }, + }, + async run({ $ }) { + const response = await this.luminPdf.downloadFileAsFileUrl({ + $, + signatureRequestId: this.signatureRequestId, + }); + + $.export("$summary", `Successfully retrieved download URL for signature request with ID: ${this.signatureRequestId}`); + return response; + }, +}; diff --git a/components/lumin_pdf/actions/download-file/download-file.mjs b/components/lumin_pdf/actions/download-file/download-file.mjs new file mode 100644 index 0000000000000..1957263d11289 --- /dev/null +++ b/components/lumin_pdf/actions/download-file/download-file.mjs @@ -0,0 +1,46 @@ +import fs from "fs"; +import stream from "stream"; +import { promisify } from "util"; +import luminPdf from "../../lumin_pdf.app.mjs"; + +export default { + name: "Download File", + version: "0.0.1", + key: "lumin_pdf-download-file", + description: "Download a file directly. [See the documentation](https://developers.luminpdf.com/api/download-file/)", + type: "action", + props: { + luminPdf, + signatureRequestId: { + propDefinition: [ + luminPdf, + "signatureRequestId", + ], + }, + filePath: { + type: "string", + label: "File Path", + description: "The path to the file you'd like to download eg. `/tmp/file.pdf`", + }, + syncDir: { + type: "dir", + accessMode: "write", + sync: true, + }, + }, + async run({ $ }) { + const response = await this.luminPdf.downloadFile({ + $, + signatureRequestId: this.signatureRequestId, + responseType: "stream", + }); + + const pipeline = promisify(stream.pipeline); + await pipeline(response, fs.createWriteStream(this.filePath)); + + $.export("$summary", `Successfully downloaded file for signature request with ID: ${this.signatureRequestId}`); + return { + filePath: this.filePath, + }; + }, +}; diff --git a/components/lumin_pdf/actions/get-signature-request/get-signature-request.mjs b/components/lumin_pdf/actions/get-signature-request/get-signature-request.mjs new file mode 100644 index 0000000000000..68ff064ed5fdc --- /dev/null +++ b/components/lumin_pdf/actions/get-signature-request/get-signature-request.mjs @@ -0,0 +1,27 @@ +import luminPdf from "../../lumin_pdf.app.mjs"; + +export default { + key: "lumin_pdf-get-signature-request", + name: "Get Signature Request", + description: "Get details of a specific signature request. [See the documentation](https://developers.luminpdf.com/api/get-signature-request/)", + version: "0.0.1", + type: "action", + props: { + luminPdf, + signatureRequestId: { + propDefinition: [ + luminPdf, + "signatureRequestId", + ], + }, + }, + async run({ $ }) { + const response = await this.luminPdf.getSignatureRequest({ + $, + signatureRequestId: this.signatureRequestId, + }); + + $.export("$summary", `Successfully retrieved signature request with ID: ${this.signatureRequestId}`); + return response; + }, +}; diff --git a/components/lumin_pdf/actions/get-user-information/get-user-information.mjs b/components/lumin_pdf/actions/get-user-information/get-user-information.mjs new file mode 100644 index 0000000000000..823d078bb1e02 --- /dev/null +++ b/components/lumin_pdf/actions/get-user-information/get-user-information.mjs @@ -0,0 +1,20 @@ +import luminPdf from "../../lumin_pdf.app.mjs"; + +export default { + name: "Get User Information", + version: "0.0.1", + key: "lumin_pdf-get-user-information", + description: "Get information about the current authenticated user. [See the documentation](https://developers.luminpdf.com/api/get-user-information/)", + type: "action", + props: { + luminPdf, + }, + async run({ $ }) { + const response = await this.luminPdf.getUserInformation({ + $, + }); + + $.export("$summary", `Successfully retrieved user information for ${response.user.email || response.user.id}`); + return response; + }, +}; diff --git a/components/lumin_pdf/actions/send-signature-request/send-signature-request.mjs b/components/lumin_pdf/actions/send-signature-request/send-signature-request.mjs new file mode 100644 index 0000000000000..2e28037eede78 --- /dev/null +++ b/components/lumin_pdf/actions/send-signature-request/send-signature-request.mjs @@ -0,0 +1,194 @@ +import { + ConfigurationError, + getFileStreamAndMetadata, +} from "@pipedream/platform"; +import FormData from "form-data"; +import { parseObject } from "../../common/utils.mjs"; +import luminPdf from "../../lumin_pdf.app.mjs"; + +export default { + key: "lumin_pdf-send-signature-request", + name: "Send Signature Request", + description: "Send a signature request to signers. [See the documentation](https://developers.luminpdf.com/api/send-signature-request/)", + version: "0.0.1", + type: "action", + props: { + luminPdf, + fileUrl: { + type: "string", + label: "File URL", + description: "The URL of a single file to be downloaded and signed. This field is mutually exclusive with `file`, `files`, and `File URLs`. Only one of these fields should be provided in the request.", + optional: true, + }, + file: { + type: "string", + label: "File", + description: "A single path to a file in the `/tmp` directory (for example, `/tmp/myFile.pdf`) to be sent for signature. This field is mutually exclusive with `File URL`, `Files`, and `File URLs`. Only one of these fields should be provided in the request.", + optional: true, + }, + fileUrls: { + type: "string[]", + label: "File URLs", + description: "An array of URLs of files to be downloaded and signed. This field is mutually exclusive with `File`, `Files`, and `File URL`. Only one of these fields should be provided in the request.", + optional: true, + }, + files: { + type: "string[]", + label: "Files", + description: "An array of path to files in the `/tmp` directory (for example, `/tmp/myFile.pdf`) to be sent for signature. This field is mutually exclusive with `File URL`, `Files`, and `File URLs`. Only one of these fields should be provided in the request.", + optional: true, + }, + signers: { + type: "string[]", + label: "Signers", + description: "A list of objects of signers to add to your Signature Request. Format: `[{'email_address': 'email@example.com', 'name': 'John Doe', 'group': 1}, {'email_address': 'email2@example.com', 'name': 'Jane Doe', 'group': 2}]`. [See the documentation](https://developers.luminpdf.com/api/send-signature-request/) for more information.", + optional: true, + }, + viewers: { + type: "string[]", + label: "Viewers", + description: "A list of objects of viewers to add to your Signature Request. Format: `[{'email_address': 'email@example.com', 'name': 'John Doe'}, {'email_address': 'email2@example.com', 'name': 'Jane Doe'}]`. [See the documentation](https://developers.luminpdf.com/api/send-signature-request/) for more information.", + optional: true, + }, + title: { + type: "string", + label: "Title", + description: "The title you want to give the Signature Request.", + }, + expiresAt: { + type: "string", + label: "Expires At", + description: "When the Signature Request will expire. Should be later than today. In ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ).", + }, + useTextTags: { + type: "boolean", + label: "Use Text Tags", + description: "Set to `true` to enable Text Tag parsing in your document. Your Text Tags will be converted into UI components for the user to interact with.", + optional: true, + }, + signingType: { + type: "string", + label: "Signing Type", + description: "The signing order for the Signature Request.", + options: [ + "SAME_TIME", + "ORDER", + ], + optional: true, + }, + senderEmail: { + type: "string", + label: "Sender Email", + description: "The email address of the sender.", + optional: true, + }, + subject: { + type: "string", + label: "Subject", + description: "The subject of the email.", + optional: true, + }, + customEmailTitle: { + type: "string", + label: "Custom Email Title", + description: "The title of the email.", + optional: true, + }, + syncDir: { + type: "dir", + accessMode: "read", + sync: true, + optional: true, + }, + }, + methods: { + async appendFile(formData, fieldName, file) { + const { + stream, + metadata, + } = await getFileStreamAndMetadata(file); + formData.append(fieldName, stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + }, + }, + async run({ $ }) { + const formData = new FormData(); + const checkFiles = {}; + if (this.file) checkFiles.file = this.file; + if (this.files) checkFiles.files = this.files; + if (this.fileUrl) checkFiles.fileUrl = this.fileUrl; + if (this.fileUrls) checkFiles.fileUrls = this.fileUrls; + + if (Object.keys(checkFiles).length > 1) { + throw new ConfigurationError("Only one of `File URL`, `File`, `File URLs`, or `Files` should be provided in the request."); + } + if (Object.keys(checkFiles).length === 0) { + throw new ConfigurationError("At least one of `File URL`, `File`, `File URLs`, or `Files` should be provided in the request."); + } + + if (this.file) { + await this.appendFile(formData, "file", this.file); + } + if (this.files) { + for (const [ + index, + file, + ] of this.files.entries()) { + await this.appendFile(formData, `files[${index}]`, file); + } + } + if (this.fileUrl) { + formData.append("file_url", this.fileUrl); + } + if (this.fileUrls) { + for (const [ + index, + fileUrl, + ] of this.fileUrls.entries()) { + formData.append(`file_urls[${index}]`, fileUrl); + } + } + if (this.signers) { + for (const [ + index, + signer, + ] of parseObject(this.signers).entries()) { + for (const item of Object.keys(signer)) { + formData.append(`signers[${index}][${item}]`, signer[item]); + } + } + } + if (this.viewers) { + for (const [ + index, + viewer, + ] of parseObject(this.viewers).entries()) { + for (const item of Object.keys(viewer)) { + formData.append(`viewers[${index}][${item}]`, viewer[item]); + } + } + } + if (this.title) formData.append("title", this.title); + if (this.expiresAt) formData.append("expires_at", Date.parse(this.expiresAt)); + if (this.useTextTags) formData.append("use_text_tags", `${this.useTextTags}`); + if (this.signingType) formData.append("signing_type", this.signingType); + if (this.senderEmail) formData.append("custom_email[sender_email]", this.senderEmail); + if (this.senderEmail) formData.append("custom_email[subject_name]", this.subject); + if (this.senderEmail) formData.append("custom_email[title]", this.customEmailTitle); + + const response = await this.luminPdf.sendSignatureRequest({ + $, + headers: formData.getHeaders(), + data: formData, + }); + + if (response) { + $.export("$summary", `Successfully sent signature request ${response.signature_request.signature_request_id}`); + } + + return response; + }, +}; diff --git a/components/lumin_pdf/common/utils.mjs b/components/lumin_pdf/common/utils.mjs new file mode 100644 index 0000000000000..dcc9cc61f6f41 --- /dev/null +++ b/components/lumin_pdf/common/utils.mjs @@ -0,0 +1,24 @@ +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; +}; diff --git a/components/lumin_pdf/lumin_pdf.app.mjs b/components/lumin_pdf/lumin_pdf.app.mjs index 006e1b5c4541d..8003d137c2857 100644 --- a/components/lumin_pdf/lumin_pdf.app.mjs +++ b/components/lumin_pdf/lumin_pdf.app.mjs @@ -1,11 +1,79 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "lumin_pdf", - propDefinitions: {}, + propDefinitions: { + signatureRequestId: { + type: "string", + label: "Signature Request ID", + description: "The ID of the signature request", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.luminpdf.com/v1"; + }, + _headers(headers = {}) { + return { + "x-api-key": `${this.$auth.api_key}`, + ...headers, + }; + }, + _makeRequest({ + $ = this, path, headers, ...opts + }) { + return axios($, { + url: this._baseUrl() + path, + headers: this._headers(headers), + ...opts, + }); + }, + getSignatureRequest({ + signatureRequestId, ...opts + }) { + return this._makeRequest({ + path: `/signature_request/${signatureRequestId}`, + ...opts, + }); + }, + sendSignatureRequest(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/signature_request/send", + ...opts, + }); + }, + cancelSignatureRequest({ + signatureRequestId, ...opts + }) { + return this._makeRequest({ + method: "PUT", + path: `/signature_request/cancel/${signatureRequestId}`, + ...opts, + }); + }, + downloadFileAsFileUrl({ + signatureRequestId, ...opts + }) { + return this._makeRequest({ + path: `/signature_request/files_as_file_url/${signatureRequestId}`, + ...opts, + }); + }, + downloadFile({ + signatureRequestId, ...opts + }) { + return this._makeRequest({ + path: `/signature_request/files/${signatureRequestId}`, + ...opts, + }); + }, + getUserInformation(opts = {}) { + return this._makeRequest({ + path: "/user/info", + ...opts, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/lumin_pdf/package.json b/components/lumin_pdf/package.json index 65b66e0ba1207..3a93392fc8bcf 100644 --- a/components/lumin_pdf/package.json +++ b/components/lumin_pdf/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/lumin_pdf", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Lumin PDF Components", "main": "lumin_pdf.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cc47e0ae73ef7..0f9f24a83ddac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8132,7 +8132,11 @@ importers: specifier: ^3.0.0 version: 3.0.3 - components/lumin_pdf: {} + components/lumin_pdf: + dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 components/luminous: {} @@ -8392,8 +8396,7 @@ importers: specifier: ^1.2.1 version: 1.7.7 - components/matrix: - specifiers: {} + components/matrix: {} components/mattermost: dependencies: @@ -8777,8 +8780,7 @@ importers: components/minerstat: {} - components/minform: - specifiers: {} + components/minform: {} components/minio: {} @@ -9939,8 +9941,7 @@ importers: specifier: ^3.0.3 version: 3.0.3 - components/orufy_bookings: - specifiers: {} + components/orufy_bookings: {} components/ory: {} @@ -9966,8 +9967,7 @@ importers: specifier: ^1.2.0 version: 1.6.6 - components/outlign: - specifiers: {} + components/outlign: {} components/outline: {} @@ -12186,8 +12186,7 @@ importers: components/sap_s_4hana_cloud: {} - components/sap_s_4hana_cloud_sandbox: - specifiers: {} + components/sap_s_4hana_cloud_sandbox: {} components/sapling: {}