Skip to content

Part 2 - applying File URL or Path improvements #17091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 53 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
1aef040
pnpm
GTFalcao Jun 5, 2025
3d6ce07
Updating _2markdown and mapbox
GTFalcao Jun 5, 2025
54a0c8d
Akeneo and LLMWhisperer apps
GTFalcao Jun 5, 2025
49b328f
pnpm
GTFalcao Jun 5, 2025
d174051
add: askyourpdf
GTFalcao Jun 6, 2025
9e11477
add: fileforge
GTFalcao Jun 6, 2025
8a57ff3
adjusting existing descriptions and platform versions
GTFalcao Jun 6, 2025
9bf8aad
Description updates
GTFalcao Jun 6, 2025
c104045
add: microsoft_onedrive, mistral_ai, onlyoffice_docspace
GTFalcao Jun 6, 2025
5624c24
add: slack
GTFalcao Jun 6, 2025
fe3bb7e
add: stannp, zamzar, zoho_desk
GTFalcao Jun 6, 2025
fed67fa
add box upload-file
GTFalcao Jun 6, 2025
b560b05
add: monday, nyckel
GTFalcao Jun 6, 2025
04ae59a
add: ocrspace
GTFalcao Jun 6, 2025
69bbb92
add: onlinecheckwriter, pandadoc, pdf4me
GTFalcao Jun 7, 2025
094bf97
Onedrive adjustment
GTFalcao Jun 9, 2025
0107ed6
pnpm
GTFalcao Jun 9, 2025
8aa2266
adjusting Slack and Pandadoc
GTFalcao Jun 9, 2025
ed11f6e
updates to include metadata in all formdatas
GTFalcao Jun 9, 2025
1afc1fa
pnpm
GTFalcao Jun 9, 2025
c0438fb
fix
GTFalcao Jun 10, 2025
055a2e4
pnpm
GTFalcao Jun 10, 2025
b6a68ad
CodeRabbit fixes
GTFalcao Jun 10, 2025
9158a07
Fixing box and nyckel
GTFalcao Jun 10, 2025
c34250f
fix mapbox
GTFalcao Jun 10, 2025
13d0e9f
add: autodesk, cradl_ai, docsbot_ai
GTFalcao Jun 10, 2025
3021054
pnpm
GTFalcao Jun 10, 2025
1192865
add: egnyte, flippingbook
GTFalcao Jun 11, 2025
38a9f0d
add: happy_scribe, ilovepdf
GTFalcao Jun 11, 2025
6106cd9
add: lokalise, podio, zoho_crm
GTFalcao Jun 11, 2025
9aa479e
add: openai, imagga
GTFalcao Jun 11, 2025
70082f3
add: google_drive
GTFalcao Jun 11, 2025
0ea7b35
add: openai (remaining actions)
GTFalcao Jun 11, 2025
5d5eb5f
add: airparser, alttext_ai
GTFalcao Jun 12, 2025
e09ce7e
add: azure_storage, boldsign
GTFalcao Jun 12, 2025
d8b5d3c
add: canva
GTFalcao Jun 12, 2025
c90462e
add: claid_ai
GTFalcao Jun 12, 2025
e89430f
Merge branch 'master' into 16977-applying-fileurl-paths-improvement
GTFalcao Jun 12, 2025
46fd256
Merge branch 'master' into 16977-part-2
GTFalcao Jun 12, 2025
ade6f85
update package.json
GTFalcao Jun 12, 2025
d8e872a
pdf4me: readding std filename check to action
GTFalcao Jun 12, 2025
5b7ca8c
Adjusting zoho_desk formdata building
GTFalcao Jun 13, 2025
86cb294
Merge branch 'master' into 16977-applying-fileurl-paths-improvement
GTFalcao Jun 14, 2025
648cc42
Merge branch 'master' into 16977-applying-fileurl-paths-improvement
GTFalcao Jun 14, 2025
2f07169
Merge branch 'master' into 16977-part-2
GTFalcao Jun 14, 2025
c30b8b9
pnpm
GTFalcao Jun 14, 2025
1b5c444
Merge branch '16977-applying-fileurl-paths-improvement' into 16977-pa…
GTFalcao Jun 14, 2025
7f2bceb
fix: alttext_ai, box
GTFalcao Jun 16, 2025
fab27d8
description improvements: docsbot_ai, lokalise
GTFalcao Jun 17, 2025
a0bc8d7
fix: openai
GTFalcao Jun 17, 2025
b1a6f91
Improving OpenAI image handling
GTFalcao Jun 17, 2025
d92f622
openai-chat fixes
GTFalcao Jun 17, 2025
637447e
Merge branch 'master' into 16977-part-2
GTFalcao Jun 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions components/_2markdown/_2markdown.app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export default {
propDefinitions: {
filePath: {
type: "string",
label: "File Path",
description: "The path to an HTML 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: "An HTML file. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myFile.html`)",
},
},
methods: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import _2markdown from "../../_2markdown.app.mjs";
import fs from "fs";
import { getFileStreamAndMetadata } from "@pipedream/platform";
import FormData from "form-data";

export default {
key: "_2markdown-html-file-to-markdown",
name: "HTML File to Markdown",
description: "Convert an HTML file to Markdown format. [See the documentation](https://2markdown.com/docs#file2md)",
version: "0.0.1",
version: "0.1.0",
type: "action",
props: {
_2markdown,
Expand All @@ -20,9 +20,14 @@ export default {
async run({ $ }) {
const form = new FormData();

form.append("document", fs.createReadStream(this.filePath.includes("tmp/")
? this.filePath
: `/tmp/${this.filePath}`));
const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filePath);
form.append("document", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});

const response = await this._2markdown.htmlFileToMarkdown({
$,
Expand Down
17 changes: 11 additions & 6 deletions components/_2markdown/actions/pdf-to-markdown/pdf-to-markdown.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import _2markdown from "../../_2markdown.app.mjs";
import fs from "fs";
import { getFileStreamAndMetadata } from "@pipedream/platform";
import FormData from "form-data";

export default {
key: "_2markdown-pdf-to-markdown",
name: "PDF to Markdown",
description: "Convert a PDF document to Markdown format. [See the documentation](https://2markdown.com/docs#pdf2md)",
version: "0.0.1",
version: "0.1.0",
type: "action",
props: {
_2markdown,
Expand All @@ -15,7 +15,7 @@ export default {
_2markdown,
"filePath",
],
description: "The path to a PDF 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: "A PDF file. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myFile.pdf`)",
},
waitForCompletion: {
type: "boolean",
Expand All @@ -27,9 +27,14 @@ export default {
async run({ $ }) {
const form = new FormData();

form.append("document", fs.createReadStream(this.filePath.includes("tmp/")
? this.filePath
: `/tmp/${this.filePath}`));
const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filePath);
form.append("document", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});

let response = await this._2markdown.pdfToMarkdown({
$,
Expand Down
4 changes: 2 additions & 2 deletions components/_2markdown/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/_2markdown",
"version": "0.1.0",
"version": "0.2.0",
"description": "Pipedream 2markdown Components",
"main": "_2markdown.app.mjs",
"keywords": [
Expand All @@ -13,7 +13,7 @@
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.0.3",
"@pipedream/platform": "^3.1.0",
"form-data": "^4.0.1"
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import airparser from "../../airparser.app.mjs";
import fs from "fs";
import { getFileStreamAndMetadata } from "@pipedream/platform";
import FormData from "form-data";

export default {
key: "airparser-upload-document-parse",
name: "Upload Document and Parse",
description: "Uploads a document into the inbox for data extraction. [See the documentation](https://help.airparser.com/public-api/public-api)",
version: "0.0.1",
version: "0.1.0",
type: "action",
props: {
airparser,
Expand All @@ -18,8 +18,8 @@ export default {
},
filePath: {
type: "string",
label: "File Path",
description: "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).",
label: "File Path or URL",
description: "The file to upload. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myFile.txt`)",
},
metadata: {
type: "object",
Expand All @@ -29,11 +29,15 @@ export default {
},
},
async run({ $ }) {
const fileStream = fs.createReadStream(this.filePath.includes("tmp/")
? this.filePath
: `/tmp/${this.filePath}`);
const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filePath);
const data = new FormData();
data.append("file", fileStream);
data.append("file", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});
Comment on lines +32 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Wrap file-stream retrieval in try/catch and validate metadata

getFileStreamAndMetadata() throws for 404/invalid URLs. Wrapping it provides clearer, action-specific errors:

-const { stream, metadata } = await getFileStreamAndMetadata(this.filePath);
+let stream, metadata;
+try {
+  ({ stream, metadata } = await getFileStreamAndMetadata(this.filePath));
+} catch (err) {
+  throw new Error(`Failed to fetch file "${this.filePath}": ${err.message}`);
+}

Also only set knownLength when metadata.size is defined to prevent form-data errors.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filePath);
const data = new FormData();
data.append("file", fileStream);
data.append("file", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});
// Wrap file‐stream retrieval in try/catch for clearer, action‐specific errors
let stream, metadata;
try {
({ stream, metadata } = await getFileStreamAndMetadata(this.filePath));
} catch (err) {
throw new Error(`Failed to fetch file "${this.filePath}": ${err.message}`);
}
const data = new FormData();
data.append("file", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});
🤖 Prompt for AI Agents
In components/airparser/actions/upload-document-parse/upload-document-parse.mjs
around lines 32 to 40, wrap the call to getFileStreamAndMetadata(this.filePath)
in a try/catch block to handle errors like 404 or invalid URLs gracefully and
provide clearer error messages. Additionally, when appending the file stream to
FormData, only set the knownLength property if metadata.size is defined to avoid
errors from the form-data library.

if (this.metadata) {
data.append("meta", JSON.stringify(this.metadata));
}
Expand Down
4 changes: 2 additions & 2 deletions components/airparser/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/airparser",
"version": "0.1.0",
"version": "0.2.0",
"description": "Pipedream Airparser Components",
"main": "airparser.app.mjs",
"keywords": [
Expand All @@ -13,7 +13,7 @@
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^1.6.0",
"@pipedream/platform": "^3.1.0",
"form-data": "^4.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import app from "../../akeneo.app.mjs";
import utils from "../../common/utils.mjs";
import { ConfigurationError } from "@pipedream/platform";
import {
ConfigurationError, getFileStreamAndMetadata,
} from "@pipedream/platform";
import FormData from "form-data";
import fs from "fs";

export default {
type: "action",
key: "akeneo-create-a-new-product-media-file",
version: "0.0.1",
version: "0.1.0",
name: "Create A New Product Media File",
description: "Allows you to create a new media file and associate it to an attribute value of a given product or product model. [See the docs](https://api.akeneo.com/api-reference.html#post_media_files)",
props: {
Expand All @@ -32,18 +32,15 @@ export default {
},
filename: {
type: "string",
label: "File",
description: "The file to be uploaded, please provide a file from `/tmp`. 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: "The file to be uploaded. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myFile.txt`)",
},
},
async run ({ $ }) {
if (!this.productId && !this.productModelCode) {
throw new ConfigurationError("Either `Product Identifier` or `Product Model Code` should be set!");
}
const path = utils.checkTmp(this.filename);
if (!fs.existsSync(path)) {
throw new ConfigurationError("File does not exist!");
}

const payload = {
attribute: this.mediaFileAttributeCode,
scope: null,
Expand All @@ -57,9 +54,15 @@ export default {
payload.code = this.productModelCode;
data.append("product_model", JSON.stringify(payload));
}
const file = fs.readFileSync(path);
const fileParts = path.split("/");
data.append("file", file, fileParts[fileParts.length - 1]);

const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filename);
data.append("file", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});
const contentLength = data.getLengthSync();
Comment on lines +58 to 66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

getLengthSync may throw when metadata.size is unknown

For remote URLs where Content-Length isn’t returned, metadata.size can be undefined, causing form-data’s getLengthSync() to fail.

Safer approach:

-const contentLength = data.getLengthSync();
+const contentLength = await new Promise((res, rej) =>
+  data.getLength((err, len) => err ? rej(err) : res(len)));

and omit knownLength when metadata.size is falsy.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filename);
data.append("file", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});
const contentLength = data.getLengthSync();
const {
stream, metadata,
} = await getFileStreamAndMetadata(this.filename);
data.append("file", stream, {
contentType: metadata.contentType,
knownLength: metadata.size,
filename: metadata.name,
});
- const contentLength = data.getLengthSync();
+ const contentLength = await new Promise((res, rej) =>
+ data.getLength((err, len) => err ? rej(err) : res(len)));
🤖 Prompt for AI Agents
In
components/akeneo/actions/create-a-new-product-media-file/create-a-new-product-media-file.mjs
around lines 58 to 66, the call to data.getLengthSync() may throw an error if
metadata.size is undefined because knownLength is set to metadata.size. To fix
this, only include the knownLength property in the data.append call if
metadata.size is truthy; otherwise, omit it. This prevents getLengthSync from
failing when the file size is unknown.

await this.app.createProductMediaFile({
$,
Expand Down
4 changes: 2 additions & 2 deletions components/akeneo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/akeneo",
"version": "0.0.2",
"version": "0.1.0",
"description": "Pipedream Akeneo Components",
"main": "akeneo.app.mjs",
"keywords": [
Expand All @@ -10,7 +10,7 @@
"homepage": "https://pipedream.com/apps/akeneo",
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
"dependencies": {
"@pipedream/platform": "^1.3.0",
"@pipedream/platform": "^3.1.0",
"form-data": "^4.0.0"
},
"publishConfig": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import alttextAi from "../../alttext_ai.app.mjs";
import fs from "fs";
import {
ConfigurationError, getFileStream,
} from "@pipedream/platform";
import { LANGUAGE_OPTIONS } from "../../commons/constants.mjs";
import { ConfigurationError } from "@pipedream/platform";

export default {
key: "alttext_ai-generate-alt-text",
name: "Generate Alt Text",
description:
"Generates a descriptive alt text for a given image. [See the documentation](https://alttext.ai/apidocs#tag/Images/operation/create-image)",
version: "0.0.1",
version: "0.1.0",
type: "action",
props: {
alttextAi,
fileInfo: {

Check warning on line 16 in components/alttext_ai/actions/generate-alt-text/generate-alt-text.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop fileInfo must have a description. See https://pipedream.com/docs/components/guidelines/#props

Check warning on line 16 in components/alttext_ai/actions/generate-alt-text/generate-alt-text.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop fileInfo must have a label. See https://pipedream.com/docs/components/guidelines/#props
type: "alert",
alertType: "warning",
content: "Either `Image Data` or `Image File Path or URL` should be provided. If both are provided, `Image Data` will be used.",
},
imageData: {
type: "string",
label: "Image Data",
description:
"The image data in base64 format. Only one of `Image Data`, `Image File Path` or `Image URL` should be specified.",
optional: true,
},
imageUrl: {
type: "string",
label: "Image URL",
description:
"The public URL to an image. Only one of `Image URL`, `Image Data` or `Image File Path` should be specified.",
"The image data in base64 format",
optional: true,
},
imageFilePath: {
type: "string",
label: "Image File Path",
label: "Image File Path or URL",
description:
"The path to an image file in the `/tmp` directory. [See the documentation on working with files](https://pipedream.com/docs/code/nodejs/working-with-files/#the-tmp-directory). Only one of `Image File Path`, `Image URL` or `Image Data` should be specified.",
"The image to process. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myImage.jpg`)",
optional: true,
},
keywords: {
Expand Down Expand Up @@ -64,31 +63,29 @@
},
},
async run({ $ }) {
if (
(!this.imageData && !this.imageFilePath && !this.imageUrl)
|| (this.imageData && this.imageFilePath)
|| (this.imageData && this.imageUrl)
|| (this.imageFilePath && this.imageUrl)
) {
throw new ConfigurationError("Only one of `Image Data`, `Image File Path` or `Image URL` should be specified.");
const {
imageData, imageFilePath,
} = this;
if (!imageData && !imageFilePath) {
throw new ConfigurationError("Either `Image Data` or `Image File Path or URL` should be specified.");
}

let rawData = imageData;
if (!rawData) {
const stream = await getFileStream(imageFilePath);
const chunks = [];
for await (const chunk of stream) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);
rawData = buffer.toString("base64");
}

const response = await this.alttextAi.generateAltText({
$,
data: {
image: {
url: this.imageUrl,
raw:
this.imageData ??
(this.imageFilePath &&
fs.readFileSync(
this.imageFilePath.includes("tmp/")
? this.imageFilePath
: `/tmp/${this.imageFilePath}`,
{
encoding: "base64",
},
)),
raw: rawData,
},
keywords: this.keywords,
negative_keywords: this.negativeKeywords,
Expand Down
4 changes: 2 additions & 2 deletions components/alttext_ai/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/alttext_ai",
"version": "0.1.0",
"version": "0.2.0",
"description": "Pipedream AltText.ai Components",
"main": "alttext_ai.app.mjs",
"keywords": [
Expand All @@ -13,6 +13,6 @@
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^1.5.1"
"@pipedream/platform": "^3.1.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ export default {
name: "Add Document Via File Upload",
description: "Add a document via file upload. [See the documentation](https://docs.askyourpdf.com/askyourpdf-docs/#2.-adding-document-via-file-upload)",
type: "action",
version: "0.0.2",
version: "0.1.0",
props: {
app,
file: {
type: "string",
label: "File Path",
description: "File path of a file previously downloaded in Pipedream E.g. (`/tmp/my-file.txt`). [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: "The file to upload. Provide either a file URL or a path to a file in the `/tmp` directory (for example, `/tmp/myFile.txt`)",
},
},
methods: {
Expand Down
6 changes: 3 additions & 3 deletions components/askyourpdf/askyourpdf.app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ export default {
...headers,
};
},
getConfig({
async getConfig({
headers, data: preData, ...args
} = {}) {
const contentType = constants.CONTENT_TYPE_KEY_HEADER;
const hasMultipartHeader = utils.hasMultipartHeader(headers);
const data = hasMultipartHeader && utils.getFormData(preData) || preData;
const data = hasMultipartHeader && await utils.getFormData(preData) || preData;
const currentHeaders = this.getHeaders(headers);

return {
Expand All @@ -49,7 +49,7 @@ export default {
async makeRequest({
step = this, path, headers, data, summary, ...args
} = {}) {
const config = this.getConfig({
const config = await this.getConfig({
url: this.getUrl(path),
headers,
data,
Expand Down
Loading
Loading