diff --git a/.github/workflows/pull-request-checks.yaml b/.github/workflows/pull-request-checks.yaml index 6a5a4168d12d2..ccb541c6d3dce 100644 --- a/.github/workflows/pull-request-checks.yaml +++ b/.github/workflows/pull-request-checks.yaml @@ -96,6 +96,8 @@ jobs: format: 'csv' # NOTE: These steps are kept in this workflow to avoid re-rerunning the rest of the lint job # in the Components Checks workflow + - name: Build TypeScript Components + run: pnpm build - name: Check component keys run: node scripts/findBadKeys.js ${{ steps.changed_files.outputs.added_modified }} ${{ steps.changed_files.outputs.renamed }} - name: Check component app prop diff --git a/components/api4ai/actions/alcohol-label-recognition/alcohol-label-recognition.mjs b/components/api4ai/actions/alcohol-label-recognition/alcohol-label-recognition.mjs index a5eeb2c6088e3..3d5a5fbf20b54 100644 --- a/components/api4ai/actions/alcohol-label-recognition/alcohol-label-recognition.mjs +++ b/components/api4ai/actions/alcohol-label-recognition/alcohol-label-recognition.mjs @@ -5,7 +5,7 @@ export default { name: "Alcohol Label Recognition", description: "Accurately identifies alcohol labels using advanced intelligent technologies. Powered by API4AI.", key: "api4ai-alcohol-label-recognition", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/actions/background-removal/background-removal.mjs b/components/api4ai/actions/background-removal/background-removal.mjs index dcc98d4e94659..9bad970f85682 100644 --- a/components/api4ai/actions/background-removal/background-removal.mjs +++ b/components/api4ai/actions/background-removal/background-removal.mjs @@ -8,7 +8,7 @@ export default { description: "Automatically and quickly remove image background with high accuracy. Powered by API4AI.", key: "api4ai-background-removal", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/actions/brand-recognition/brand-recognition.mjs b/components/api4ai/actions/brand-recognition/brand-recognition.mjs index efbd1c34edbcd..f910caa4457b9 100644 --- a/components/api4ai/actions/brand-recognition/brand-recognition.mjs +++ b/components/api4ai/actions/brand-recognition/brand-recognition.mjs @@ -5,7 +5,7 @@ export default { name: "Brand Recognition", description: "The service processes input image and responds with a list of found brand logos. Powered by API4AI.", key: "api4ai-brand-recognition", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/actions/car-image-background-removal/car-image-background-removal.mjs b/components/api4ai/actions/car-image-background-removal/car-image-background-removal.mjs index 34cc8d47b2d79..d85b2b9e1e64a 100644 --- a/components/api4ai/actions/car-image-background-removal/car-image-background-removal.mjs +++ b/components/api4ai/actions/car-image-background-removal/car-image-background-removal.mjs @@ -8,7 +8,7 @@ export default { description: "Remove Background for car images. Powered by API4AI.", key: "api4ai-car-image-background-removal", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/actions/furniture-and-household-item-recognition/furniture-and-household-item-recognition.mjs b/components/api4ai/actions/furniture-and-household-item-recognition/furniture-and-household-item-recognition.mjs index 317da1d924c38..6303b2c6e307f 100644 --- a/components/api4ai/actions/furniture-and-household-item-recognition/furniture-and-household-item-recognition.mjs +++ b/components/api4ai/actions/furniture-and-household-item-recognition/furniture-and-household-item-recognition.mjs @@ -5,7 +5,7 @@ export default { name: "Furniture & Household Item Recognition", description: "This API provides identification of furniture & household items with advanced intelligent detection, categorization, and counting technologies. Powered by API4AI.", key: "api4ai-furniture-and-household-item-recognition", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/actions/image-anonymization/image-anonymization.mjs b/components/api4ai/actions/image-anonymization/image-anonymization.mjs index f5d27a1dcb366..8225cc4beba1d 100644 --- a/components/api4ai/actions/image-anonymization/image-anonymization.mjs +++ b/components/api4ai/actions/image-anonymization/image-anonymization.mjs @@ -7,7 +7,7 @@ export default { name: "Image Anonymization", description: "Performs actual image anonymization. Powered by API4AI.", key: "api4ai-image-anonymization", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/actions/nsfw-image-recognition/nsfw-image-recognition.mjs b/components/api4ai/actions/nsfw-image-recognition/nsfw-image-recognition.mjs index eb2c2fa205d07..cb362ceb3fcc5 100644 --- a/components/api4ai/actions/nsfw-image-recognition/nsfw-image-recognition.mjs +++ b/components/api4ai/actions/nsfw-image-recognition/nsfw-image-recognition.mjs @@ -6,7 +6,7 @@ export default { description: "Content moderation solution for NSFW (Not Safe For Work) sexual images identification. Powered by API4AI.", key: "api4ai-nsfw-image-recognition", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/api4ai/api4ai.app.mjs b/components/api4ai/api4ai.app.mjs index a91436b79c894..3f897a6da9a04 100644 --- a/components/api4ai/api4ai.app.mjs +++ b/components/api4ai/api4ai.app.mjs @@ -1,6 +1,7 @@ -import { axios } from "@pipedream/platform"; +import { + axios, getFileStreamAndMetadata, +} from "@pipedream/platform"; import FormData from "form-data"; -import fs from "node:fs"; export default { type: "app", @@ -9,63 +10,22 @@ export default { image: { type: "string", label: "Image", - description: "Input image. Various types are accepted:\n * a **path** to a file\n * a **URL** to a file\n * a file's content encoded as a **base64** string\n * a file's content as a **Buffer** encoded in JSON\n * a file's content as an **Array** of bytes", + description: "Input image. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); - }, - - /** - * Make HTTP request. - * - * @param {Object} $ - Pipedream. - * @param {string} url - API Endpoint URL. - * @param {*} image - Input image. - * Various types are accepted: - * - a path to a file - * - a URL to a file - * - a file's content encoded as a base64 string - * - a file's content as a Buffer encoded in JSON - * - a file's content as an Array of bytes - * @param {Object} params - Query parameters. - * @returns Axios response. - */ async makeRequest($, url, image, params = {}) { // Prepare form data. - const base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; - const urlregex = /^(http|ftp)s?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/; const form = new FormData(); - if (urlregex.test(image)) { - console.log("Input image considered as URL"); - form.append("url", image); - } - else { - let buf; - if (image instanceof Buffer) { - console.log("Input image considered as Buffer"); - buf = image; - } - else if ((image instanceof Object) && image.type === "Buffer") { - console.log("Input image considered as JSON object with Buffer"); - buf = Buffer.from(image); - } - else if (image instanceof Array) { - console.log("Input image considered as Array"); - buf = Buffer.from(image); - } - else if (base64regex.test(image)) { - console.log("Input image considered as base64 string"); - buf = Buffer.from(image, "base64"); - } - else { - console.log("Input image considered as file path"); - buf = fs.readFileSync(image); - } - form.append("image", buf); - } + const { + stream, metadata, + } = await getFileStreamAndMetadata(image); + + form.append("image", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); // Prepare headers. const headers = { diff --git a/components/api4ai/package.json b/components/api4ai/package.json index 1b1f6e4a2c363..a2bd19fb03cb0 100644 --- a/components/api4ai/package.json +++ b/components/api4ai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/api4ai", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream API4AI Components", "main": "api4ai.app.mjs", "keywords": [ @@ -27,7 +27,7 @@ "homepage": "https://pipedream.com/apps/api4ai", "author": "API4AI Team (https://api4.ai/)", "dependencies": { - "@pipedream/platform": "^1.6.2", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0" }, "publishConfig": { diff --git a/components/dropbox/actions/upload-file/upload-file.mjs b/components/dropbox/actions/upload-file/upload-file.mjs index d7d4cb5821a05..99973faf40cd6 100644 --- a/components/dropbox/actions/upload-file/upload-file.mjs +++ b/components/dropbox/actions/upload-file/upload-file.mjs @@ -1,6 +1,4 @@ -import { ConfigurationError } from "@pipedream/platform"; -import fs from "fs"; -import got from "got"; +import { getFileStream } from "@pipedream/platform"; import consts from "../../common/consts.mjs"; import dropbox from "../../dropbox.app.mjs"; @@ -8,7 +6,7 @@ export default { name: "Upload a File", description: "Uploads a file to a selected folder. [See the documentation](https://dropbox.github.io/dropbox-sdk-js/Dropbox.html#filesUpload__anchor)", key: "dropbox-upload-file", - version: "0.0.14", + version: "1.0.0", type: "action", props: { dropbox, @@ -27,17 +25,10 @@ export default { label: "File Name", description: "The name of your new file (make sure to include the file extension).", }, - fileUrl: { - type: "string", - label: "File URL", - description: "The URL of the file you want to upload to Dropbox. Must specify either File URL or File Path.", - optional: true, - }, filePath: { type: "string", - label: "File Path", - description: "The path to the file, e.g. /tmp/myFile.csv . Must specify either File URL or File Path.", - optional: true, + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, autorename: { type: "boolean", @@ -67,7 +58,6 @@ export default { }, async run({ $ }) { const { - fileUrl, filePath, path, name, @@ -78,13 +68,7 @@ export default { clientModified, } = this; - if (!fileUrl && !filePath) { - throw new ConfigurationError("Must specify either File URL or File Path."); - } - - const contents = fileUrl - ? await got.stream(fileUrl) - : fs.createReadStream(filePath); + const contents = await getFileStream(filePath); let normalizedPath = this.dropbox.getNormalizedPath(path, true); diff --git a/components/dropbox/actions/upload-multiple-files/upload-multiple-files.mjs b/components/dropbox/actions/upload-multiple-files/upload-multiple-files.mjs index b1820b8e5deda..dd488f7abd106 100644 --- a/components/dropbox/actions/upload-multiple-files/upload-multiple-files.mjs +++ b/components/dropbox/actions/upload-multiple-files/upload-multiple-files.mjs @@ -1,6 +1,6 @@ -import { ConfigurationError } from "@pipedream/platform"; -import fs from "fs"; -import got from "got"; +import { + getFileStream, ConfigurationError, +} from "@pipedream/platform"; import consts from "../../common/consts.mjs"; import dropbox from "../../dropbox.app.mjs"; @@ -8,7 +8,7 @@ export default { name: "Upload Multiple Files", description: "Uploads multiple file to a selected folder. [See the documentation](https://dropbox.github.io/dropbox-sdk-js/Dropbox.html#filesUpload__anchor)", key: "dropbox-upload-multiple-files", - version: "0.0.2", + version: "1.0.0", type: "action", props: { dropbox, @@ -22,19 +22,10 @@ export default { ], description: "The folder to upload to. Type the folder name to search for it in the user's Dropbox.", }, - fileUrls: { + filesPaths: { type: "string[]", - label: "File URLs", - description: "The URLs of the files you want to upload to Dropbox. Must specify either File URLs or File Paths.", - default: [], - optional: true, - }, - filePaths: { - type: "string[]", - label: "File Paths", - description: "The paths to the files, e.g. /tmp/myFile.csv . Must specify either File URLs or File Paths.", - default: [], - optional: true, + label: "File Paths or URLs", + description: "Provide an array of either file URLs or paths to a files in the /tmp directory (for example, /tmp/myFile.pdf).", }, filenames: { type: "string[]", @@ -71,8 +62,7 @@ export default { const { dropbox, path, - fileUrls, - filePaths, + filesPaths, autorename, mute, strictConflict, @@ -80,11 +70,7 @@ export default { filenames, } = this; - if (!fileUrls?.length && !filePaths?.length) { - throw new ConfigurationError("Must specify either File URLs or File Paths."); - } - - const numFiles = fileUrls.length + filePaths.length; + const numFiles = filesPaths.length; if (numFiles !== filenames.length) { throw new ConfigurationError(`Number of filenames must match number of files. Detected ${numFiles} file(s) and ${filenames.length} filename(s)`); } @@ -93,24 +79,13 @@ export default { const normalizedPath = dropbox.getNormalizedPath(path, true); let i = 0; - if (fileUrls?.length) { - for (const url of fileUrls) { - fileInfo.push({ - contents: await got.stream(url), - path: `${normalizedPath}${filenames[i]}`, - }); - i++; - } - } - - if (filePaths?.length) { - for (const filePath of filePaths) { - fileInfo.push({ - contents: fs.createReadStream(filePath), - path: `${normalizedPath}${filenames[i]}`, - }); - i++; - } + for (const file of filesPaths) { + const contents = await getFileStream(file); + fileInfo.push({ + contents, + path: `${normalizedPath}${filenames[i]}`, + }); + i++; } const responses = []; diff --git a/components/dropbox/package.json b/components/dropbox/package.json index adc1d3c408d4d..85b8e5ad1ae3b 100644 --- a/components/dropbox/package.json +++ b/components/dropbox/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/dropbox", - "version": "0.4.1", + "version": "1.0.0", "description": "Pipedream Dropbox Components", "main": "dropbox.app.mjs", "keywords": [ @@ -10,6 +10,7 @@ "homepage": "https://pipedream.com/apps/dropbox", "author": "Pipedream (https://pipedream.com/)", "dependencies": { + "@pipedream/platform": "^3.1.0", "@types/node-fetch": "^2.5.7", "dropbox": "^10.34.0", "got": "^13.0.0", diff --git a/components/elevenlabs/actions/add-voice/add-voice.mjs b/components/elevenlabs/actions/add-voice/add-voice.mjs index 47c71f4a74c7f..a0445433d3d10 100644 --- a/components/elevenlabs/actions/add-voice/add-voice.mjs +++ b/components/elevenlabs/actions/add-voice/add-voice.mjs @@ -1,11 +1,11 @@ import FormData from "form-data"; -import fs from "fs"; import elevenlabs from "../../elevenlabs.app.mjs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { key: "elevenlabs-add-voice", name: "Add Voice", - version: "0.0.3", + version: "0.0.4", description: "Add a voice from one or more audio files. [See the documentation](https://elevenlabs.io/docs/api-reference/add-voice)", type: "action", props: { @@ -17,8 +17,8 @@ export default { }, files: { type: "string[]", - label: "Files", - description: "One or more audio files (in the `/tmp` folder) to clone the voice from. Example: `/tmp/voice.mp3`", + label: "File Paths or URLs", + description: "Provide either an array of file URLs or an array of paths to a files in the /tmp directory (for example, /tmp/myFile.pdf).", }, description: { type: "string", @@ -45,10 +45,16 @@ export default { const data = new FormData(); if (description) data.append("description", description); - files.forEach((file) => { - data.append("files", fs.createReadStream(file.includes("tmp/") - ? file - : `/tmp/${file}`));}); + for (const file of files) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); + data.append("files", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } if (labels) data.append("labels", labels); data.append("name", name); diff --git a/components/elevenlabs/package.json b/components/elevenlabs/package.json index d030ccb3d752e..5a0f210162351 100644 --- a/components/elevenlabs/package.json +++ b/components/elevenlabs/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/elevenlabs", - "version": "0.4.0", + "version": "0.4.1", "description": "Pipedream ElevenLabs Components", "main": "elevenlabs.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.3", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0" } } diff --git a/components/google_drive/actions/upload-file/upload-file.mjs b/components/google_drive/actions/upload-file/upload-file.mjs index 2c8853e3b8d6c..35c3b3a39f0e5 100644 --- a/components/google_drive/actions/upload-file/upload-file.mjs +++ b/components/google_drive/actions/upload-file/upload-file.mjs @@ -12,7 +12,7 @@ export default { key: "google_drive-upload-file", name: "Upload File", description: "Upload a file to Google Drive. [See the documentation](https://developers.google.com/drive/api/v3/manage-uploads) for more information", - version: "2.0.0", + version: "2.0.1", type: "action", props: { googleDrive, @@ -36,10 +36,9 @@ export default { optional: true, }, filePath: { - propDefinition: [ - googleDrive, - "filePath", - ], + type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, name: { propDefinition: [ diff --git a/components/google_drive/package.json b/components/google_drive/package.json index 3f87f45339ae3..7786c49e54095 100644 --- a/components/google_drive/package.json +++ b/components/google_drive/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/google_drive", - "version": "1.0.0", + "version": "1.0.1", "description": "Pipedream Google_drive Components", "main": "google_drive.app.mjs", "keywords": [ diff --git a/components/jira/actions/add-attachment-to-issue/add-attachment-to-issue.mjs b/components/jira/actions/add-attachment-to-issue/add-attachment-to-issue.mjs index 473bfbdd01053..7a9ce35b1716c 100644 --- a/components/jira/actions/add-attachment-to-issue/add-attachment-to-issue.mjs +++ b/components/jira/actions/add-attachment-to-issue/add-attachment-to-issue.mjs @@ -1,14 +1,12 @@ -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import FormData from "form-data"; -import fs from "fs"; -import utils from "../../common/utils.mjs"; import jira from "../../jira.app.mjs"; export default { key: "jira-add-attachment-to-issue", name: "Add Attachment To Issue", description: "Adds an attachment to an issue, [See the docs](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-attachments/#api-rest-api-3-issue-issueidorkey-attachments-post)", - version: "0.2.11", + version: "1.0.0", type: "action", props: { jira, @@ -27,23 +25,26 @@ export default { }), ], }, - filename: { + file: { type: "string", - label: "File name", - description: "Path of the file in /tmp folder to add as an attachment. To upload a file to /tmp folder, please follow the [doc here](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, }, async run({ $ }) { const data = new FormData(); - const path = utils.checkTmp(this.filename); - if (!fs.existsSync(path)) { - throw new ConfigurationError("File does not exist!"); - } - const file = fs.createReadStream(path); - const stats = fs.statSync(path); - data.append("file", file, { - knownLength: stats.size, + const file = this.file; + + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); + + data .append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, }); + const headers = { "Content-Type": `multipart/form-data; boundary=${data._boundary}`, "X-Atlassian-Token": "no-check", diff --git a/components/jira/actions/add-multiple-attachments-to-issue/add-multiple-attachments-to-issue.mjs b/components/jira/actions/add-multiple-attachments-to-issue/add-multiple-attachments-to-issue.mjs index 940407a16f5df..e0d8e3f50905a 100644 --- a/components/jira/actions/add-multiple-attachments-to-issue/add-multiple-attachments-to-issue.mjs +++ b/components/jira/actions/add-multiple-attachments-to-issue/add-multiple-attachments-to-issue.mjs @@ -1,14 +1,12 @@ -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import FormData from "form-data"; -import fs from "fs"; -import utils from "../../common/utils.mjs"; import jira from "../../jira.app.mjs"; export default { key: "jira-add-multiple-attachments-to-issue", name: "Add Multiple Attachments To Issue", description: "Adds multiple attachments to an issue, [See the docs](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-attachments/#api-rest-api-3-issue-issueidorkey-attachments-post)", - version: "0.0.9", + version: "1.0.0", type: "action", props: { jira, @@ -27,39 +25,26 @@ export default { }), ], }, - filenames: { + files: { type: "string[]", - label: "File names", - description: "Array of file paths in `/tmp` folder to add as attachments. To upload a file to `/tmp` folder, please follow the [doc here](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + label: "File Paths or URLs", + description: "Provide either an array of file URLs or paths to files in the /tmp directory (for example, /tmp/myFile.pdf).", }, }, async run({ $ }) { const responses = []; - //validate all files exist before processing - const not_found = []; - for (let i = 0; i < this.filenames.length; i++) { - const path = utils.checkTmp(this.filenames[i]); - if (!fs.existsSync(path)) { - not_found.push(path); - } - } - - if (not_found.length > 0) { - // eslint-disable-next-line multiline-ternary - throw new ConfigurationError(`File${not_found.length > 1 ? "s" : ""} not found: ${not_found.join(", ")}`); - } - - //all files exist - let's process them - for (let i = 0; i < this.filenames.length; i++) { - const filename = this.filenames[i]; + for (let i = 0; i < this.files.length; i++) { + const file = this.files[i]; const data = new FormData(); - const path = utils.checkTmp(filename); - const file = fs.createReadStream(path); - const stats = fs.statSync(path); + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); - data.append("file", file, { - knownLength: stats.size, + data.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, }); const headers = { diff --git a/components/jira/package.json b/components/jira/package.json index 5339a48c78ff3..478ccaa3258cf 100644 --- a/components/jira/package.json +++ b/components/jira/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/jira", - "version": "0.2.0", + "version": "1.0.0", "description": "Pipedream Jira Components", "main": "jira.app.mjs", "keywords": [ @@ -10,7 +10,7 @@ "homepage": "https://pipedream.com/apps/jira", "author": "Pipedream (https://pipedream.com/)", "dependencies": { - "@pipedream/platform": "^3.0.1", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0" }, "publishConfig": { diff --git a/components/microsoft_outlook/actions/add-label-to-email/add-label-to-email.mjs b/components/microsoft_outlook/actions/add-label-to-email/add-label-to-email.mjs index 45b0dceb9b250..6b5ce5b3bd8e5 100644 --- a/components/microsoft_outlook/actions/add-label-to-email/add-label-to-email.mjs +++ b/components/microsoft_outlook/actions/add-label-to-email/add-label-to-email.mjs @@ -5,7 +5,7 @@ export default { key: "microsoft_outlook-add-label-to-email", name: "Add Label to Email", description: "Adds a label/category to an email in Microsoft Outlook. [See the documentation](https://learn.microsoft.com/en-us/graph/api/message-update)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/approve-workflow/approve-workflow.mjs b/components/microsoft_outlook/actions/approve-workflow/approve-workflow.mjs index 7abbc9b8adaf9..2ab42b00d3781 100644 --- a/components/microsoft_outlook/actions/approve-workflow/approve-workflow.mjs +++ b/components/microsoft_outlook/actions/approve-workflow/approve-workflow.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-approve-workflow", name: "Approve Workflow", description: "Suspend the workflow until approved by email. [See the documentation](https://pipedream.com/docs/code/nodejs/rerun#flowsuspend)", - version: "0.0.4", + version: "0.0.5", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/create-contact/create-contact.mjs b/components/microsoft_outlook/actions/create-contact/create-contact.mjs index 3ca74216de1d6..8ec5af30b2dfd 100644 --- a/components/microsoft_outlook/actions/create-contact/create-contact.mjs +++ b/components/microsoft_outlook/actions/create-contact/create-contact.mjs @@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook.app.mjs"; export default { type: "action", key: "microsoft_outlook-create-contact", - version: "0.0.13", + version: "0.0.14", name: "Create Contact", description: "Add a contact to the root Contacts folder, [See the documentation](https://docs.microsoft.com/en-us/graph/api/user-post-contacts)", props: { diff --git a/components/microsoft_outlook/actions/create-draft-email/create-draft-email.mjs b/components/microsoft_outlook/actions/create-draft-email/create-draft-email.mjs index 739c3fef06f16..4e11d7e92d70b 100644 --- a/components/microsoft_outlook/actions/create-draft-email/create-draft-email.mjs +++ b/components/microsoft_outlook/actions/create-draft-email/create-draft-email.mjs @@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook.app.mjs"; export default { type: "action", key: "microsoft_outlook-create-draft-email", - version: "0.0.13", + version: "0.0.14", name: "Create Draft Email", description: "Create a draft email, [See the documentation](https://docs.microsoft.com/en-us/graph/api/user-post-messages)", props: { diff --git a/components/microsoft_outlook/actions/download-attachment/download-attachment.mjs b/components/microsoft_outlook/actions/download-attachment/download-attachment.mjs index 68381ba5345b2..cf9cbe1089221 100644 --- a/components/microsoft_outlook/actions/download-attachment/download-attachment.mjs +++ b/components/microsoft_outlook/actions/download-attachment/download-attachment.mjs @@ -6,7 +6,7 @@ export default { key: "microsoft_outlook-download-attachment", name: "Download Attachment", description: "Downloads an attachment to the /tmp directory. [See the documentation](https://learn.microsoft.com/en-us/graph/api/attachment-get?view=graph-rest-1.0&tabs=http)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/find-contacts/find-contacts.mjs b/components/microsoft_outlook/actions/find-contacts/find-contacts.mjs index 2d0ac938d84d6..a52ebd3378ec1 100644 --- a/components/microsoft_outlook/actions/find-contacts/find-contacts.mjs +++ b/components/microsoft_outlook/actions/find-contacts/find-contacts.mjs @@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook.app.mjs"; export default { type: "action", key: "microsoft_outlook-find-contacts", - version: "0.0.13", + version: "0.0.14", name: "Find Contacts", description: "Finds contacts with the given search string. [See the documentation](https://docs.microsoft.com/en-us/graph/api/user-list-contacts)", props: { diff --git a/components/microsoft_outlook/actions/find-email/find-email.mjs b/components/microsoft_outlook/actions/find-email/find-email.mjs index 0163c31c4474b..c812f83f87552 100644 --- a/components/microsoft_outlook/actions/find-email/find-email.mjs +++ b/components/microsoft_outlook/actions/find-email/find-email.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-find-email", name: "Find Email", description: "Search for an email in Microsoft Outlook. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-list-messages)", - version: "0.0.4", + version: "0.0.5", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/list-contacts/list-contacts.mjs b/components/microsoft_outlook/actions/list-contacts/list-contacts.mjs index a9e19ba61fff8..f57414f97cdc0 100644 --- a/components/microsoft_outlook/actions/list-contacts/list-contacts.mjs +++ b/components/microsoft_outlook/actions/list-contacts/list-contacts.mjs @@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook.app.mjs"; export default { type: "action", key: "microsoft_outlook-list-contacts", - version: "0.0.13", + version: "0.0.14", name: "List Contacts", description: "Get a contact collection from the default contacts folder, [See the documentation](https://docs.microsoft.com/en-us/graph/api/user-list-contacts)", props: { diff --git a/components/microsoft_outlook/actions/list-folders/list-folders.mjs b/components/microsoft_outlook/actions/list-folders/list-folders.mjs index 2ebe2d0b58fd8..4fa8d51dd9959 100644 --- a/components/microsoft_outlook/actions/list-folders/list-folders.mjs +++ b/components/microsoft_outlook/actions/list-folders/list-folders.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-list-folders", name: "List Folders", description: "Retrieves a list of all folders in Microsoft Outlook. [See the documentation](https://learn.microsoft.com/en-us/graph/api/user-list-mailfolders)", - version: "0.0.4", + version: "0.0.5", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/list-labels/list-labels.mjs b/components/microsoft_outlook/actions/list-labels/list-labels.mjs index bec17bb4d6098..7fc3a9d5ed2ba 100644 --- a/components/microsoft_outlook/actions/list-labels/list-labels.mjs +++ b/components/microsoft_outlook/actions/list-labels/list-labels.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-list-labels", name: "List Labels", description: "Get all the labels/categories that have been defined for a user. [See the documentation](https://learn.microsoft.com/en-us/graph/api/outlookuser-list-mastercategories)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/move-email-to-folder/move-email-to-folder.mjs b/components/microsoft_outlook/actions/move-email-to-folder/move-email-to-folder.mjs index 59a6e0838fcc2..a78052bd41e48 100644 --- a/components/microsoft_outlook/actions/move-email-to-folder/move-email-to-folder.mjs +++ b/components/microsoft_outlook/actions/move-email-to-folder/move-email-to-folder.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-move-email-to-folder", name: "Move Email to Folder", description: "Moves an email to the specified folder in Microsoft Outlook. [See the documentation](https://learn.microsoft.com/en-us/graph/api/message-move)", - version: "0.0.4", + version: "0.0.5", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/remove-label-from-email/remove-label-from-email.mjs b/components/microsoft_outlook/actions/remove-label-from-email/remove-label-from-email.mjs index 0fb2bcb78345d..f4e9bd5c198fd 100644 --- a/components/microsoft_outlook/actions/remove-label-from-email/remove-label-from-email.mjs +++ b/components/microsoft_outlook/actions/remove-label-from-email/remove-label-from-email.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-remove-label-from-email", name: "Remove Label from Email", description: "Removes a label/category from an email in Microsoft Outlook. [See the documentation](https://learn.microsoft.com/en-us/graph/api/message-update)", - version: "0.0.6", + version: "0.0.7", type: "action", props: { microsoftOutlook, diff --git a/components/microsoft_outlook/actions/reply-to-email/reply-to-email.mjs b/components/microsoft_outlook/actions/reply-to-email/reply-to-email.mjs index b87a4e06f69a5..34323f797ae9b 100644 --- a/components/microsoft_outlook/actions/reply-to-email/reply-to-email.mjs +++ b/components/microsoft_outlook/actions/reply-to-email/reply-to-email.mjs @@ -4,7 +4,7 @@ export default { key: "microsoft_outlook-reply-to-email", name: "Reply to Email", description: "Reply to an email in Microsoft Outlook. [See the documentation](https://learn.microsoft.com/en-us/graph/api/message-reply)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { microsoftOutlook, @@ -67,7 +67,7 @@ export default { data: { comment: this.comment, message: { - ...this.microsoftOutlook.prepareMessageBody(this), + ...await this.microsoftOutlook.prepareMessageBody(this), ...this.expand, }, }, diff --git a/components/microsoft_outlook/actions/send-email/send-email.mjs b/components/microsoft_outlook/actions/send-email/send-email.mjs index cb58c9c94db4f..9cc2a8c1b2b3e 100644 --- a/components/microsoft_outlook/actions/send-email/send-email.mjs +++ b/components/microsoft_outlook/actions/send-email/send-email.mjs @@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook.app.mjs"; export default { type: "action", key: "microsoft_outlook-send-email", - version: "0.0.14", + version: "0.0.15", name: "Send Email", description: "Send an email to one or multiple recipients, [See the docs](https://docs.microsoft.com/en-us/graph/api/user-sendmail)", props: { @@ -63,7 +63,7 @@ export default { $, data: { message: { - ...this.microsoftOutlook.prepareMessageBody(this), + ...await this.microsoftOutlook.prepareMessageBody(this), ...this.expand, }, }, diff --git a/components/microsoft_outlook/actions/update-contact/update-contact.mjs b/components/microsoft_outlook/actions/update-contact/update-contact.mjs index ec7569c648bb4..5f04826e6f913 100644 --- a/components/microsoft_outlook/actions/update-contact/update-contact.mjs +++ b/components/microsoft_outlook/actions/update-contact/update-contact.mjs @@ -3,7 +3,7 @@ import microsoftOutlook from "../../microsoft_outlook.app.mjs"; export default { type: "action", key: "microsoft_outlook-update-contact", - version: "0.0.13", + version: "0.0.14", name: "Update Contact", description: "Add a contact to the root Contacts folder, [See the docs](https://docs.microsoft.com/en-us/graph/api/user-post-contacts)", props: { diff --git a/components/microsoft_outlook/microsoft_outlook.app.mjs b/components/microsoft_outlook/microsoft_outlook.app.mjs index d46c01ff3c3d4..ec64ce7893b9f 100644 --- a/components/microsoft_outlook/microsoft_outlook.app.mjs +++ b/components/microsoft_outlook/microsoft_outlook.app.mjs @@ -1,7 +1,7 @@ -import { axios } from "@pipedream/platform"; -import fs from "fs"; +import { + axios, getFileStream, +} from "@pipedream/platform"; import path from "path"; -import { encode } from "js-base64"; import mime from "mime-types"; const DEFAULT_LIMIT = 50; @@ -54,9 +54,9 @@ export default { optional: true, }, files: { - label: "File paths", - description: "Absolute paths to the files (eg. `/tmp/my_file.pdf`)", type: "string[]", + label: "File Paths or URLs", + description: "Provide either an array of file URLs or an array of paths to a files in the /tmp directory (for example, /tmp/myFile.pdf).", optional: true, }, contact: { @@ -253,7 +253,19 @@ export default { ...args, }); }, - prepareMessageBody(self) { + async streamToBase64(stream) { + return new Promise((resolve, reject) => { + const chunks = []; + + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => { + const buffer = Buffer.concat(chunks); + resolve(buffer.toString("base64")); + }); + stream.on("error", reject); + }); + }, + async prepareMessageBody(self) { const toRecipients = []; const ccRecipients = []; const bccRecipients = []; @@ -285,15 +297,13 @@ export default { const attachments = []; for (let i = 0; self.files && i < self.files.length; i++) { + const stream = await getFileStream(self.files[i]); + const base64 = await this.streamToBase64(stream); attachments.push({ "@odata.type": "#microsoft.graph.fileAttachment", "name": path.basename(self.files[i]), "contentType": mime.lookup(self.files[i]), - "contentBytes": encode([ - ...fs.readFileSync(self.files[i], { - flag: "r", - }).values(), - ]), + "contentBytes": base64, }); } const message = { diff --git a/components/microsoft_outlook/package.json b/components/microsoft_outlook/package.json index 10435130a43eb..218d898ac8380 100644 --- a/components/microsoft_outlook/package.json +++ b/components/microsoft_outlook/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/microsoft_outlook", - "version": "1.5.0", + "version": "1.5.1", "description": "Pipedream Microsoft Outlook Components", "main": "microsoft_outlook.app.mjs", "keywords": [ @@ -12,7 +12,7 @@ "homepage": "https://pipedream.com/apps/microsoft_outlook", "author": "Pipedream (https://pipedream.com/)", "dependencies": { - "@pipedream/platform": "^3.0.3", + "@pipedream/platform": "^3.1.0", "axios": "^0.21.1", "js-base64": "^3.7.2", "md5": "^2.3.0", diff --git a/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs b/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs index 4e194afb6e2b7..3dd0c5354149d 100644 --- a/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs +++ b/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs @@ -5,7 +5,7 @@ export default { key: "microsoft_outlook-new-attachment-received", name: "New Attachment Received (Instant)", description: "Emit new event when a new email containing one or more attachments arrives in a specified Microsoft Outlook folder.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/microsoft_outlook/sources/new-contact/new-contact.mjs b/components/microsoft_outlook/sources/new-contact/new-contact.mjs index 719b5bb49be63..94e9dbe808d0f 100644 --- a/components/microsoft_outlook/sources/new-contact/new-contact.mjs +++ b/components/microsoft_outlook/sources/new-contact/new-contact.mjs @@ -5,7 +5,7 @@ export default { key: "microsoft_outlook-new-contact", name: "New Contact Event (Instant)", description: "Emit new event when a new Contact is created", - version: "0.0.14", + version: "0.0.15", type: "source", hooks: { ...common.hooks, diff --git a/components/microsoft_outlook/sources/new-email/new-email.mjs b/components/microsoft_outlook/sources/new-email/new-email.mjs index 5d6b6ce84531e..4eb69d3bb3fe4 100644 --- a/components/microsoft_outlook/sources/new-email/new-email.mjs +++ b/components/microsoft_outlook/sources/new-email/new-email.mjs @@ -7,7 +7,7 @@ export default { key: "microsoft_outlook-new-email", name: "New Email Event (Instant)", description: "Emit new event when an email is received in specified folders.", - version: "0.0.17", + version: "0.0.18", type: "source", dedupe: "unique", methods: { diff --git a/components/speechace/actions/score-scripted-recording/score-scripted-recording.mjs b/components/speechace/actions/score-scripted-recording/score-scripted-recording.mjs index 331855762a23c..82b64d1c3f08e 100644 --- a/components/speechace/actions/score-scripted-recording/score-scripted-recording.mjs +++ b/components/speechace/actions/score-scripted-recording/score-scripted-recording.mjs @@ -1,12 +1,14 @@ import speechace from "../../speechace.app.mjs"; import FormData from "form-data"; -import fs from "fs"; +import { + getFileStreamAndMetadata, ConfigurationError, +} from "@pipedream/platform"; export default { key: "speechace-score-scripted-recording", name: "Score Scripted Recording", description: "Scores a scripted recording based on fluency and pronunciation. [See the documentation](https://docs.speechace.com/#c34b11dd-8172-441a-bc27-223339d48d8e)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { speechace, @@ -42,10 +44,14 @@ export default { }, async run({ $ }) { const data = new FormData(); - const content = fs.createReadStream(this.filePath.includes("tmp/") - ? this.filePath - : `/tmp/${this.filePath}`); - data.append("user_audio_file", content); + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.filePath); + data.append("user_audio_file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); if (this.text) { data.append("text", this.text); } @@ -62,6 +68,9 @@ export default { data, headers: data.getHeaders(), }); + if (response.status === "error") { + throw new ConfigurationError(response.detail_message); + } $.export("$summary", `Scored scripted recording for audio file: ${this.filePath}`); return response; }, diff --git a/components/speechace/actions/transcribe-and-score-recording/transcribe-and-score-recording.mjs b/components/speechace/actions/transcribe-and-score-recording/transcribe-and-score-recording.mjs index c78b2e888e2b0..f9d4d64b14fec 100644 --- a/components/speechace/actions/transcribe-and-score-recording/transcribe-and-score-recording.mjs +++ b/components/speechace/actions/transcribe-and-score-recording/transcribe-and-score-recording.mjs @@ -1,12 +1,14 @@ import speechace from "../../speechace.app.mjs"; import FormData from "form-data"; -import fs from "fs"; +import { + getFileStreamAndMetadata, ConfigurationError, +} from "@pipedream/platform"; export default { key: "speechace-transcribe-and-score-recording", name: "Transcribe and Score Recording", description: "Transcribes and scores a provided speech recording. [See the documentation](https://docs.speechace.com/#76089b5d-7e25-4744-8d32-f6c230acf217)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { speechace, @@ -37,10 +39,14 @@ export default { }, async run({ $ }) { const data = new FormData(); - const content = fs.createReadStream(this.filePath.includes("tmp/") - ? this.filePath - : `/tmp/${this.filePath}`); - data.append("user_audio_file", content); + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.filePath); + data.append("user_audio_file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); if (this.relevanceContext) { data.append("relevance_context", this.relevanceContext); } @@ -54,6 +60,9 @@ export default { data, headers: data.getHeaders(), }); + if (response.status === "error") { + throw new ConfigurationError(response.detail_message); + } $.export("$summary", `Transcription and scoring completed for audio file: ${this.filePath}`); return response; }, diff --git a/components/speechace/package.json b/components/speechace/package.json index 8d4c0088e1bfa..7aa7538039c5d 100644 --- a/components/speechace/package.json +++ b/components/speechace/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/speechace", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream Speechace Components", "main": "speechace.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^2.0.0", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0" } } diff --git a/components/speechace/speechace.app.mjs b/components/speechace/speechace.app.mjs index 710f6afd22ae8..b1aff064ed561 100644 --- a/components/speechace/speechace.app.mjs +++ b/components/speechace/speechace.app.mjs @@ -23,8 +23,8 @@ export default { }, filePath: { type: "string", - label: "File Path", - description: "The path to an audio file (wav, mp3, m4a, webm, ogg, aiff) in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, userId: { type: "string", diff --git a/components/spotlightr/actions/create-video/create-video.mjs b/components/spotlightr/actions/create-video/create-video.mjs index a1a0dc5aad8de..9ad5095f8e547 100644 --- a/components/spotlightr/actions/create-video/create-video.mjs +++ b/components/spotlightr/actions/create-video/create-video.mjs @@ -1,22 +1,19 @@ -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import FormData from "form-data"; -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; import spotlightr from "../../spotlightr.app.mjs"; export default { key: "spotlightr-create-video", name: "Create Video", - version: "0.0.1", + version: "1.0.0", description: "Create a video in an application. [See the documentation](https://app.spotlightr.com/docs/api/#create-video)", type: "action", props: { spotlightr, - url: { + file: { type: "string", - label: "URL", - description: "The video URL. `You must provide at least the URL or File.`", - optional: true, + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, name: { type: "string", @@ -74,65 +71,44 @@ export default { description: "Video ID for coping playerSettings (decoded base64)", optional: true, }, - file: { - type: "string", - label: "File", - description: "Full path to the file in `/tmp/` directory. E.g. `/tmp/video.mp4`. `You must provide at least the URL or File.`", - optional: true, - }, }, async run({ $ }) { const { spotlightr, - url, file, ...data } = this; - if (!file && !url) { - throw new ConfigurationError("You must provide at least the URL or File."); - } - - let preparedData = {}; - if (file) { - const formData = new FormData(); - - const path = checkTmp(file); - if (!fs.existsSync(path)) { - throw new ConfigurationError("File does not exist!"); - } - - formData.append("file", fs.createReadStream(path)); - for (const [ - key, - value, - ] of Object.entries(data)) { - formData.append(key, value); - } + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); - preparedData = { - formDataRequest: true, - headers: formData.getHeaders(), - data: formData, - }; + const formData = new FormData(); - } else { - preparedData = { - data: { - URL: url, - ...data, - }, - }; + formData.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + for (const [ + key, + value, + ] of Object.entries(data)) { + formData.append(key, value); } + const preparedData = { + formDataRequest: true, + headers: formData.getHeaders(), + data: formData, + }; + const response = await spotlightr.createVideo({ $, ...preparedData, }); - $.export("$summary", `A new video with ${response.data - ? `URL: ${response.data}` - : `Id: ${response}`} was successfully created!`); + $.export("$summary", "New video successfully created!"); return response.data || response; }, }; diff --git a/components/spotlightr/package.json b/components/spotlightr/package.json index d61745dce68b8..008f1e0c66873 100644 --- a/components/spotlightr/package.json +++ b/components/spotlightr/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/spotlightr", - "version": "0.1.0", + "version": "1.0.0", "description": "Pipedream Spotlightr Components", "main": "spotlightr.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.5.1", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0", "fs": "^0.0.1-security" } diff --git a/components/supabase/actions/batch-insert-rows/batch-insert-rows.mjs b/components/supabase/actions/batch-insert-rows/batch-insert-rows.mjs index 8a32b0bfff576..4469986915554 100644 --- a/components/supabase/actions/batch-insert-rows/batch-insert-rows.mjs +++ b/components/supabase/actions/batch-insert-rows/batch-insert-rows.mjs @@ -1,12 +1,12 @@ import supabase from "../../supabase.app.mjs"; -import fs from "fs"; import { parse } from "csv-parse/sync"; +import { getFileStream } from "@pipedream/platform"; export default { key: "supabase-batch-insert-rows", name: "Batch Insert Rows", description: "Inserts new rows into a database. [See the documentation](https://supabase.com/docs/reference/javascript/insert)", - version: "0.0.2", + version: "0.0.3", type: "action", props: { supabase, @@ -40,8 +40,8 @@ export default { if (this.source === "CSV File") { props.filePath = { type: "string", - label: "File Path", - description: "The path to a csv file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }; } return props; @@ -59,20 +59,30 @@ export default { return JSON.parse(arr); } }, - getRowsFromCSV(filePath) { - const fileContent = fs.readFileSync(filePath.includes("tmp/") - ? filePath - : `/tmp/${filePath}`, "utf-8"); + async getRowsFromCSV(filePath) { + const stream = await getFileStream(filePath); + const fileContent = await this.streamToUtf8(stream); const rows = parse(fileContent, { columns: true, skip_empty_lines: true, }); return rows; }, + async streamToUtf8(stream) { + return new Promise((resolve, reject) => { + let data = ""; + + stream.setEncoding("utf-8"); + + stream.on("data", (chunk) => data += chunk); + stream.on("end", () => resolve(data)); + stream.on("error", reject); + }); + }, }, async run({ $ }) { const data = this.source === "CSV File" - ? this.getRowsFromCSV(this.filePath) + ? await this.getRowsFromCSV(this.filePath) : this.parseArray(this.data); const response = await this.supabase.insertRow(this.table, data); diff --git a/components/supabase/package.json b/components/supabase/package.json index e9e5c466121e1..a7dc685f9a584 100644 --- a/components/supabase/package.json +++ b/components/supabase/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/supabase", - "version": "0.3.1", + "version": "0.3.2", "description": "Pipedream Supabase Components", "main": "supabase.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.3", + "@pipedream/platform": "^3.1.0", "@supabase/supabase-js": "^2.45.6", "csv-parse": "^5.5.6" } diff --git a/components/syncmate_by_assitro/actions/send-bulk-messages/send-bulk-messages.mjs b/components/syncmate_by_assitro/actions/send-bulk-messages/send-bulk-messages.mjs index 6a3f30cbe4f8c..b42311e20fd31 100644 --- a/components/syncmate_by_assitro/actions/send-bulk-messages/send-bulk-messages.mjs +++ b/components/syncmate_by_assitro/actions/send-bulk-messages/send-bulk-messages.mjs @@ -1,13 +1,14 @@ -import { ConfigurationError } from "@pipedream/platform"; -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; +import { + getFileStream, ConfigurationError, +} from "@pipedream/platform"; +import { streamToBuffer } from "../../common/utils.mjs"; import syncmateByAssitro from "../../syncmate_by_assitro.app.mjs"; export default { key: "syncmate_by_assitro-send-bulk-messages", name: "Send Bulk Messages", description: "Send multiple WhatsApp messages in bulk. [See the documentation](https://assistro.co/user-guide/bulk-messaging-at-a-scheduled-time-using-syncmate-2/)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { syncmateByAssitro, @@ -34,7 +35,7 @@ export default { props[`media${i}`] = { type: "string", label: `Media ${i}`, - description: "The the path to a file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", optional: true, }; props[`fileName${i}`] = { @@ -60,12 +61,12 @@ export default { }; if (this[`media${i}`]) { - const file = fs.readFileSync(checkTmp(this[`media${i}`]), { - encoding: "base64", - }); + const stream = await getFileStream(this[`media${i}`]); + const buffer = await streamToBuffer(stream); + const base64 = buffer.toString("base64"); data.media = [ { - media_base64: file, + media_base64: base64, file_name: this[`fileName${i}`], }, ]; diff --git a/components/syncmate_by_assitro/actions/send-message/send-message.mjs b/components/syncmate_by_assitro/actions/send-message/send-message.mjs index d8fa92bd1ffc7..37732ab0326c6 100644 --- a/components/syncmate_by_assitro/actions/send-message/send-message.mjs +++ b/components/syncmate_by_assitro/actions/send-message/send-message.mjs @@ -1,13 +1,14 @@ -import { ConfigurationError } from "@pipedream/platform"; -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; +import { streamToBuffer } from "../../common/utils.mjs"; import syncmateByAssitro from "../../syncmate_by_assitro.app.mjs"; +import { + getFileStream, ConfigurationError, +} from "@pipedream/platform"; export default { key: "syncmate_by_assitro-send-message", name: "Send WhatsApp Message", description: "Send a single WhatsApp message using SyncMate by Assistro. [See the documentation](https://assistro.co/user-guide/connect-your-custom-app-with-syncmate/)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { syncmateByAssitro, @@ -24,7 +25,7 @@ export default { media: { type: "string", label: "Media", - description: "The the path to a file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", optional: true, }, fileName: { @@ -47,13 +48,13 @@ export default { ]; if (this.media) { - const file = fs.readFileSync(checkTmp(this.media), { - encoding: "base64", - }); + const stream = await getFileStream(this.media); + const buffer = await streamToBuffer(stream); + const base64 = buffer.toString("base64"); msgs[0].media = [ { - media_base64: file, + media_base64: base64, file_name: this.fileName, }, ]; diff --git a/components/syncmate_by_assitro/common/utils.mjs b/components/syncmate_by_assitro/common/utils.mjs index 1a5e36f32a603..24d2103c0b60b 100644 --- a/components/syncmate_by_assitro/common/utils.mjs +++ b/components/syncmate_by_assitro/common/utils.mjs @@ -4,3 +4,13 @@ export const checkTmp = (filename) => { } return filename; }; + +export const streamToBuffer = (stream) => { + return new Promise((resolve, reject) => { + const chunks = []; + + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => resolve(Buffer.concat(chunks))); + stream.on("error", reject); + }); +}; diff --git a/components/syncmate_by_assitro/package.json b/components/syncmate_by_assitro/package.json index 259eda1b8640b..ccaa43802df5a 100644 --- a/components/syncmate_by_assitro/package.json +++ b/components/syncmate_by_assitro/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/syncmate_by_assitro", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream SyncMate by Assitro Components", "main": "syncmate_by_assitro.app.mjs", "keywords": [ @@ -13,6 +13,6 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.3" + "@pipedream/platform": "^3.1.0" } } diff --git a/components/testmonitor/actions/create-test-result/create-test-result.mjs b/components/testmonitor/actions/create-test-result/create-test-result.mjs index 1cba89bfcd150..461b070ea4bc1 100644 --- a/components/testmonitor/actions/create-test-result/create-test-result.mjs +++ b/components/testmonitor/actions/create-test-result/create-test-result.mjs @@ -1,16 +1,15 @@ -import { ConfigurationError } from "@pipedream/platform"; -import FormData from "form-data"; -import fs from "fs"; import { - checkTmp, parseObject, -} from "../../common/utils.mjs"; + getFileStreamAndMetadata, ConfigurationError, +} from "@pipedream/platform"; +import FormData from "form-data"; +import { parseObject } from "../../common/utils.mjs"; import testmonitor from "../../testmonitor.app.mjs"; export default { key: "testmonitor-create-test-result", name: "Create Test Result", - description: "Create a new test result. [See the docs here](https://docs.testmonitor.com/#tag/Test-Results/operation/PostTestResult)", - version: "0.0.1", + description: "Create a new test result. [See the documentation](https://docs.testmonitor.com/#tag/Test-Results/operation/PostTestResult)", + version: "0.0.2", type: "action", props: { testmonitor, @@ -33,8 +32,11 @@ export default { propDefinition: [ testmonitor, "testRunId", - ({ projectId }) => ({ + ({ + projectId, testCaseId, + }) => ({ projectId, + testCaseId, }), ], }, @@ -47,7 +49,7 @@ export default { attachments: { type: "string[]", label: "Attachments", - description: "A list of attachment files.", + description: "A list of attachment files. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", hidden: true, optional: true, }, @@ -76,6 +78,27 @@ export default { return {}; }, async run({ $ }) { + let attachmentData = []; + if (this.attachments) { + try { + const files = parseObject(this.attachments); + for (const file of files) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); + const data = new FormData(); + data.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + attachmentData.push(data); + } + } catch (e) { + throw new ConfigurationError(`Error accessing attachments: ${e.message}`); + } + } + let testResultId; let summary = ""; try { @@ -92,9 +115,7 @@ export default { if (this.attachments) { try { - for (const file of parseObject(this.attachments)) { - const data = new FormData(); - data.append("file", fs.createReadStream(checkTmp(file))); + for (const data of attachmentData) { await this.testmonitor.uploadAttachment({ $, testResultId, @@ -103,7 +124,7 @@ export default { }); } } catch (e) { - summary = ", but the attachments could not be loaded."; + throw new ConfigurationError(`Error uploading attachments: ${e.message}`); } } diff --git a/components/testmonitor/actions/find-issue/find-issue.mjs b/components/testmonitor/actions/find-issue/find-issue.mjs index 8b12331e6f3b9..dba751b734d60 100644 --- a/components/testmonitor/actions/find-issue/find-issue.mjs +++ b/components/testmonitor/actions/find-issue/find-issue.mjs @@ -6,7 +6,7 @@ export default { key: "testmonitor-find-issue", name: "Find an Issue", description: "Retrieve a list of issues. [See the docs here](https://docs.testmonitor.com/#tag/Issues/operation/GetIssueCollection)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { ...common.props, diff --git a/components/testmonitor/actions/find-project/find-project.mjs b/components/testmonitor/actions/find-project/find-project.mjs index 43a7478026fa9..d61cb0084620b 100644 --- a/components/testmonitor/actions/find-project/find-project.mjs +++ b/components/testmonitor/actions/find-project/find-project.mjs @@ -6,7 +6,7 @@ export default { key: "testmonitor-find-project", name: "Find a Project", description: "Retrieve a list of projects. [See the docs here](https://docs.testmonitor.com/#tag/Projects/operation/GetProjectCollection)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { ...common.props, diff --git a/components/testmonitor/actions/find-test-result/find-test-result.mjs b/components/testmonitor/actions/find-test-result/find-test-result.mjs index c05db0c104770..e30699943e25f 100644 --- a/components/testmonitor/actions/find-test-result/find-test-result.mjs +++ b/components/testmonitor/actions/find-test-result/find-test-result.mjs @@ -6,7 +6,7 @@ export default { key: "testmonitor-find-test-result", name: "Find a Test Result", description: "Retrieve a list of test results. [See the docs here](https://docs.testmonitor.com/#tag/Test-Results/operation/GetTestResultCollection)", - version: "0.0.3", + version: "0.0.4", type: "action", props: { ...common.props, diff --git a/components/testmonitor/package.json b/components/testmonitor/package.json index b3784a128c57a..a65c6518f6b9f 100644 --- a/components/testmonitor/package.json +++ b/components/testmonitor/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/testmonitor", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream Testmonitor Components", "main": "testmonitor.app.mjs", "keywords": [ @@ -10,7 +10,7 @@ "homepage": "https://pipedream.com/apps/testmonitor", "author": "Pipedream (https://pipedream.com/)", "dependencies": { - "@pipedream/platform": "^3.0.3", + "@pipedream/platform": "^3.1.0", "fs": "^0.0.1-security", "moment": "^2.29.4" }, diff --git a/components/testmonitor/sources/new-issue/new-issue.mjs b/components/testmonitor/sources/new-issue/new-issue.mjs index fa61f228a7e95..8f188103f707b 100644 --- a/components/testmonitor/sources/new-issue/new-issue.mjs +++ b/components/testmonitor/sources/new-issue/new-issue.mjs @@ -5,7 +5,7 @@ export default { key: "testmonitor-new-issue", name: "New Issue", description: "Emit new event when a new issue is created.", - version: "0.0.3", + version: "0.0.4", type: "source", dedupe: "unique", methods: { diff --git a/components/testmonitor/sources/new-test-result/new-test-result.mjs b/components/testmonitor/sources/new-test-result/new-test-result.mjs index 15ac1efc8a435..245035c0db380 100644 --- a/components/testmonitor/sources/new-test-result/new-test-result.mjs +++ b/components/testmonitor/sources/new-test-result/new-test-result.mjs @@ -5,7 +5,7 @@ export default { key: "testmonitor-new-test-result", name: "New Test Result", description: "Emit new event when a new test result is created.", - version: "0.0.3", + version: "0.0.4", type: "source", dedupe: "unique", methods: { diff --git a/components/testmonitor/testmonitor.app.mjs b/components/testmonitor/testmonitor.app.mjs index a98f68bf76f1f..da2432edcd645 100644 --- a/components/testmonitor/testmonitor.app.mjs +++ b/components/testmonitor/testmonitor.app.mjs @@ -80,15 +80,22 @@ export default { label: "Test Run Id", description: "The test run identifier where this test result belongs to.", async options({ - page, projectId, + page, projectId, testCaseId, }) { - const { data } = await this.getTestRuns({ - page: page + 1, - params: { - project_id: projectId, - }, - }); - return data.map(({ + let response; + if (testCaseId) { + response = await this.getTestRunsForTestCase({ + testCaseId, + }); + } else { + response = await this.getTestRuns({ + page: page + 1, + params: { + project_id: projectId, + }, + }); + } + return response.data.map(({ id: value, name: label, }) => ({ label, @@ -208,6 +215,14 @@ export default { ...opts, }); }, + getTestRunsForTestCase({ + testCaseId, ...opts + }) { + return this._makeRequest({ + path: `test-case/${testCaseId}/test-runs`, + ...opts, + }); + }, getIssue({ issueId, ...opts }) { diff --git a/components/testmonitor/yarn.lock b/components/testmonitor/yarn.lock index 87d77b5df366b..dbed6d0e6259e 100644 --- a/components/testmonitor/yarn.lock +++ b/components/testmonitor/yarn.lock @@ -2,94 +2,217 @@ # yarn lockfile v1 -"@pipedream/platform@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@pipedream/platform/-/platform-3.0.3.tgz#b0f1d1274e061fb581635a30fabc830358975fd2" - integrity sha512-7elalas41lnT8i6EAFkqB7fT/+hkLGEQ1njS6A7CVguTrEswaIYk/seKmkfkRY7+O6qncgnXswYIKCBML9Co7w== +"@pipedream/platform@^3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@pipedream/platform/-/platform-3.1.0.tgz" + integrity sha512-ELmV3fpd9PIUm74/RPaqmA7hJaY4ryIn6PCNT1NP/gnqMrkRNOAr+DTV4xPaJgPiRm74WC5HvrkC8YdRveXzZA== dependencies: axios "^1.7.4" fp-ts "^2.0.2" io-ts "^2.0.0" + mime-types "^3.0.1" querystring "^0.2.1" + uuid "^11.1.0" asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== axios@^1.7.4: - version "1.7.9" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" - integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== + version "1.9.0" + resolved "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz" + integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + follow-redirects@^1.15.6: version "1.15.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== form-data@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" - integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== + version "4.0.3" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz" + integrity sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" mime-types "^2.1.12" -fp-ts@^2.0.2: - version "2.16.9" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.16.9.tgz#99628fc5e0bb3b432c4a16d8f4455247380bae8a" - integrity sha512-+I2+FnVB+tVaxcYyQkHUq7ZdKScaBlX53A41mxQtpIccsfyv8PzdzP7fzp2AY832T4aoK6UZ5WRX/ebGd8uZuQ== +fp-ts@^2.0.2, fp-ts@^2.5.0: + version "2.16.10" + resolved "https://registry.npmjs.org/fp-ts/-/fp-ts-2.16.10.tgz" + integrity sha512-vuROzbNVfCmUkZSUbnWSltR1sbheyQbTzug7LB/46fEa1c0EucLeBaCEUE0gF3ZGUGBt9lVUiziGOhhj6K1ORA== fs@^0.0.1-security: version "0.0.1-security" - resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + io-ts@^2.0.0: - version "2.2.21" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.21.tgz#4ef754176f7082a1099d04c7d5c4ea53267c530a" - integrity sha512-zz2Z69v9ZIC3mMLYWIeoUcwWD6f+O7yP92FMVVaXEOSZH1jnVBmET/urd/uoarD1WGBY4rCj8TAyMPzsGNzMFQ== + version "2.2.22" + resolved "https://registry.npmjs.org/io-ts/-/io-ts-2.2.22.tgz" + integrity sha512-FHCCztTkHoV9mdBsHpocLpdTAfh956ZQcIkWQxxS0U5HT53vtrcuYdQneEJKH6xILaLNzXVl2Cvwtoy8XNN0AA== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + moment@^2.29.4: version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz" integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== querystring@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz" integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== + +uuid@^11.1.0: + version "11.1.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz" + integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== diff --git a/components/the_bookie/actions/create-sales-invoice/create-sales-invoice.mjs b/components/the_bookie/actions/create-sales-invoice/create-sales-invoice.mjs index ed3bc56c00fb5..0380940fcdb0f 100644 --- a/components/the_bookie/actions/create-sales-invoice/create-sales-invoice.mjs +++ b/components/the_bookie/actions/create-sales-invoice/create-sales-invoice.mjs @@ -1,15 +1,14 @@ -import { ConfigurationError } from "@pipedream/platform"; -import fs from "fs"; import { - checkTmp, parseObject, -} from "../../common/utils.mjs"; + getFileStream, ConfigurationError, +} from "@pipedream/platform"; +import { parseObject } from "../../common/utils.mjs"; import theBookie from "../../the_bookie.app.mjs"; export default { key: "the_bookie-create-sales-invoice", name: "Create Sales Invoice", description: "Creates a new sales invoice. [See the documentation](https://app.thebookie.nl/nl/help/article/api-documentatie/#salesentry_create)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { theBookie, @@ -67,18 +66,29 @@ export default { attachment: { type: "string", label: "Attachment", - description: "The path to the pdf file saved to the `/tmp` directory (e.g. `/tmp/example.pdf`). [See the documentation](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory).", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", optional: true, }, }, + methods: { + async streamToBuffer(stream) { + return new Promise((resolve, reject) => { + const chunks = []; + + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => resolve(Buffer.concat(chunks))); + stream.on("error", reject); + }); + }, + }, async run({ $ }) { if (!this.journalEntryLines) { throw new ConfigurationError("At least one (1) 'Journal Entry Line' should be added"); } if (this.attachment) { - this.attachment = fs.readFileSync(checkTmp(this.attachment), { - encoding: "base64", - }); + const stream = await getFileStream(this.attachment); + const buffer = await this.streamToBuffer(stream); + this.attachment = buffer.toString("base64"); } const response = await this.theBookie.createInvoice({ $, diff --git a/components/the_bookie/package.json b/components/the_bookie/package.json index 12092ea586510..4597a68afdd8c 100644 --- a/components/the_bookie/package.json +++ b/components/the_bookie/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/the_bookie", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream The Bookie Components", "main": "the_bookie.app.mjs", "keywords": [ @@ -13,7 +13,6 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.1" + "@pipedream/platform": "^3.1.0" } } - diff --git a/components/timetonic/actions/common/create-update-row.mjs b/components/timetonic/actions/common/create-update-row.mjs index de684d75e77f0..f9de11c02b2b9 100644 --- a/components/timetonic/actions/common/create-update-row.mjs +++ b/components/timetonic/actions/common/create-update-row.mjs @@ -1,7 +1,7 @@ import timetonic from "../../timetonic.app.mjs"; import constants from "../../common/constants.mjs"; -import fs from "fs"; import FormData from "form-data"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { props: { @@ -38,7 +38,7 @@ export default { for (const field of fields) { if (!field?.readOnly) { const id = `${field.id}`; - props[id] = { + props[`id_${id}`] = { type: constants.FIELD_TYPES[field.type] || "string", label: field.name, optional: this.isUpdate() @@ -56,22 +56,23 @@ export default { id, name: label, }) => ({ value: `${id}`, - label, + label: label || `${id}`, })) || []; - props[id].options = options; - props[id].description = "The Row ID from the linked table to create a link to"; + props[`id_${id}`].options = options; + props[`id_${id}`].description = "The Row ID from the linked table to create a link to"; tableRows.forEach(({ id: rowId, name, }) => { props[`${id}_${rowId}_link_text`] = { type: "string", - default: name, + default: name || `${rowId}`, hidden: true, }; }); } if (field.type === "file" || field.type === "files") { - props[id].description = "The path to the file saved to the `/tmp` directory (e.g. `/tmp/example.pdf`). [See the documentation](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory)."; + props[`id_${id}`].type = "string[]"; + props[`id_${id}`].description = "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf)."; props[`${id}_is_file`] = { type: "boolean", default: true, @@ -86,12 +87,16 @@ export default { isUpdate() { return false; }, - uploadFile($, fieldId, filePath, rowId) { - const fileStream = fs.createReadStream(filePath.includes("/tmp") - ? filePath - : `/tmp/${filePath}`); + async uploadFile($, fieldId, filePath, rowId) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(filePath); const formData = new FormData(); - formData.append("qqfile", fileStream); + formData.append("qqfile", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); return this.timetonic.uploadFile({ $, params: { @@ -124,21 +129,22 @@ export default { key, value, ] of Object.entries(fields)) { + const id = parseInt(key.split("_")[1], 10); if (key.includes("link_text") || key.includes("is_file")) { continue; } - if (fields[`${key}_is_file`]) { + if (fields[`${id}_is_file`]) { files.push({ - fieldId: key, + fieldId: id, filePath: value, }); continue; } - fieldValues[+key] = fields[`${key}_${value}_link_text`] + fieldValues[id] = fields[`${id}_${value}_link_text`] ? [ { row_id: +value, - value: fields[`${key}_${value}_link_text`], + value: fields[`${id}_${value}_link_text`], }, ] : value; diff --git a/components/timetonic/actions/create-row/create-row.mjs b/components/timetonic/actions/create-row/create-row.mjs index ff71499913bcf..a4e69d352d880 100644 --- a/components/timetonic/actions/create-row/create-row.mjs +++ b/components/timetonic/actions/create-row/create-row.mjs @@ -5,6 +5,6 @@ export default { key: "timetonic-create-row", name: "Create Row", description: "Create a new row within an existing table in TimeTonic. [See the documentation](https://timetonic.com/live/apidoc/#api-Smart_table_operations-createOrUpdateTableRow)", - version: "0.0.1", + version: "0.0.2", type: "action", }; diff --git a/components/timetonic/actions/update-row/update-row.mjs b/components/timetonic/actions/update-row/update-row.mjs index ec742ab095e29..9be81903b94ad 100644 --- a/components/timetonic/actions/update-row/update-row.mjs +++ b/components/timetonic/actions/update-row/update-row.mjs @@ -5,7 +5,7 @@ export default { key: "timetonic-update-row", name: "Update Row", description: "Updates the values within a specified row in a table. [See the documentation](https://timetonic.com/live/apidoc/#api-Smart_table_operations-createOrUpdateTableRow)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { ...common.props, diff --git a/components/timetonic/package.json b/components/timetonic/package.json index 7ea1d96f6b3d8..3f08633796bb2 100644 --- a/components/timetonic/package.json +++ b/components/timetonic/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/timetonic", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream TimeTonic Components", "main": "timetonic.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.6.5", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0", "md5": "^2.3.0" } diff --git a/components/transifex/actions/download-file/download-file.mjs b/components/transifex/actions/download-file/download-file.mjs index 06385514a4f2f..0afa1434a3708 100644 --- a/components/transifex/actions/download-file/download-file.mjs +++ b/components/transifex/actions/download-file/download-file.mjs @@ -5,7 +5,7 @@ export default { key: "transifex-download-file", name: "Download File", description: "Downloads a user-specified file from the Transifex platform. [See the documentation](https://developers.transifex.com/reference/get_resource-strings-async-downloads-resource-strings-async-download-id)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { transifex, diff --git a/components/transifex/actions/upload-file/upload-file.mjs b/components/transifex/actions/upload-file/upload-file.mjs index 11fdd9c9d1834..0b224d1308f89 100644 --- a/components/transifex/actions/upload-file/upload-file.mjs +++ b/components/transifex/actions/upload-file/upload-file.mjs @@ -1,12 +1,11 @@ -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; import transifex from "../../transifex.app.mjs"; +import { getFileStream } from "@pipedream/platform"; export default { key: "transifex-upload-file", name: "Upload File to Transifex", description: "Uploads a given file to the Transifex platform. [See the documentation](https://developers.transifex.com/reference/post_resource-strings-async-uploads)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { transifex, @@ -59,7 +58,21 @@ export default { ], }, }, + methods: { + async streamToBuffer(stream) { + return new Promise((resolve, reject) => { + const chunks = []; + + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => resolve(Buffer.concat(chunks))); + stream.on("error", reject); + }); + }, + }, async run({ $ }) { + const stream = await getFileStream(this.file); + const buffer = await this.streamToBuffer(stream); + const base64 = buffer.toString("base64"); const response = await this.transifex.uploadFile({ $, headers: { @@ -70,9 +83,7 @@ export default { data: { attributes: { callback_url: this.callbackUrl, - content: fs.readFileSync(checkTmp(this.file), { - encoding: "base64", - }), + content: base64, content_encoding: "base64", keep_translations: this.keepTranslations, replace_edited_strings: this.replaceEditedStrings, diff --git a/components/transifex/package.json b/components/transifex/package.json index 3e1794903a0c3..245ce799b5400 100644 --- a/components/transifex/package.json +++ b/components/transifex/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/transifex", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream Transifex Components", "main": "transifex.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^2.0.0", + "@pipedream/platform": "^3.1.0", "fs": "^0.0.1-security" } } diff --git a/components/transifex/sources/new-localization-activity-completed-instant/new-localization-activity-completed-instant.mjs b/components/transifex/sources/new-localization-activity-completed-instant/new-localization-activity-completed-instant.mjs index 8729ec3765c68..09d2764f013fa 100644 --- a/components/transifex/sources/new-localization-activity-completed-instant/new-localization-activity-completed-instant.mjs +++ b/components/transifex/sources/new-localization-activity-completed-instant/new-localization-activity-completed-instant.mjs @@ -6,7 +6,7 @@ export default { key: "transifex-new-localization-activity-completed-instant", name: "New Localization Activity Completed (Instant)", description: "Emit new event when a resource language is completely translated, reviewed, or filled up by TM or MT.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/transifex/sources/new-task-for-set-of-strings-instant/new-task-for-set-of-strings-instant.mjs b/components/transifex/sources/new-task-for-set-of-strings-instant/new-task-for-set-of-strings-instant.mjs index cefed0ae675a0..d691a4ebd8e9e 100644 --- a/components/transifex/sources/new-task-for-set-of-strings-instant/new-task-for-set-of-strings-instant.mjs +++ b/components/transifex/sources/new-task-for-set-of-strings-instant/new-task-for-set-of-strings-instant.mjs @@ -6,7 +6,7 @@ export default { key: "transifex-new-task-for-set-of-strings-instant", name: "New Task for Set of Strings (Instant)", description: "Emit new event when the strings of a task are fully translated.", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/transifex/transifex.app.mjs b/components/transifex/transifex.app.mjs index 4fc84d07b88ee..89944fbe6fb8e 100644 --- a/components/transifex/transifex.app.mjs +++ b/components/transifex/transifex.app.mjs @@ -6,8 +6,8 @@ export default { propDefinitions: { file: { type: "string", - label: "File", - description: "The path to the json file saved to the `/tmp` directory (e.g. `/tmp/example.json`). [See the documentation](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory).", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, organizationId: { type: "string", diff --git a/components/trello/actions/add-attachment-to-card/add-attachment-to-card.mjs b/components/trello/actions/add-attachment-to-card/add-attachment-to-card.mjs index 12c31d0063404..7ace43dd038f9 100644 --- a/components/trello/actions/add-attachment-to-card/add-attachment-to-card.mjs +++ b/components/trello/actions/add-attachment-to-card/add-attachment-to-card.mjs @@ -1,5 +1,4 @@ -import { ConfigurationError } from "@pipedream/platform"; -import fs from "fs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import FormData from "form-data"; import app from "../../trello.app.mjs"; @@ -7,7 +6,7 @@ export default { key: "trello-add-attachment-to-card", name: "Add Attachment To Card", description: "Adds a file attachment on a card. [See the documentation](https://developer.atlassian.com/cloud/trello/rest/api-group-cards/#api-cards-id-attachments-post)", - version: "0.0.2", + version: "1.0.0", type: "action", props: { app, @@ -36,33 +35,16 @@ export default { "name", ], }, - fileType: { - propDefinition: [ - app, - "fileType", - ], - reloadProps: true, - }, - url: { - propDefinition: [ - app, - "url", - ], - hidden: true, - }, file: { - propDefinition: [ - app, - "file", - ], - hidden: true, + type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, mimeType: { propDefinition: [ app, "mimeType", ], - hidden: true, }, setCover: { type: "boolean", @@ -72,20 +54,10 @@ export default { optional: true, }, }, - async additionalProps(props) { - const attachmentIsPath = this.fileType === "path"; - const attachmentIsUrl = this.fileType === "url"; - props.file.hidden = !attachmentIsPath; - props.mimeType.hidden = !attachmentIsPath; - props.url.hidden = !attachmentIsUrl; - - return {}; - }, async run({ $ }) { const { cardId, name, - url, mimeType, setCover, file, @@ -98,32 +70,24 @@ export default { setCover, }; - if (file && !file?.startsWith("/tmp")) { - throw new ConfigurationError("The file path must be in the `/tmp` directory"); - } - - if (file) { - const form = new FormData(); - form.append("file", fs.createReadStream(file)); + const form = new FormData(); + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); - response = await this.app.addAttachmentToCard({ - $, - cardId, - params, - headers: form.getHeaders(), - data: form, - }); + form.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); - } else { - response = await this.app.addAttachmentToCard({ - $, - cardId, - params: { - ...params, - url, - }, - }); - } + response = await this.app.addAttachmentToCard({ + $, + cardId, + params, + headers: form.getHeaders(), + data: form, + }); $.export("$summary", `Successfully added attachement to card ${cardId}`); return response; diff --git a/components/trello/actions/create-card/create-card.mjs b/components/trello/actions/create-card/create-card.mjs index fddb8544440a2..a5daef9ec2b84 100644 --- a/components/trello/actions/create-card/create-card.mjs +++ b/components/trello/actions/create-card/create-card.mjs @@ -1,14 +1,13 @@ import app from "../../trello.app.mjs"; -import fs from "fs"; import FormData from "form-data"; -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import constants from "../../common/constants.mjs"; export default { key: "trello-create-card", name: "Create Card", description: "Creates a new card. [See the documentation](https://developer.atlassian.com/cloud/trello/rest/api-group-cards/#api-cards-post).", - version: "0.1.1", + version: "1.0.0", type: "action", props: { app, @@ -90,34 +89,18 @@ export default { description: "Array of labelIDs to add to the card", optional: true, }, - fileType: { - propDefinition: [ - app, - "fileType", - ], - optional: true, - reloadProps: true, - }, - urlSource: { - propDefinition: [ - app, - "url", - ], - hidden: true, - }, file: { - propDefinition: [ - app, - "file", - ], - hidden: true, + type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", + optional: true, }, mimeType: { propDefinition: [ app, "mimeType", ], - hidden: true, + optional: true, }, idCardSource: { propDefinition: [ @@ -172,12 +155,6 @@ export default { async additionalProps(existingProps) { const props = {}; - const attachmentIsPath = this.fileType === "path"; - const attachmentIsUrl = this.fileType === "url"; - existingProps.file.hidden = !attachmentIsPath; - existingProps.mimeType.hidden = !attachmentIsPath; - existingProps.urlSource.hidden = !attachmentIsUrl; - existingProps.keepFromSource.hidden = !this.idCardSource; if (!this.customFieldIds?.length) { @@ -237,7 +214,6 @@ export default { idList, idMembers, idLabels, - urlSource, mimeType, file, idCardSource, @@ -266,14 +242,16 @@ export default { coordinates, }; - if (file && !file?.startsWith("/tmp")) { - throw new ConfigurationError("The file path must be in the `/tmp` directory"); - } - if (file) { const form = new FormData(); - form.append("fileSource", fs.createReadStream(file)); - + const { + stream, metadata, + } = await getFileStreamAndMetadata(file); + form.append("fileSource", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); response = await this.app.createCard({ $, params, @@ -283,10 +261,7 @@ export default { } else { response = await this.app.createCard({ $, - params: { - ...params, - urlSource, - }, + params, }); } diff --git a/components/trello/package.json b/components/trello/package.json index e2930002d5276..e7d30e634563d 100644 --- a/components/trello/package.json +++ b/components/trello/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/trello", - "version": "0.4.1", + "version": "1.0.0", "description": "Pipedream Trello Components", "main": "trello.app.mjs", "keywords": [ @@ -10,7 +10,7 @@ "homepage": "https://pipedream.com/apps/trello", "author": "Pipedream (https://pipedream.com/)", "dependencies": { - "@pipedream/platform": "^3.0.1", + "@pipedream/platform": "^3.1.0", "crypto": "^1.0.1", "form-data": "^4.0.0", "lodash-es": "^4.17.21", diff --git a/components/trust/actions/upload-video/upload-video.mjs b/components/trust/actions/upload-video/upload-video.mjs index d243efd5196b7..f708b70d8b97e 100644 --- a/components/trust/actions/upload-video/upload-video.mjs +++ b/components/trust/actions/upload-video/upload-video.mjs @@ -1,12 +1,12 @@ -import fs from "fs"; import FormData from "form-data"; import app from "../../trust.app.mjs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { key: "trust-upload-video", name: "Upload Video", description: "Upload a video to the Trust platform. [See the documentation](https://api-docs.usetrust.io/uploads-a-video-to-be-used-for-testimonials).", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, @@ -18,8 +18,8 @@ export default { }, filePath: { type: "string", - label: "File Path", - description: "File path of a file previously downloaded in Pipedream E.g. (`/tmp/my-file.mp4`). [Download a file to the `/tmp` directory](https://pipedream.com/docs/code/nodejs/http-requests/#download-a-file-to-the-tmp-directory)", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, }, methods: { @@ -40,7 +40,14 @@ export default { } = this; const data = new FormData(); - data.append("file", fs.createReadStream(filePath)); + const { + stream, metadata, + } = await getFileStreamAndMetadata(filePath); + data.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); const response = await uploadVideo({ $, diff --git a/components/trust/package.json b/components/trust/package.json index 7086e869f0386..9b4cf97d203ee 100644 --- a/components/trust/package.json +++ b/components/trust/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/trust", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream Trust Components", "main": "trust.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.0", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0", "fs": "^0.0.1-security" } diff --git a/components/twitter/actions/upload-media/upload-media.ts b/components/twitter/actions/upload-media/upload-media.ts index 26ac322fd70a2..6b633509c2cf9 100644 --- a/components/twitter/actions/upload-media/upload-media.ts +++ b/components/twitter/actions/upload-media/upload-media.ts @@ -2,8 +2,7 @@ import common from "../../common/appValidation"; import { ACTION_ERROR_MESSAGE } from "../../common/errorMessage"; import { defineAction } from "@pipedream/types"; import constants from "../../common/constants"; -import fs from "fs"; -import { axios } from "@pipedream/platform"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import FormData from "form-data"; const DOCS_LINK = "https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload"; @@ -13,15 +12,14 @@ export default defineAction({ key: "twitter-upload-media", name: "Upload Media", description: `Upload new media. [See the documentation](${DOCS_LINK})`, - version: "0.0.12", + version: "0.0.13", type: "action", props: { ...common.props, filePath: { type: "string", - label: "File Path", - description: "A file URL or a file path in the `/tmp` directory. [See the documentation on working with files.](https://pipedream.com/docs/code/nodejs/working-with-files/)", - optional: false, + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, media_category: { type: "string", @@ -32,31 +30,25 @@ export default defineAction({ }, }, async run({ $ }): Promise { - const isLocalFile = this.filePath?.startsWith("/tmp"); - let content; + let content, meta; try { - content = isLocalFile - ? fs.createReadStream(this.filePath, { - encoding: "base64", - }) - : await axios($, { - url: this.filePath, - responseType: "arraybuffer", - }); - + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.filePath); + content = stream; + meta = metadata; } catch (err) { $.export("error", err); throw new Error(ACTION_ERROR_MESSAGE); } const data = new FormData(); - - if (isLocalFile) { - data.append("media_data", content); - } else { - data.append("media", content); - } + data.append("media_data", content, { + contentType: meta.contentType, + knownLength: meta.size, + filename: meta.name, + }); const response = await this.app.uploadMedia({ $, diff --git a/components/twitter/package.json b/components/twitter/package.json index 6b077ef4363d2..59a160300b6e2 100644 --- a/components/twitter/package.json +++ b/components/twitter/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/twitter", - "version": "2.3.0", + "version": "2.3.1", "description": "Pipedream Twitter Components", "main": "dist/app/twitter.app.mjs", "keywords": [ @@ -16,7 +16,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.5.1", + "@pipedream/platform": "^3.1.0", "@pipedream/types": "^0.1.4", "form-data": "^4.0.0", "oauth-1.0a": "^2.2.6" diff --git a/components/twitter/twitter.app.mjs b/components/twitter/twitter.app.mjs deleted file mode 100644 index 55d81a68bfa48..0000000000000 --- a/components/twitter/twitter.app.mjs +++ /dev/null @@ -1,11 +0,0 @@ -export default { - type: "app", - app: "twitter", - propDefinitions: {}, - methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); - }, - }, -}; \ No newline at end of file diff --git a/components/vapi/actions/upload-file/upload-file.mjs b/components/vapi/actions/upload-file/upload-file.mjs index cf6d9c49a77c2..317be47f0eebb 100644 --- a/components/vapi/actions/upload-file/upload-file.mjs +++ b/components/vapi/actions/upload-file/upload-file.mjs @@ -1,27 +1,31 @@ import FormData from "form-data"; -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; import vapi from "../../vapi.app.mjs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { key: "vapi-upload-file", name: "Upload File", description: "Uploads a new file. [See the documentation](https://docs.vapi.ai/api-reference)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { vapi, file: { type: "string", - label: "File", - description: "The path to the file saved to the `/tmp` directory (e.g. `/tmp/example.txt`). [See the documentation](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory).", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, }, async run({ $ }) { const formData = new FormData(); - const filePath = checkTmp(this.file); - - formData.append("file", fs.createReadStream(filePath)); + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.file); + formData.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); const response = await this.vapi.uploadFile({ $, diff --git a/components/vapi/package.json b/components/vapi/package.json index ab186fdbc6448..d99a2e777aac7 100644 --- a/components/vapi/package.json +++ b/components/vapi/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/vapi", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream Vapi Components", "main": "vapi.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.3", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.1" } } diff --git a/components/what_are_those/actions/find-sneakers-by-sku/find-sneakers-by-sku.mjs b/components/what_are_those/actions/find-sneakers-by-sku/find-sneakers-by-sku.mjs index 61f1296aca567..f56cfb871be3d 100644 --- a/components/what_are_those/actions/find-sneakers-by-sku/find-sneakers-by-sku.mjs +++ b/components/what_are_those/actions/find-sneakers-by-sku/find-sneakers-by-sku.mjs @@ -1,24 +1,25 @@ -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; +import { streamToBuffer } from "../../common/utils.mjs"; import app from "../../what_are_those.app.mjs"; +import { getFileStream } from "@pipedream/platform"; export default { key: "what_are_those-find-sneakers-by-sku", name: "Find Sneakers by SKU", description: "Identifies sneakers from a size tag photo and returns sneaker name and details. [See the documentation](https://documenter.getpostman.com/view/3847098/2sAY4rDQDs#4f6a49f9-3393-42cd-8474-3856a79888af)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, sizeTagImage: { type: "string", label: "Size Tag Image", - description: "The path to the size tag image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The image to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, }, async run({ $ }) { - const data = fs.readFileSync(checkTmp(this.sizeTagImage)); - const base64Image = Buffer.from(data, "binary").toString("base64"); + const stream = await getFileStream(this.sizeTagImage); + const buffer = await streamToBuffer(stream); + const base64Image = buffer.toString("base64"); const response = await this.app.identifySneakersFromSizeTag({ $, diff --git a/components/what_are_those/actions/grade-sneakers-condition/grade-sneakers-condition.mjs b/components/what_are_those/actions/grade-sneakers-condition/grade-sneakers-condition.mjs index 2382e7e4e40dd..6fe28d9d28cc9 100644 --- a/components/what_are_those/actions/grade-sneakers-condition/grade-sneakers-condition.mjs +++ b/components/what_are_those/actions/grade-sneakers-condition/grade-sneakers-condition.mjs @@ -1,50 +1,49 @@ import FormData from "form-data"; -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; import app from "../../what_are_those.app.mjs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { key: "what_are_those-grade-sneakers-condition", name: "Grade and Authenticate Sneakers", description: "Grades and authenticates sneakers using provided images. [See the documentation](https://documenter.getpostman.com/view/3847098/2sAY4rDQDs#13d527e8-5d8f-4511-857c-b40b8dd921b8)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, frontImage: { type: "string", label: "Front Image", - description: "The path to the front image image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The frontimage to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, leftImage: { type: "string", label: "Left Image", - description: "The path to the left image image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The leftimage to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, rightImage: { type: "string", label: "Right Image", - description: "The path to the right image image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The right image to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, soleImage: { type: "string", label: "Sole Image", - description: "The path to the sole image image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The sole image to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, insoleImage: { type: "string", label: "Insole Image", - description: "The path to the insole image image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The insole image to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, sizeTagImage: { type: "string", label: "Size Tag Image", - description: "The path to the sizeTag image image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The size tag image to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, type: { type: "string", label: "Use Type", - description: "the type parameter to see specific types of data.", + description: "The type parameter to see specific types of data", options: [ "grading", "authentication", @@ -53,13 +52,78 @@ export default { }, }, async run({ $ }) { + const { + frontImage, + leftImage, + rightImage, + soleImage, + insoleImage, + sizeTagImage, + type, + } = this; + const data = new FormData(); - data.append("image1", fs.createReadStream(checkTmp(this.frontImage))); - data.append("image2", fs.createReadStream(checkTmp(this.leftImage))); - data.append("image3", fs.createReadStream(checkTmp(this.rightImage))); - data.append("image4", fs.createReadStream(checkTmp(this.soleImage))); - data.append("image5", fs.createReadStream(checkTmp(this.insoleImage))); - data.append("image6", fs.createReadStream(checkTmp(this.sizeTagImage))); + + if (frontImage) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(frontImage); + data.append("image1", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } + if (leftImage) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(leftImage); + data.append("image2", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } + if (rightImage) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(rightImage); + data.append("image3", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } + if (soleImage) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(soleImage); + data.append("image4", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } + if (insoleImage) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(insoleImage); + data.append("image5", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } + if (sizeTagImage) { + const { + stream, metadata, + } = await getFileStreamAndMetadata(sizeTagImage); + data.append("image6", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); + } const response = await this.app.gradeAuthenticateSneakers({ headers: { @@ -68,7 +132,7 @@ export default { data: data, maxBodyLength: Infinity, params: { - type: this.type, + type, }, timeout: 120000, }); diff --git a/components/what_are_those/actions/identify-sneakers-from-photo/identify-sneakers-from-photo.mjs b/components/what_are_those/actions/identify-sneakers-from-photo/identify-sneakers-from-photo.mjs index 1ff6a6585f5c2..d708e3dd2e4a8 100644 --- a/components/what_are_those/actions/identify-sneakers-from-photo/identify-sneakers-from-photo.mjs +++ b/components/what_are_those/actions/identify-sneakers-from-photo/identify-sneakers-from-photo.mjs @@ -1,25 +1,31 @@ import FormData from "form-data"; -import fs from "fs"; -import { checkTmp } from "../../common/utils.mjs"; import app from "../../what_are_those.app.mjs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { key: "what_are_those-identify-sneakers-from-photo", name: "Identify Sneakers from Photo", description: "Identifies sneakers from an uploaded image and returns details such as name, links, images, prices, and confidence scores. [See the documentation](https://documenter.getpostman.com/view/3847098/2sAY4rDQDs#957c900c-501f-4c8f-9b8b-71655a8cfb5d).", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, image: { type: "string", label: "Image", - description: "The path to the size tag image in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp).", + description: "The image to upload. Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.jpg).", }, }, async run({ $ }) { const data = new FormData(); - data.append("image1", fs.createReadStream(checkTmp(this.image))); + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.image); + data.append("image1", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); const response = await this.app.identifySneakers({ headers: { diff --git a/components/what_are_those/common/utils.mjs b/components/what_are_those/common/utils.mjs index 1a5e36f32a603..24d2103c0b60b 100644 --- a/components/what_are_those/common/utils.mjs +++ b/components/what_are_those/common/utils.mjs @@ -4,3 +4,13 @@ export const checkTmp = (filename) => { } return filename; }; + +export const streamToBuffer = (stream) => { + return new Promise((resolve, reject) => { + const chunks = []; + + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("end", () => resolve(Buffer.concat(chunks))); + stream.on("error", reject); + }); +}; diff --git a/components/what_are_those/package.json b/components/what_are_those/package.json index 16b409180cf3b..cb3ae342069b9 100644 --- a/components/what_are_those/package.json +++ b/components/what_are_those/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/what_are_those", - "version": "0.1.0", + "version": "0.1.1", "description": "Pipedream What Are Those Components", "main": "what_are_those.app.mjs", "keywords": [ @@ -13,6 +13,6 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.3" + "@pipedream/platform": "^3.1.0" } } diff --git a/components/whatsapp_business/actions/send-voice-message/send-voice-message.mjs b/components/whatsapp_business/actions/send-voice-message/send-voice-message.mjs index 8058a155efaf2..dac3d5f6b7c23 100644 --- a/components/whatsapp_business/actions/send-voice-message/send-voice-message.mjs +++ b/components/whatsapp_business/actions/send-voice-message/send-voice-message.mjs @@ -1,12 +1,12 @@ import whatsapp from "../../whatsapp_business.app.mjs"; import FormData from "form-data"; -import fs from "fs"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; export default { key: "whatsapp_business-send-voice-message", name: "Send Voice Message", description: "Sends a voice message. [See the documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/messages/audio-messages)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { whatsapp, @@ -24,8 +24,8 @@ export default { }, filePath: { type: "string", - label: "File Path", - description: "The path to a media file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#writing-a-file-to-tmp)", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, type: { type: "string", @@ -44,10 +44,14 @@ export default { async run({ $ }) { // upload media file const formData = new FormData(); - const content = fs.createReadStream(this.filePath.includes("tmp/") - ? this.filePath - : `/tmp/${this.filePath}`); - formData.append("file", content); + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.filePath); + formData.append("file", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); formData.append("type", this.type); formData.append("messaging_product", "whatsapp"); const { id: mediaId } = await this.whatsapp.uploadMedia({ diff --git a/components/whatsapp_business/package.json b/components/whatsapp_business/package.json index f92aa41447c0c..c5cf0fbed2007 100644 --- a/components/whatsapp_business/package.json +++ b/components/whatsapp_business/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/whatsapp_business", - "version": "0.0.10", + "version": "0.0.11", "description": "Pipedream WhatsApp Business Components", "main": "whatsapp_business.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.2.0", + "@pipedream/platform": "^3.1.0", "form-data": "^4.0.0" } } diff --git a/components/wordpress_org/actions/upload-media/upload-media.mjs b/components/wordpress_org/actions/upload-media/upload-media.mjs index f59517a81b730..35a66a464fa0e 100644 --- a/components/wordpress_org/actions/upload-media/upload-media.mjs +++ b/components/wordpress_org/actions/upload-media/upload-media.mjs @@ -1,19 +1,19 @@ import wordpress from "../../wordpress_org.app.mjs"; import utils from "../../common/utils.mjs"; -import fs from "fs"; +import { getFileStream } from "@pipedream/platform"; export default { key: "wordpress_org-upload-media", name: "Upload Media", description: "Upload a media item to your WordPress media library. Returns a media ID to be used in creating or updating posts.[See the documentation](https://www.npmjs.com/package/wpapi#uploading-media)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { wordpress, filePath: { type: "string", - label: "File Path", - description: "The path to a document file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#the-tmp-directory).", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, title: { propDefinition: [ @@ -39,7 +39,7 @@ export default { }, }, async run({ $ }) { - const content = fs.createReadStream(utils.getFilePath(this.filePath)); + const content = await getFileStream(this.filePath); const params = utils.cleanObj({ title: this.title, diff --git a/components/wordpress_org/package.json b/components/wordpress_org/package.json index 21079a5d4212d..8a0c9a78cb57d 100644 --- a/components/wordpress_org/package.json +++ b/components/wordpress_org/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/wordpress_org", - "version": "0.4.0", + "version": "0.4.1", "description": "Pipedream Wordpress.org Components", "main": "wordpress_org.app.mjs", "keywords": [ @@ -10,6 +10,7 @@ "homepage": "https://pipedream.com/apps/wordpress_org", "author": "Pipedream (https://pipedream.com/)", "dependencies": { + "@pipedream/platform": "^3.1.0", "lodash.pickby": "^4.6.0", "wpapi": "^1.2.2" }, diff --git a/components/youtube_data_api/actions/upload-channel-banner/common.mjs b/components/youtube_data_api/actions/upload-channel-banner/common.mjs index 09bd086c1b158..da8539999640f 100644 --- a/components/youtube_data_api/actions/upload-channel-banner/common.mjs +++ b/components/youtube_data_api/actions/upload-channel-banner/common.mjs @@ -1,16 +1,9 @@ -import fs from "fs"; -import got from "got"; -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStream } from "@pipedream/platform"; export default { async run({ $ }) { - if ((!this.fileUrl && !this.filePath) || (this.fileUrl && this.filePath)) { - throw new ConfigurationError("This action requires either `File URL` or `File Path`. Please enter one or the other above."); - } + const body = await getFileStream(this.filePath); - const body = this.fileUrl - ? await got.stream(this.fileUrl) - : fs.createReadStream(this.filePath); const params = { onBehalfOfContentOwner: this.onBehalfOfContentOwner, media: { diff --git a/components/youtube_data_api/actions/upload-channel-banner/upload-channel-banner.mjs b/components/youtube_data_api/actions/upload-channel-banner/upload-channel-banner.mjs index b633bc6e97de3..8ca7d5e8b43f1 100644 --- a/components/youtube_data_api/actions/upload-channel-banner/upload-channel-banner.mjs +++ b/components/youtube_data_api/actions/upload-channel-banner/upload-channel-banner.mjs @@ -6,7 +6,7 @@ export default { key: "youtube_data_api-upload-channel-banner", name: "Upload Channel Banner", description: "Uploads a channel banner image to YouTube. [See the documentation](https://developers.google.com/youtube/v3/docs/channelBanners/insert) for more information", - version: "0.0.4", + version: "1.0.0", type: "action", props: { youtubeDataApi, @@ -15,19 +15,10 @@ export default { alertType: "info", content: "- Maximum file size: 6MB \n- The image must have a 16:9 aspect ratio and be at least 2048x1152 pixels \n- Accepted Media MIME types: image/jpeg, image/png, application/octet-stream", }, - fileUrl: { - propDefinition: [ - youtubeDataApi, - "fileUrl", - ], - description: "The URL of the banner image file you want to upload to YouTube. Must specify either **File URL** or **File Path**.", - }, filePath: { - propDefinition: [ - youtubeDataApi, - "filePath", - ], - description: "Path to the banner image file to upload (e.g., `/tmp/myVideo.mp4`). Must specify either **File URL** or **File Path**.", + type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, onBehalfOfContentOwner: { propDefinition: [ diff --git a/components/youtube_data_api/actions/upload-thumbnail/common.mjs b/components/youtube_data_api/actions/upload-thumbnail/common.mjs index 797e3b6c188c2..2d9705034ecbb 100644 --- a/components/youtube_data_api/actions/upload-thumbnail/common.mjs +++ b/components/youtube_data_api/actions/upload-thumbnail/common.mjs @@ -1,16 +1,9 @@ -import fs from "fs"; -import got from "got"; -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStream } from "@pipedream/platform"; export default { async run({ $ }) { - if ((!this.fileUrl && !this.filePath) || (this.fileUrl && this.filePath)) { - throw new ConfigurationError("This action requires either `File URL` or `File Path`. Please enter one or the other above."); - } + const body = await getFileStream(this.filePath); - const body = this.fileUrl - ? await got.stream(this.fileUrl) - : fs.createReadStream(this.filePath); const params = { videoId: this.videoId, onBehalfOfContentOwner: this.onBehalfOfContentOwner, diff --git a/components/youtube_data_api/actions/upload-thumbnail/upload-thumbnail.mjs b/components/youtube_data_api/actions/upload-thumbnail/upload-thumbnail.mjs index 3dc9f1c72ba2b..85f13a0ef4087 100644 --- a/components/youtube_data_api/actions/upload-thumbnail/upload-thumbnail.mjs +++ b/components/youtube_data_api/actions/upload-thumbnail/upload-thumbnail.mjs @@ -6,7 +6,7 @@ export default { key: "youtube_data_api-upload-thumbnail", name: "Upload Thumbnail", description: "Uploads a custom video thumbnail to YouTube and sets it for a video. Note: Account must be [verified](https://www.youtube.com/verify). [See the documentation](https://developers.google.com/youtube/v3/docs/thumbnails/set) for more information", - version: "0.0.3", + version: "1.0.0", type: "action", props: { youtubeDataApi, @@ -21,19 +21,10 @@ export default { "userOwnedVideo", ], }, - fileUrl: { - propDefinition: [ - youtubeDataApi, - "fileUrl", - ], - description: "The URL of the thumbnail image file you want to upload to YouTube. Must specify either **File URL** or **File Path**.", - }, filePath: { - propDefinition: [ - youtubeDataApi, - "filePath", - ], - description: "Path to the thumbnail image file to upload (e.g., `/tmp/myVideo.mp4`). Must specify either **File URL** or **File Path**.", + type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, onBehalfOfContentOwner: { propDefinition: [ diff --git a/components/youtube_data_api/actions/upload-video/common.mjs b/components/youtube_data_api/actions/upload-video/common.mjs index 7e97cde3ce2a8..716f798b4dc02 100644 --- a/components/youtube_data_api/actions/upload-video/common.mjs +++ b/components/youtube_data_api/actions/upload-video/common.mjs @@ -1,11 +1,8 @@ -import fs from "fs"; -import got from "got"; -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStream } from "@pipedream/platform"; export default { async run({ $ }) { const { - fileUrl, filePath, title, description, @@ -14,12 +11,9 @@ export default { tags, notifySubscribers, } = this; - if ((!fileUrl && !filePath) || (fileUrl && filePath)) { - throw new ConfigurationError("This action requires either `File URL` or `File Path`. Please enter one or the other above."); - } - const body = fileUrl - ? await got.stream(fileUrl) - : fs.createReadStream(filePath); + + const body = await getFileStream(filePath); + const { data: resp } = await this.youtubeDataApi.insertVideo({ title, description, diff --git a/components/youtube_data_api/actions/upload-video/upload-video.mjs b/components/youtube_data_api/actions/upload-video/upload-video.mjs index e5255964eeed4..74ed8b2f0247b 100644 --- a/components/youtube_data_api/actions/upload-video/upload-video.mjs +++ b/components/youtube_data_api/actions/upload-video/upload-video.mjs @@ -6,7 +6,7 @@ export default { key: "youtube_data_api-upload-video", name: "Upload Video", description: "Post a video to your channel. [See the documentation](https://developers.google.com/youtube/v3/docs/videos/insert) for more information", - version: "0.0.7", + version: "1.0.0", type: "action", props: { youtubeDataApi, @@ -22,17 +22,10 @@ export default { "description", ], }, - fileUrl: { - propDefinition: [ - youtubeDataApi, - "fileUrl", - ], - }, filePath: { - propDefinition: [ - youtubeDataApi, - "filePath", - ], + type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, privacyStatus: { propDefinition: [ diff --git a/components/youtube_data_api/package.json b/components/youtube_data_api/package.json index 98acd3bf9f574..2fe0ec674245d 100644 --- a/components/youtube_data_api/package.json +++ b/components/youtube_data_api/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/youtube_data_api", - "version": "0.6.2", + "version": "1.0.0", "description": "Pipedream Youtube Components", "main": "youtube_data_api.app.mjs", "keywords": [ @@ -11,7 +11,7 @@ "author": "Pipedream (https://pipedream.com/)", "dependencies": { "@googleapis/youtube": "^6.0.0", - "@pipedream/platform": "^3.0.3", + "@pipedream/platform": "^3.1.0", "got": "^14.4.6", "util": "^0.12.4" }, diff --git a/components/zoho_workdrive/actions/upload-file/upload-file.mjs b/components/zoho_workdrive/actions/upload-file/upload-file.mjs index 4024bfbf34555..72ff6d3ae835b 100644 --- a/components/zoho_workdrive/actions/upload-file/upload-file.mjs +++ b/components/zoho_workdrive/actions/upload-file/upload-file.mjs @@ -1,13 +1,11 @@ -import { ConfigurationError } from "@pipedream/platform"; +import { getFileStreamAndMetadata } from "@pipedream/platform"; import FormData from "form-data"; -import fs from "fs"; -import { getFilePath } from "../../common/utils.mjs"; import app from "../../zoho_workdrive.app.mjs"; export default { key: "zoho_workdrive-upload-file", name: "Upload File", - version: "0.0.3", + version: "0.0.5", description: "Upload a new file to your WorkDrive account. [See the documentation](https://workdrive.zoho.com/apidocs/v1/chunkupload/chunkuploadcreatesession)", type: "action", props: { @@ -49,27 +47,28 @@ export default { optional: true, }, content: { - label: "File Path", - description: "Full path to the file in `/tmp/` directory. E.g. `/tmp/file.jpg`", type: "string", + label: "File Path or URL", + description: "Provide either a file URL or a path to a file in the /tmp directory (for example, /tmp/myFile.pdf).", }, }, async run({ $ }) { - const path = getFilePath(this.content); - if (!fs.existsSync(path)) { - throw new ConfigurationError("File does not exist!"); - } - const file = fs.createReadStream(path); + const { + stream, metadata, + } = await getFileStreamAndMetadata(this.content); const data = new FormData(); + data.append("content", stream, { + contentType: metadata.contentType, + knownLength: metadata.size, + filename: metadata.name, + }); const override = this.overrideNameExist?.toString(); - data.append("content", file); data.append("parent_id", this.parentId); - if (this.filename)data.append("filename", this.filename); - if (override)data.append("override-name-exist", override); + if (this.filename) data.append("filename", this.filename); + if (override) data.append("override-name-exist", override); const response = await this.app.uploadFile({ - $, data, headers: { "Content-Type": `multipart/form-data; boundary=${data._boundary}`, diff --git a/components/zoho_workdrive/package.json b/components/zoho_workdrive/package.json index d361bdf9bb8b2..1344afb5ec579 100644 --- a/components/zoho_workdrive/package.json +++ b/components/zoho_workdrive/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/zoho_workdrive", - "version": "0.2.2", + "version": "0.2.3", "description": "Pipedream Zoho WorkDrive Components", "main": "zoho_workdrive.app.mjs", "keywords": [ @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^1.5.1", + "@pipedream/platform": "^3.1.0", "axios": "^1.5.1", "form-data": "^4.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e6c1739ef51b0..ed376735740b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -871,8 +871,8 @@ importers: components/api4ai: dependencies: '@pipedream/platform': - specifier: ^1.6.2 - version: 1.6.6 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -3904,6 +3904,9 @@ importers: components/dropbox: dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 '@types/node-fetch': specifier: ^2.5.7 version: 2.6.12 @@ -4124,8 +4127,8 @@ importers: components/elevenlabs: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -6838,8 +6841,8 @@ importers: components/jira: dependencies: '@pipedream/platform': - specifier: ^3.0.1 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -8266,8 +8269,8 @@ importers: components/microsoft_outlook: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 axios: specifier: ^0.21.1 version: 0.21.4 @@ -12714,8 +12717,8 @@ importers: components/speechace: dependencies: '@pipedream/platform': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -12790,8 +12793,8 @@ importers: components/spotlightr: dependencies: '@pipedream/platform': - specifier: ^1.5.1 - version: 1.6.6 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -13004,8 +13007,8 @@ importers: components/supabase: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 '@supabase/supabase-js': specifier: ^2.45.6 version: 2.46.1 @@ -13169,8 +13172,8 @@ importers: components/syncmate_by_assitro: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 components/syncro: {} @@ -13417,8 +13420,8 @@ importers: components/testmonitor: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 fs: specifier: ^0.0.1-security version: 0.0.1-security @@ -13476,8 +13479,8 @@ importers: components/the_bookie: dependencies: '@pipedream/platform': - specifier: ^3.0.1 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 components/the_magic_drip: dependencies: @@ -13605,8 +13608,8 @@ importers: components/timetonic: dependencies: '@pipedream/platform': - specifier: ^1.6.5 - version: 1.6.6 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -13761,8 +13764,8 @@ importers: components/transifex: dependencies: '@pipedream/platform': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^3.1.0 + version: 3.1.0 fs: specifier: ^0.0.1-security version: 0.0.1-security @@ -13798,8 +13801,8 @@ importers: components/trello: dependencies: '@pipedream/platform': - specifier: ^3.0.1 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 crypto: specifier: ^1.0.1 version: 1.0.1 @@ -13860,8 +13863,8 @@ importers: components/trust: dependencies: '@pipedream/platform': - specifier: ^3.0.0 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -13979,8 +13982,8 @@ importers: components/twitter: dependencies: '@pipedream/platform': - specifier: ^1.5.1 - version: 1.6.6 + specifier: ^3.1.0 + version: 3.1.0 '@pipedream/types': specifier: ^0.1.4 version: 0.1.6 @@ -14263,8 +14266,8 @@ importers: components/vapi: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.1 version: 4.0.1 @@ -14668,8 +14671,8 @@ importers: components/what_are_those: dependencies: '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 components/what_converts: dependencies: @@ -14692,8 +14695,8 @@ importers: components/whatsapp_business: dependencies: '@pipedream/platform': - specifier: ^1.2.0 - version: 1.6.6 + specifier: ^3.1.0 + version: 3.1.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -14862,6 +14865,9 @@ importers: components/wordpress_org: dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 lodash.pickby: specifier: ^4.6.0 version: 4.6.0 @@ -15120,8 +15126,8 @@ importers: specifier: ^6.0.0 version: 6.0.0 '@pipedream/platform': - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 got: specifier: ^14.4.6 version: 14.4.6 @@ -15494,8 +15500,8 @@ importers: components/zoho_workdrive: dependencies: '@pipedream/platform': - specifier: ^1.5.1 - version: 1.6.6 + specifier: ^3.1.0 + version: 3.1.0 axios: specifier: ^1.5.1 version: 1.7.7 @@ -15835,7 +15841,7 @@ importers: version: 3.1.7 ts-jest: specifier: ^29.2.5 - version: 29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0))(typescript@5.7.2) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0))(typescript@5.7.2) tsup: specifier: ^8.3.6 version: 8.3.6(@microsoft/api-extractor@7.47.12(@types/node@20.17.30))(jiti@1.21.6)(postcss@8.4.49)(tsx@4.19.4)(typescript@5.7.2)(yaml@2.6.1) @@ -15878,7 +15884,7 @@ importers: version: 3.1.0 jest: specifier: ^29.1.2 - version: 29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0) + version: 29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0) type-fest: specifier: ^4.15.0 version: 4.27.0 @@ -49799,7 +49805,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0))(typescript@5.7.2): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0))(typescript@5.7.2): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -49813,10 +49819,10 @@ snapshots: typescript: 5.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 8.0.0-alpha.13 + '@babel/core': 7.26.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@8.0.0-alpha.13) + babel-jest: 29.7.0(@babel/core@7.26.0) ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.6.3): dependencies: