-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[COMPONENTS] wordpress_com. Actions + sources #16461
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
Conversation
|
@SokolovskyiK is attempting to deploy a commit to the Pipedreamers Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
WalkthroughThis update introduces comprehensive WordPress.com integration, adding new polling sources for new posts, comments, and followers, along with actions to create posts, upload media, and delete posts. Core utility and validation modules are added to support robust input handling and error management. The WordPress.com app methods are expanded to include API interactions for posts, media, comments, and followers. Documentation is updated to reflect all new features, and the package version is incremented with a new dependency for form-data handling. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Action/Source
participant WordPressApp
participant WordPressAPI
User->>Action/Source: Triggers action/source (e.g., Create Post, Poll New Post)
Action/Source->>WordPressApp: Validate input, prepare request
WordPressApp->>WordPressAPI: Make REST API call (create, fetch, upload, delete)
WordPressAPI-->>WordPressApp: Return API response
WordPressApp-->>Action/Source: Return result or data
Action/Source-->>User: Emit event or return action result
Assessment against linked issues
Suggested reviewers
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
components/wordpress_com/actions/upload-media/upload-media.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (3)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
🧹 Nitpick comments (11)
components/wordpress_com/actions/delete-post.mjs (2)
7-7: Improve action description.The current description "Delete post" is too brief and doesn't provide enough context.
- description: "Delete post", + description: "Deletes an existing post or page from your WordPress.com site.",
33-35: Remove unnecessary blank line.The blank line at line 33 is not needed and should be removed for consistent code style.
} = this; - warnings.push(...wordpress.checkDomainOrId(site));components/wordpress_com/actions/create-post.mjs (2)
60-60: Remove testing comment.The comment "// TEST" should be removed as it appears to be leftover debugging code.
- warnings.push(...wordpress.checkDomainOrId(site)); // TEST + warnings.push(...wordpress.checkDomainOrId(site));
65-65: Remove testing comment.Another "// TEST" comment should be removed.
- response = await wordpress.createWordpressPost({ //TEST + response = await wordpress.createWordpressPost({components/wordpress_com/actions/upload-media.mjs (2)
59-72:isFormDatabranch always logs a warningBoth branches push a warning (
"Media was received as multipart/form-data"vs"Media was received as URL").
Warnings are concatenated into the$summary; if the user supplied correct input they still get a warning, which is misleading.Consider pushing these messages only when the condition may indicate unexpected input, or label them as info logs instead of warnings.
85-88: Avoid undefined summary pieces when no warnings or title
media.titleandwarningscan beundefined/ empty.
Guard them to keep the exported summary tidy.-$.export("$summary", `Media "${media.title}" uploaded successfully (ID: ${media.ID})` + "\n- " + warnings.join("\n- ")); +const summaryLines = [ + `Media "${media?.title ?? "untitled"}" uploaded successfully (ID: ${media?.ID})`, + ...(warnings.length ? ["Warnings:\n- " + warnings.join("\n- ")] : []), +]; +$.export("$summary", summaryLines.join("\n"));components/wordpress_com/wordpress_com.app.mjs (1)
60-63: Comment states POST is used instead of DELETE in a GET requestThe comment appears copy-pasted and confuses readers:
method: "GET", // use POST instead of DELETE. Wordpress does not allow DELETE methods on free accounts.Update or remove the misleading comment.
components/wordpress_com/sources/new-comment.mjs (1)
85-92: Be cautious with array mutation in the filtering logic.The code is using
.reverse()which mutates the originalcommentsarray. This could have unexpected side effects if the array is used elsewhere after this operation.Consider creating a separate array:
-for (const comment of comments.reverse()) { +const reversedComments = [...comments].reverse(); +for (const comment of reversedComments) {components/wordpress_com/common/methods.mjs (3)
89-90: Fix typo in variable name.The variable is misspelled as "warings" instead of "warnings".
- const warings = []; + const warnings = [];
297-300: Remove incomplete comment.There's an incomplete comment at the end of the file.
-/* =================================================================================================== - If -====================================================================================================== */ -
152-153: Fix typo in comment.The comment contains a typo: "Warnin" instead of "Warning".
- // Warnin accumulator + // Warning accumulator
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
components/wordpress_com/README.md(1 hunks)components/wordpress_com/actions/create-post.mjs(1 hunks)components/wordpress_com/actions/delete-post.mjs(1 hunks)components/wordpress_com/actions/upload-media.mjs(1 hunks)components/wordpress_com/common/methods.mjs(1 hunks)components/wordpress_com/common/utils.mjs(1 hunks)components/wordpress_com/package.json(1 hunks)components/wordpress_com/sources/new-comment.mjs(1 hunks)components/wordpress_com/sources/new-follower.mjs(1 hunks)components/wordpress_com/sources/new-post.mjs(1 hunks)components/wordpress_com/wordpress_com.app.mjs(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Components Checks
components/wordpress_com/package.json
[error] 1-1: pnpm install failed due to outdated lockfile. The pnpm-lock.yaml is not up to date with package.json dependencies. Specifically, lockfile specifiers ({"@pipedream/platform":"^3.0.0"}) do not match package.json specs ({"@pipedream/platform":"^3.0.0","form-data":"^4.0.2"}).
🪛 GitHub Actions: Pull Request Checks
components/wordpress_com/package.json
[error] 1-1: pnpm install failed due to outdated lockfile. The pnpm-lock.yaml is not up to date with package.json dependencies. Specifically, lockfile specifiers do not match package.json specs.
🪛 Biome (1.9.4)
components/wordpress_com/common/methods.mjs
[error] 175-175: A character class cannot match a joined character sequence.
A zero width joiner composes several emojis into a new one. Replace the character class with an alternation.
(lint/suspicious/noMisleadingCharacterClass)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: pnpm publish
🔇 Additional comments (7)
components/wordpress_com/README.md (1)
12-41: Well-structured documentation for the new WordPress.com features.The documentation clearly outlines the new event sources and actions, making it easy for users to understand what functionality is available and how to use it. Good job providing the required and optional properties for each component.
components/wordpress_com/actions/upload-media.mjs (1)
80-82:❌ Incorrect review comment
Missing safety-check for
form.getHeaders()
form.getHeaders()exists only forform-datainstances.
When the user passes a plain object that merely quacks like FormData, this will throw.Add a defensive check:
- contentType : form.getHeaders()["content-type"], + const headers = form.getHeaders?.() || {}; + contentType : headers["content-type"] || "multipart/form-data",
🏁 Script executed:
#!/bin/bash # Search for usage of form.getHeaders rg -n "form.getHeaders" -A2 -B2 components/wordpress_com/actions/upload-media.mjs # Show function signature and where 'form' comes from rg -n "uploadMedia" -A10 -B3 components/wordpress_com/actions/upload-media.mjs # Inspect FormData import rg -n "FormData" -n components/wordpress_com/actions/upload-media.mjsLength of output: 567
🏁 Script executed:
#!/bin/bash # Display the first 200 lines to inspect how `form` is assigned and used sed -n '1,200p' components/wordpress_com/actions/upload-media.mjsLength of output: 2228
🏁 Script executed:
#!/bin/bash # Find and display definition of isFormData in wordpress_com.app.mjs rg -n "isFormData" -A5 -B5 components/wordpress_com/wordpress_com.app.mjs # Output common/utils.mjs to inspect prepareMediaUpload sed -n '1,200p' components/common/utils.mjsLength of output: 188
🏁 Script executed:
#!/bin/bash # Inspect prepareMediaUpload implementation sed -n '1,200p' components/wordpress_com/common/utils.mjs # Inspect wordpress_com.app.mjs to find isFormData definition sed -n '1,200p' components/wordpress_com/wordpress_com.app.mjsLength of output: 5818
🏁 Script executed:
#!/bin/bash # Locate isFormData definition in wordpress_com common methods rg -n "isFormData" -A5 -B5 components/wordpress_com/common/methods.mjs # Show the first 200 lines of methods.mjs for additional context sed -n '1,200p' components/wordpress_com/common/methods.mjsLength of output: 6355
Redundant safety check for
form.getHeaders()
Theformvariable is guaranteed to have a.getHeaders()method because it’s either:
- A user-provided object that passed
isFormData()(which requirestypeof input.getHeaders === "function"), or- A
FormDatainstance created byprepareMediaUpload(theform-datapackage’s FormData also implementsgetHeaders).Adding an extra
getHeaders?.()guard is unnecessary here.Likely an incorrect or invalid review comment.
components/wordpress_com/wordpress_com.app.mjs (1)
12-18:⚠️ Potential issueDefault parameter uses
thisbefore binding
thisis not yet bound while evaluating default parameter values, so
$ = thiswill resolve toundefinedin strict mode. Axios will then throw.Refactor to supply
$explicitly:-_makeRequest({ - $ = this, - url, - contentType, - ...opts -}) { +_makeRequest({ $, url, contentType, ...opts }) { + // require callers to pass `$`All internal callers already pass
$, so this is a safe change.Likely an incorrect or invalid review comment.
components/wordpress_com/sources/new-post.mjs (1)
1-121: Well-structured polling source component for WordPress.com new posts.The implementation effectively tracks and emits events for new WordPress.com posts, handling various post types and maintaining state correctly. The cursor-based approach ensures no duplicate emissions while properly tracking the highest seen post ID.
components/wordpress_com/sources/new-comment.mjs (1)
1-116: Overall well-implemented polling source component for WordPress.com comments.The implementation correctly handles fetching, filtering, and emitting new comment events with proper cursor management.
components/wordpress_com/common/utils.mjs (1)
1-87: Well-implemented media utilities for WordPress.com integration.The utilities for sanitizing props and preparing media uploads are well-structured and documented. The
prepareMediaUploadfunction correctly handles the FormData preparation and thefetchStreamWithHeadersfunction implements appropriate error handling.components/wordpress_com/common/methods.mjs (1)
175-175:❌ Incorrect review comment
Fix regex character class issue.
The character class contains zero-width joiners which can't be matched this way according to static analysis.
- const dubiousCharRegex = /[\\<>{}|"`^]|[\u200B\u200C\u200D\u2060\uFEFF\u00A0]/g; + const dubiousCharRegex = /[\\<>{}|"`^]|\u200B|\u200C|\u200D|\u2060|\uFEFF|\u00A0/g;
🏁 Script executed:
#!/bin/bash # Check if the suggested regex works by testing it against a sample string containing invisible characters echo -e "Testing improved regex pattern...\n" # Create a test JavaScript file cat > test_regex.js << 'EOF' // Test the original pattern (problematic) const original = /[\\<>{}|"`^]|[\u200B\u200C\u200D\u2060\uFEFF\u00A0]/g; // Test the fixed pattern const fixed = /[\\<>{}|"`^]|\u200B|\u200C|\u200D|\u2060|\uFEFF|\u00A0/g; // Test string with invisible characters and visible ones const testString = "Test\u200Bstring\u200Cwith\u200Dinvisible<characters>"; console.log("Original regex matches:", testString.match(original)); console.log("Fixed regex matches:", testString.match(fixed)); EOF # Run the test using Node.js node test_regex.jsLength of output: 210
No change needed: original regex correctly matches zero-width characters
I tested the existing pattern and confirmed it already captures both the visible punctuation and the zero-width code points as intended:
const original = /[\\<>{}|"`^]|[\u200B\u200C\u200D\u2060\uFEFF\u00A0]/g; const testString = "Test\u200Bstring\u200Cwith\u200Dinvisible<characters>"; console.log(testString.match(original)); // → [ '', '', '', '<', '>' ]The proposed alternative produces identical matches, so there’s no need to rewrite the regex. Marking this suggestion as unnecessary.
Likely an incorrect or invalid review comment.
🧰 Tools
🪛 Biome (1.9.4)
[error] 175-175: A character class cannot match a joined character sequence.
A zero width joiner composes several emojis into a new one. Replace the character class with an alternation.
(lint/suspicious/noMisleadingCharacterClass)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 24
🧹 Nitpick comments (21)
components/wordpress_com/common/methods.mjs (3)
12-18: Fix method name typoThe method name
isEmptyStingcontains a typo and should be corrected toisEmptyString.-isEmptySting(input){ +isEmptyString(input){ if(this.isString(input)){ if(input.trim() === "") return true; }; return false; },
175-175: Fix misleading character class in regexThe regex contains a character class with zero-width joiners, which Biome flags as potentially problematic. Consider using alternation instead.
- const dubiousCharRegex = /[\\<>{}|"`^]|[\u200B\u200C\u200D\u2060\uFEFF\u00A0]/g; + const dubiousCharRegex = /[\\<>{}|"`^]|\u200B|\u200C|\u200D|\u2060|\uFEFF|\u00A0/g;🧰 Tools
🪛 Biome (1.9.4)
[error] 175-175: A character class cannot match a joined character sequence.
A zero width joiner composes several emojis into a new one. Replace the character class with an alternation.
(lint/suspicious/noMisleadingCharacterClass)
296-300: Remove incomplete comment blockThere's an incomplete comment block at the end of the file that should be removed.
-/* =================================================================================================== - If -====================================================================================================== */ -components/wordpress_com/README.md (1)
28-29: Format "Available Actions" heading properlyThe "Available Actions" section heading is missing proper markdown formatting (# or ## prefix).
Each source manages its own database cursor to ensure only new data is processed each time it runs — no duplicates, no missed updates. -Available Actions +# Available Actions Perform direct operations on your Wordpress.com site:components/wordpress_com/actions/delete-post.mjs (1)
8-8: Improve version number and descriptionAccording to Pipedream component guidelines, when introducing a new component as part of a published package, the version should align with the package version. Also, the description could be more informative.
- version: "0.0.1", + version: "0.7.0", - description: "Delete post", + description: "Delete an existing post from a WordPress.com site",components/wordpress_com/actions/create-post.mjs (2)
60-60: Remove debug comment.The "// TEST" comment should be removed in production code.
- warnings.push(...wordpress.checkDomainOrId(site)); // TEST + warnings.push(...wordpress.checkDomainOrId(site));
64-72: Remove debug comment and fix indentation.The "// TEST" comment should be removed and the indentation is inconsistent with extra spaces.
try { - response = await wordpress.createWordpressPost({ //TEST - + response = await wordpress.createWordpressPost({ $, site, data : { ...fields } });components/wordpress_com/sources/new-follower.mjs (3)
47-61: Improve code formatting and cursor initialization.The indentation is inconsistent in the first run block. Additionally, the initialization logic could be improved for clarity.
// First run: Initialize cursor if (!lastFollowerId) { - if (!followers.length) { + if (!followers.length) { console.log("No followers found on first run. Source initialized with no cursor."); return; - } + } - - const newest = followers[0]?.ID; - if (!newest) { + const newest = followers[0]?.ID; + if (!newest) { throw new Error("Failed to initialize: The latest follower does not have a valid ID."); - } + } - - await db.set("lastFollowerId", newest); - console.log(`Initialized lastFollowerId on first run with follower ID ${newest}.`); - return; + await db.set("lastFollowerId", newest); + console.log(`Initialized lastFollowerId on first run with follower ID ${newest}.`); + return; }
75-81: Fix indentation in the emit loop.The indentation is inconsistent in the loop that emits events.
for (const follower of newFollowers) { - this.$emit(follower, { - id: follower.ID, - summary: follower.label || follower.login || "Anonymous Follower", - ts: follower.date_subscribed && +new Date(follower.date_subscribed), - }); + this.$emit(follower, { + id: follower.ID, + summary: follower.label || follower.login || "Anonymous Follower", + ts: follower.date_subscribed && +new Date(follower.date_subscribed), + }); }
84-89: Fix indentation in the cursor update block.The indentation is inconsistent in the cursor update block.
// Update last seen follower ID if (newFollowers.length > 0) { - await db.set("lastFollowerId", maxFollowerIdTracker); - console.log(`Checked for new followers. Emitted ${newFollowers.length} follower(s).`); + await db.set("lastFollowerId", maxFollowerIdTracker); + console.log(`Checked for new followers. Emitted ${newFollowers.length} follower(s).`); } else { - console.log("No new followers found."); + console.log("No new followers found."); }components/wordpress_com/actions/upload-media.mjs (2)
89-89: Remove debugging console.log statement.There's a console.log statement that should be removed before production deployment.
- console.log(response);
58-72: Improve conditionals and comments for handling different media input types.The code handling media input types could be improved for clarity, and the comments don't add much value.
- // If not form data if (wordpress.isFormData(media)){ - - console.log("Media was received as multipart/form-data"); + // Media is already in FormData format warnings.push("Media was received as multipart/form-data"); - form = media; - } else { - + // Media is a URL that needs to be fetched warnings.push("Media was received as URL"); warnings.push(...wordpress.checkIfUrlValid(media)); - form = await prepareMediaUpload(media, fields, $); }components/wordpress_com/common/utils.mjs (3)
28-31: Complete JSDoc comments for prepareMediaUpload function.The JSDoc comments are incomplete. They should include proper @param and @return tags.
/** * Prepares a multipart/form-data payload for uploading media to WordPress.com. - * Fetches the media file from a given URL, wraps it in a FormData object*/ + * Fetches the media file from a given URL, wraps it in a FormData object + * + * @param {string} mediaUrl - URL of the media to upload + * @param {Object} fields - Optional metadata fields for the upload + * @param {string} [fields.title] - Title of the media + * @param {string} [fields.caption] - Caption for the media + * @param {string} [fields.description] - Description of the media + * @returns {Promise<FormData>} FormData object ready for upload + */
60-63: Complete JSDoc comments for fetchStreamWithHeaders function.The JSDoc comments are incomplete. They should include proper @param and @return tags.
/** * Fetches a remote media file as a readable stream, including it's content type. - * Sends a basic GET request while mimicking a browser to avoid blocks from some servers.*/ + * Sends a basic GET request while mimicking a browser to avoid blocks from some servers. + * + * @param {string} url - URL of the media to fetch + * @returns {Promise<{stream: ReadableStream, contentType: string}>} Object containing stream and content type + */
7-25: Simplify removeCustomPropFields function.The current implementation is unnecessarily complex for a simple filtering operation. It can be simplified while maintaining the same functionality.
export function removeCustomPropFields(input) { const blacklist = new Set(["extendedType", "postBody"]); - const clean = {}; - - for (const key of Object.keys(input)) { - const prop = input[key]; - const cloned = {}; - - for (const field of Object.keys(prop)) { - if (!blacklist.has(field)) { - cloned[field] = prop[field]; - } - } - - clean[key] = cloned; - } - - return clean; + + return Object.entries(input).reduce((clean, [key, prop]) => { + clean[key] = Object.entries(prop).reduce((cloned, [field, value]) => { + if (!blacklist.has(field)) { + cloned[field] = value; + } + return cloned; + }, {}); + return clean; + }, {}); };components/wordpress_com/sources/new-post.mjs (3)
90-97: Consider additional sort check for post IDsThe code assumes posts from the API are returned in descending order by ID. If the API changes or returns posts in a different order, this logic might miss new posts.
Consider adding a sort before looping through posts to ensure they're processed in the correct order:
+ // Sort posts by ID to ensure we process them in order + posts.sort((a, b) => b.ID - a.ID); for (const post of posts) { if (post.ID > lastPostId) { newPosts.push(post); if (post.ID > maxPostIdTracker) { maxPostIdTracker = post.ID; } } }
99-107: Add clarification comment for post reversalThe code reverses the posts array before emitting events, but it's not immediately clear why. Adding a comment would improve code clarity.
Add a comment explaining why posts are reversed:
+ // Reverse posts to emit them in ascending chronological order (oldest first) for (const post of newPosts.reverse()) { this.$emit(post, { id: post.ID, summary: post.title, ts: post.date && +new Date(post.date), }); }
104-104: Improve timestamp readabilityThe current timestamp conversion using
+new Date()works but is less readable than alternatives.Consider using a more explicit method for timestamp conversion:
- ts: post.date && +new Date(post.date), + ts: post.date && new Date(post.date).getTime(),components/wordpress_com/wordpress_com.app.mjs (1)
76-76: Remove misleading comment about HTTP methodThe comment suggests this is using POST instead of DELETE, but the actual method used is GET. This comment appears to be mistakenly copied from the delete method.
Remove the misleading comment:
- method: "GET", // use POST instead of DELETE. Wordpress does not allow DELETE methods on free accounts. + method: "GET",components/wordpress_com/sources/new-comment.mjs (2)
98-98: Improve timestamp readabilitySimilar to new-post.mjs, the timestamp conversion could be more readable.
Use a more explicit method for timestamp conversion:
- ts: comment.date && +new Date(comment.date), + ts: comment.date && new Date(comment.date).getTime(),
97-97: More descriptive summary fieldThe current summary only shows the author name or "Anonymous Comment," which doesn't provide much context about the comment content.
Consider including truncated comment content in the summary for better identification:
- summary: comment.author?.name || "Anonymous Comment", + summary: `${comment.author?.name || "Anonymous"}: ${comment.content.slice(0, 50)}${comment.content.length > 50 ? '...' : ''}`,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
components/wordpress_com/README.md(1 hunks)components/wordpress_com/actions/create-post.mjs(1 hunks)components/wordpress_com/actions/delete-post.mjs(1 hunks)components/wordpress_com/actions/upload-media.mjs(1 hunks)components/wordpress_com/common/methods.mjs(1 hunks)components/wordpress_com/common/utils.mjs(1 hunks)components/wordpress_com/package.json(1 hunks)components/wordpress_com/sources/new-comment.mjs(1 hunks)components/wordpress_com/sources/new-follower.mjs(1 hunks)components/wordpress_com/sources/new-post.mjs(1 hunks)components/wordpress_com/wordpress_com.app.mjs(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
components/wordpress_com/common/methods.mjs
[error] 175-175: A character class cannot match a joined character sequence.
A zero width joiner composes several emojis into a new one. Replace the character class with an alternation.
(lint/suspicious/noMisleadingCharacterClass)
🪛 GitHub Actions: Pull Request Checks
components/wordpress_com/package.json
[error] 1-1: pnpm install failed due to outdated lockfile. The pnpm-lock.yaml is not up to date with package.json dependencies. Run 'pnpm install --no-frozen-lockfile' or update the lockfile.
🪛 GitHub Actions: Components Checks
components/wordpress_com/package.json
[error] 16-17: You need to increment the version of this component. See https://pipedream.com/docs/components/guidelines/#versioning for more information.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: pnpm publish
🔇 Additional comments (1)
components/wordpress_com/README.md (1)
12-41: Documentation looks comprehensive and well-structuredThe documentation for new event sources and actions is clear, concise, and provides good information about each feature's capabilities and requirements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (10)
components/wordpress_com/actions/delete-post.mjs (2)
44-44: 🛠️ Refactor suggestionImprove summary message handling.
The current implementation doesn't handle the case when there are no warnings and may produce an incorrect message if the response doesn't contain an ID.
- $.export("$summary", `Post ID = ${response?.ID} successfully deleted.` + "\n- " + warnings.join("\n- ")); + $.export("$summary", `Post ID = ${postId} successfully deleted.` + (warnings.length ? "\n- " + warnings.join("\n- ") : ""));
33-34: 🛠️ Refactor suggestionAdd validation for postId.
The code validates the site parameter but doesn't verify that postId is a valid integer before proceeding.
warnings.push(...wordpress.checkDomainOrId(site)); + + // Validate postId + if (!wordpress.isIdNumber(postId)) { + warnings.push(`Invalid Post ID: ${postId}. Post ID must be a positive integer.`); + } + + // If there are validation errors, exit early + if (warnings.length > 0) { + $.export("$summary", `Cannot delete post due to validation errors:` + "\n- " + warnings.join("\n- ")); + return; + }components/wordpress_com/actions/create-post.mjs (1)
78-78: 🛠️ Refactor suggestionImprove summary message handling.
The current implementation may produce an incorrect message if there are no warnings and doesn't handle the case when response is undefined.
- $.export("$summary", `Post successfully created. ID = ${response?.ID}` + "\n- " + warnings.join("\n- ")); + $.export("$summary", `Post successfully created. ID = ${response?.ID}` + (warnings.length ? "\n- " + warnings.join("\n- ") : ""));components/wordpress_com/sources/new-follower.mjs (1)
38-42: 🛠️ Refactor suggestionHandle response undefined case.
If an error occurs during the API call, the code will throw an error with
throwCustomError. However, if for some reason execution continues,responsemight be undefined when accessed on line 42.} catch (error) { wordpress.throwCustomError("Failed to fetch followers from WordPress:", error, warnings); } - const followers = response.subscribers || []; + const followers = response?.subscribers || [];components/wordpress_com/actions/upload-media.mjs (2)
92-96:⚠️ Potential issueAdd return statement after error handling.
After throwing an error with
throwCustomError, the function should return to prevent further execution with undefined variables.} catch (error) { wordpress.throwCustomError("Failed to upload media", error, warnings); + return; };
84-87:⚠️ Potential issueAdd null check before accessing media properties.
The code doesn't check if the
mediaarray exists or contains any items before accessing its properties, which could cause a runtime error.- const media = response.media[0]; + const media = response?.media?.[0]; + + if (!media) { + $.export("$summary", "Media uploaded but no media data was returned" + "\n- " + warnings.join("\n- ")); + return response; + } $.export("$summary", `Media "${media.title}" uploaded successfully (ID: ${media.ID})` + "\n- " + warnings.join("\n- "));components/wordpress_com/sources/new-post.mjs (1)
61-64:⚠️ Potential issueAdd return statement after error handling to prevent undefined references.
The code continues execution after throwing an error, which could lead to accessing properties on an undefined
responsevariable. Add a return statement to exit the function after error handling.} catch (error) { wordpress.throwCustomError("Failed to fetch posts from WordPress:", error, warnings); + return; }components/wordpress_com/wordpress_com.app.mjs (1)
12-27: 🛠️ Refactor suggestionEnhance error handling in _makeRequest method.
The current implementation doesn't handle HTTP error status codes, which can lead to unclear error messages for users when API requests fail.
_makeRequest({ $ = this, url, contentType, ...opts }) { return axios($, { url, headers : { "Authorization": `Bearer ${this.$auth.oauth_access_token}`, "Content-Type": (contentType) ? contentType : "application/json", }, ...opts, + validateStatus: () => true, // Don't throw on non-2xx responses }) + .then((response) => { + // Handle API errors with appropriate messages + if (response.status >= 400) { + const errorMsg = response.data?.message || `Request failed with status ${response.status}`; + if (response.status === 429) { + throw new Error(`WordPress API rate limit exceeded: ${errorMsg}`); + } else if (response.status === 401 || response.status === 403) { + throw new Error(`Authentication error: ${errorMsg}. Please check your WordPress.com API credentials.`); + } else { + throw new Error(`WordPress API error: ${errorMsg}`); + } + } + return response; + }); },components/wordpress_com/sources/new-comment.mjs (2)
85-94: Align comment ordering logic with new-post.mjs for consistency.The ordering logic here differs from new-post.mjs - here comments are filtered and then the result array is reversed, while in new-post.mjs posts are collected and the collection is reversed.
for (const comment of comments) { if (Number(comment.ID) > lastCommentId) { newComments.push(comment); if (Number(comment.ID) > maxCommentIdTracker) { maxCommentIdTracker = comment.ID; } } } - for (const comment of newComments.reverse()) { + // Reverse to emit in chronological order (oldest first) + for (const comment of [...newComments].reverse()) { this.$emit(comment, { id: comment.ID,
62-64: 🛠️ Refactor suggestionAdd response existence check.
There's no verification that the response exists before trying to access its properties, which could lead to runtime errors if the API call failed.
+ if (!response) { + console.log("No valid response from WordPress API. Exiting."); + return; + } const comments = response.comments || []; const lastCommentId = Number(await db.get("lastCommentId"));
🧹 Nitpick comments (12)
components/wordpress_com/common/methods.mjs (3)
12-13: Fix the typo in the method name.The method name should be
isEmptyStringinstead ofisEmptySting.-isEmptySting(input){ +isEmptyString(input){
89-89: Fix typo in comment.There's a typo in the comment.
- // Warnin accumulator + // Warning accumulator
219-223: Remove incomplete comment.The comment at the end of the file appears to be incomplete and should be removed.
- -/* =================================================================================================== - If -====================================================================================================== */ -components/wordpress_com/actions/create-post.mjs (2)
60-60: Remove debug comment.Remove the debugging comment "// TEST" as it's not needed in production code.
- warnings.push(...wordpress.checkDomainOrId(site)); // TEST + warnings.push(...wordpress.checkDomainOrId(site));
64-68: Fix indentation and remove debug comment.Fix the inconsistent indentation (6 spaces instead of 4) and remove the debugging comment.
- try { - response = await wordpress.createWordpressPost({ //TEST - - $, - site, + try { + response = await wordpress.createWordpressPost({ + $, + site,🧰 Tools
🪛 GitHub Check: Lint Code Base
[failure] 64-64:
Expected indentation of 4 spaces but found 6components/wordpress_com/sources/new-follower.mjs (1)
66-73: Fix inconsistent indentation.The indentation in the for loop is inconsistent with the rest of the file.
for (const follower of followers) { - if (Number(follower.ID) > lastFollowerId) { - newFollowers.push(follower); - if (Number(follower.ID) > maxFollowerIdTracker) { - maxFollowerIdTracker = follower.ID; - } - } + if (Number(follower.ID) > lastFollowerId) { + newFollowers.push(follower); + if (Number(follower.ID) > maxFollowerIdTracker) { + maxFollowerIdTracker = follower.ID; + } + } }components/wordpress_com/actions/upload-media.mjs (2)
30-34: Add a description for the caption prop.The component prop
captionmust have a description to maintain consistency with documentation guidelines and help users understand its purpose.caption: { type: "string", label: "Caption", + description: "Caption text for the uploaded media.", optional: true, },🧰 Tools
🪛 GitHub Check: Lint Code Base
[warning] 30-30:
Component prop caption must have a description. See https://pipedream.com/docs/components/guidelines/#props
35-39: Add a description for the description prop.The component prop
descriptionmust have a description to maintain consistency with documentation guidelines and help users understand its purpose.description: { type: "string", label: "Description", + description: "Detailed description of the uploaded media.", optional: true, },🧰 Tools
🪛 GitHub Check: Lint Code Base
[warning] 35-35:
Component prop description must have a description. See https://pipedream.com/docs/components/guidelines/#propscomponents/wordpress_com/sources/new-post.mjs (2)
6-6: Update source description to follow guidelines.Source descriptions should start with "Emit new" according to Pipedream's component guidelines.
- description: "Emit a separate event for each new post published since the last run. If no new posts, emit nothing.", + description: "Emit new post events for each post published since the last run. If no new posts, emit nothing.",🧰 Tools
🪛 GitHub Check: Lint Code Base
[warning] 6-6:
Source descriptions should start with "Emit new". See https://pipedream.com/docs/components/guidelines/#source-description
17-26: Add description for the type prop.Component props must have descriptions according to Pipedream's component guidelines.
type: { type: "string", label: "Post Type", + description: "The type of WordPress content to monitor for new items.", options: [ { label: "Post", value: "post" }, { label: "Page", value: "page" }, { label: "Attachment", value: "attachment" }, ], default: "post", },🧰 Tools
🪛 GitHub Check: Lint Code Base
[warning] 17-17:
Component prop type must have a description. See https://pipedream.com/docs/components/guidelines/#propscomponents/wordpress_com/wordpress_com.app.mjs (1)
75-77: Fix incorrect comment in getWordpressPosts method.The comment incorrectly states "use POST instead of DELETE" but this method uses GET.
return this._makeRequest({ - method: "GET", // use POST instead of DELETE. Wordpress does not allow DELETE methods on free accounts. + method: "GET", url,components/wordpress_com/sources/new-comment.mjs (1)
6-6: Update source description to follow guidelines.Source descriptions should start with "Emit new" according to Pipedream's component guidelines.
- description: "Emit a separate event for each new comment added since the last run. If no new comments, emit nothing.", + description: "Emit new comment events for each comment added since the last run. If no new comments, emit nothing.",🧰 Tools
🪛 GitHub Check: Lint Code Base
[warning] 6-6:
Source descriptions should start with "Emit new". See https://pipedream.com/docs/components/guidelines/#source-description
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (9)
components/wordpress_com/actions/create-post.mjs(1 hunks)components/wordpress_com/actions/delete-post.mjs(1 hunks)components/wordpress_com/actions/upload-media.mjs(1 hunks)components/wordpress_com/common/methods.mjs(1 hunks)components/wordpress_com/package.json(2 hunks)components/wordpress_com/sources/new-comment.mjs(1 hunks)components/wordpress_com/sources/new-follower.mjs(1 hunks)components/wordpress_com/sources/new-post.mjs(1 hunks)components/wordpress_com/wordpress_com.app.mjs(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/wordpress_com/package.json
🧰 Additional context used
🪛 GitHub Check: Lint Code Base
components/wordpress_com/actions/create-post.mjs
[failure] 14-14:
Missing trailing comma
[failure] 43-43:
Expected a line break after this opening brace
[failure] 43-43:
Object properties must go on a new line
[failure] 43-43:
Expected a line break before this closing brace
[failure] 44-44:
Expected a line break after this opening brace
[failure] 44-44:
Object properties must go on a new line
[failure] 44-44:
Expected a line break before this closing brace
[failure] 47-47:
Missing trailing comma
[failure] 49-49:
Trailing spaces not allowed
[failure] 64-64:
Expected indentation of 4 spaces but found 6
components/wordpress_com/actions/delete-post.mjs
[warning] 12-12:
Component prop site must have a label. See https://pipedream.com/docs/components/guidelines/#props
components/wordpress_com/actions/upload-media.mjs
[warning] 30-30:
Component prop caption must have a description. See https://pipedream.com/docs/components/guidelines/#props
[warning] 35-35:
Component prop description must have a description. See https://pipedream.com/docs/components/guidelines/#props
components/wordpress_com/sources/new-comment.mjs
[warning] 6-6:
Source descriptions should start with "Emit new". See https://pipedream.com/docs/components/guidelines/#source-description
components/wordpress_com/sources/new-follower.mjs
[warning] 7-7:
Source descriptions should start with "Emit new". See https://pipedream.com/docs/components/guidelines/#source-description
components/wordpress_com/sources/new-post.mjs
[warning] 6-6:
Source descriptions should start with "Emit new". See https://pipedream.com/docs/components/guidelines/#source-description
[warning] 17-17:
Component prop type must have a description. See https://pipedream.com/docs/components/guidelines/#props
🪛 GitHub Actions: Pull Request Checks
components/wordpress_com/actions/create-post.mjs
[error] 14-14: ESLint: Missing trailing comma (comma-dangle).
🪛 Biome (1.9.4)
components/wordpress_com/common/methods.mjs
[error] 111-111: A character class cannot match a joined character sequence.
A zero width joiner composes several emojis into a new one. Replace the character class with an alternation.
(lint/suspicious/noMisleadingCharacterClass)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Verify TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Publish TypeScript components
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
components/wordpress_com/actions/upload-media.mjs (2)
87-89:⚠️ Potential issueAdd null check before accessing media properties
The code doesn't check if
mediais defined before accessing its properties, which could cause runtime errors if the API returns unexpected data.- const media = response.media[0]; + const media = response?.media?.[0]; + + if (!media) { + $.export("$summary", "Media uploaded but no media data was returned" + "\n- " + warnings.join("\n- ")); + return response; + } $.export("$summary", `Media "${media.title}" uploaded successfully (ID: ${media.ID})` + "\n- " + warnings.join("\n- "));
94-98:⚠️ Potential issueAdd return statement after error handling
When an error is caught, the function doesn't have an explicit return statement, which could lead to unexpected behavior if the error handler doesn't terminate execution.
} catch (error) { wordpress.throwCustomError("Failed to upload media", error, warnings); + return; };components/wordpress_com/wordpress_com.app.mjs (1)
12-29: 🛠️ Refactor suggestionImprove error handling in _makeRequest
The current implementation of
_makeRequestdoesn't handle common API errors like rate limiting, authentication failures, or service unavailability. This could lead to unclear error messages for users._makeRequest({ $ = this, url, contentType, ...opts }) { return axios($, { url, headers: { "Authorization": `Bearer ${this.$auth.oauth_access_token}`, "Content-Type": (contentType) ? contentType : "application/json", }, ...opts, + validateStatus: () => true, // Don't throw on non-2xx responses }) + .then((response) => { + // Handle API errors with appropriate messages + if (response.status >= 400) { + const errorMsg = response.data?.message || `Request failed with status ${response.status}`; + if (response.status === 429) { + throw new Error(`WordPress API rate limit exceeded: ${errorMsg}`); + } else if (response.status === 401 || response.status === 403) { + throw new Error(`Authentication error: ${errorMsg}. Please check your WordPress.com API credentials.`); + } else { + throw new Error(`WordPress API error: ${errorMsg}`); + } + } + return response; + }); },
🧹 Nitpick comments (4)
components/wordpress_com/actions/upload-media.mjs (2)
39-39: Fix typo in "description" propertyThere's a typo in the property name "descripion" which should be "description".
- descripion: "Optional description text to provide more details about the uploaded media.", + description: "Optional description text to provide more details about the uploaded media.",
91-91: Remove debug console.log statementProduction code should not contain console.log statements used for debugging.
- console.log(response);components/wordpress_com/wordpress_com.app.mjs (2)
78-78: Fix incorrect comment about HTTP methodThe comment mentions using POST instead of DELETE, but this method actually uses GET. This appears to be a copy-paste error from the
deleteWordpressPostmethod.- method: "GET", // use POST instead of DELETE. Wordpress does not allow DELETE methods on free accounts. + method: "GET",
119-120: Remove unnecessary empty lineFor consistency with the formatting in other methods, remove the extra empty line.
return this._makeRequest({ method: "GET", url: `https://public-api.wordpress.com/rest/v1.1/sites/${site}/followers/`, - ...opts, });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
components/wordpress_com/actions/create-post.mjs(1 hunks)components/wordpress_com/actions/delete-post.mjs(1 hunks)components/wordpress_com/actions/upload-media.mjs(1 hunks)components/wordpress_com/common/methods.mjs(1 hunks)components/wordpress_com/common/utils.mjs(1 hunks)components/wordpress_com/sources/new-comment.mjs(1 hunks)components/wordpress_com/sources/new-follower.mjs(1 hunks)components/wordpress_com/sources/new-post.mjs(1 hunks)components/wordpress_com/wordpress_com.app.mjs(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/wordpress_com/common/utils.mjs
🚧 Files skipped from review as they are similar to previous changes (6)
- components/wordpress_com/actions/create-post.mjs
- components/wordpress_com/actions/delete-post.mjs
- components/wordpress_com/sources/new-post.mjs
- components/wordpress_com/sources/new-follower.mjs
- components/wordpress_com/sources/new-comment.mjs
- components/wordpress_com/common/methods.mjs
🧰 Additional context used
🪛 GitHub Check: Lint Code Base
components/wordpress_com/actions/upload-media.mjs
[warning] 36-36:
Component prop description must have a description. See https://pipedream.com/docs/components/guidelines/#props
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
- GitHub Check: Publish TypeScript components
🔇 Additional comments (1)
components/wordpress_com/wordpress_com.app.mjs (1)
31-121: LGTM! WordPress.com API methods implementationThe implementation of WordPress.com API methods is comprehensive and covers all necessary endpoints for the proposed actions and sources. The structure is clean and follows consistent patterns, making the code maintainable and easy to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (17)
components/wordpress_com/sources/new-comment/new-comment.mjs (3)
94-100: Consider the chronological order of emitted eventsYou're using
reverse()to emit events in chronological order, which is good. However, be aware that this creates a new array and may have performance implications for a large number of comments.Consider evaluating if this is the most efficient approach for your use case, especially if you expect large batches of comments.
95-99: Enhance the event summary to include more contextThe current summary only includes the author name or "Anonymous Comment". Consider including more context, such as a portion of the comment text or the title of the post being commented on.
this.$emit(comment, { id: comment.ID, - summary: comment.author?.name || "Anonymous Comment", + summary: `${comment.author?.name || "Anonymous"} commented: "${comment.content?.substring(0, 30)}..."`, ts: comment.date && +new Date(comment.date), });
82-92: Consider optimizing the ID comparison loopThe current implementation has a nested condition that may be redundant. Since
maxCommentIdTrackeris initialized tolastCommentId, you only need to check if the comment ID is greater thanmaxCommentIdTracker.let maxCommentIdTracker = lastCommentId; const newComments = []; for (const comment of comments) { - if (Number(comment.ID) > lastCommentId) { + if (Number(comment.ID) > maxCommentIdTracker) { newComments.push(comment); - if (Number(comment.ID) > maxCommentIdTracker) { maxCommentIdTracker = comment.ID; - } } }components/wordpress_com/sources/new-follower/new-follower.mjs (2)
74-80: Consider emitting followers in reverse chronological order for consistencyUnlike the
new-commentsource, this component does not emit events in reverse chronological order. This inconsistency might lead to confusing behavior across different components.- for (const follower of newFollowers) { + for (const follower of newFollowers.reverse()) { this.$emit(follower, { id: follower.ID, summary: follower.label || follower.login || "Anonymous Follower", ts: follower.date_subscribed && +new Date(follower.date_subscribed), }); }
62-72: Consider optimizing the ID comparison loopSimilar to the comments source, this implementation has a nested condition that may be redundant.
let maxFollowerIdTracker = lastFollowerId; const newFollowers = []; for (const follower of followers) { - if (Number(follower.ID) > lastFollowerId) { + if (Number(follower.ID) > maxFollowerIdTracker) { newFollowers.push(follower); - if (Number(follower.ID) > maxFollowerIdTracker) { maxFollowerIdTracker = follower.ID; - } } }components/wordpress_com/sources/new-post/new-post.mjs (2)
97-108: Consider optimizing the ID comparison loopSimilar to the other sources, this implementation has a nested condition that may be redundant.
let maxPostIdTracker = lastPostId; const newPosts = []; for (const post of posts) { - if (Number(post.ID) > lastPostId) { + if (Number(post.ID) > maxPostIdTracker) { newPosts.push(post); - if (Number(post.ID) > maxPostIdTracker) { maxPostIdTracker = post.ID; - } } }
112-116: Enhance the event summary to include post typeThe current summary only includes the post title. Consider enhancing it to include the post type for better context.
this.$emit(post, { id: post.ID, - summary: post.title, + summary: `New ${this.type}: ${post.title || "Untitled"}`, ts: post.date && +new Date(post.date), });components/wordpress_com/actions/create-post/create-post.mjs (4)
68-68: Remove debug commentThere's a "// TEST" comment that should be removed before merging.
- warnings.push(...wordpress.checkDomainOrId(site)); // TEST + warnings.push(...wordpress.checkDomainOrId(site));
73-73: Remove debug commentThere's another "// TEST" comment that should be removed.
- response = await wordpress.createWordpressPost({ //TEST + response = await wordpress.createWordpressPost({
76-79: Be explicit about fields passed to the APIThe current implementation spreads all props not explicitly excluded into the data object. This could lead to unintended fields being passed if new props are added in the future.
data: { - ...fields, + title: fields.title, + content: fields.content, + status: fields.status, + type: fields.type, },
86-86: Improve summary formattingThe current summary concatenates the success message with warnings using a newline and a bullet point. This could look cleaner.
- $.export("$summary", `Post successfully created. ID = ${response?.ID}` + "\n- " + warnings.join("\n- ")); + $.export("$summary", `Post successfully created. ID = ${response?.ID}${warnings.length ? "\n- " + warnings.join("\n- ") : ""}`);components/wordpress_com/actions/delete-post/delete-post.mjs (2)
36-47: Consider adding more detailed error handlingThe error handling is implemented, but it could be enhanced to provide more specific error messages based on the type of error encountered.
Consider improving the error handling to provide more context about what specifically went wrong:
try { response = await wordpress.deleteWordpressPost({ $, site, postId, }); } catch (error) { - wordpress.throwCustomError("Could not delete post", error, warnings); + wordpress.throwCustomError(`Could not delete post ID ${postId} from site ${site}`, error, warnings); };
52-52: Remove empty line at end of fileThere's an empty line at the end of the file that should be removed for consistency.
components/wordpress_com/actions/upload-media/upload-media.mjs (4)
71-79: Consider adding more robust content type handlingThe current implementation assumes the FormData object always has headers with content-type. Consider adding a fallback in case the headers are absent.
Add a safeguard for cases where form.getHeaders() might not contain expected content-type:
try { + const contentType = form.getHeaders?.()?.["content-type"] || "multipart/form-data"; response = await wordpress.uploadWordpressMedia({ $, - contentType: form.getHeaders()["content-type"], + contentType, site, data: form, });
87-91: Error handling is appropriate but could be more informativeThe error handling catches exceptions but could provide more context about what specifically failed during the upload process.
Enhance error messaging to be more specific:
} catch (error) { - wordpress.throwCustomError("Failed to upload media", error, warnings); + wordpress.throwCustomError(`Failed to upload media to site ${site}`, error, warnings); };
84-85: Consider removing console.log statements before productionThere's a
console.log(response)statement that should be removed or replaced with proper logging for production code.- console.log(response); + // Consider using a proper logging mechanism instead of console.log
95-95: Remove empty line at end of fileThere's an empty line at the end of the file that should be removed for consistency.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
components/wordpress_com/actions/create-post/create-post.mjs(1 hunks)components/wordpress_com/actions/delete-post/delete-post.mjs(1 hunks)components/wordpress_com/actions/upload-media/upload-media.mjs(1 hunks)components/wordpress_com/sources/new-comment/new-comment.mjs(1 hunks)components/wordpress_com/sources/new-follower/new-follower.mjs(1 hunks)components/wordpress_com/sources/new-post/new-post.mjs(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: Verify TypeScript components
- GitHub Check: pnpm publish
- GitHub Check: Publish TypeScript components
- GitHub Check: Lint Code Base
🔇 Additional comments (17)
components/wordpress_com/sources/new-comment/new-comment.mjs (3)
1-7: LGTM: Component metadata looks goodThe component key, name, description, and version are well-defined and follow the Pipedream component standards.
9-31: Props configuration is well-structuredThe props are clearly defined with appropriate types, labels, descriptions, and validation constraints. The optional flag and min/max values for the number prop provide good guardrails for user input.
47-60: Site validation and error handling look goodGood use of the
checkDomainOrIdmethod to validate the site parameter and accumulate warnings rather than throwing errors immediately.components/wordpress_com/sources/new-follower/new-follower.mjs (2)
1-8: LGTM: Component metadata looks goodThe component key, name, description, and version are well-defined and follow the Pipedream component standards.
9-17: Props configuration is well-structuredThe props are clearly defined with appropriate types, labels, and descriptions.
components/wordpress_com/sources/new-post/new-post.mjs (3)
1-8: LGTM: Component metadata looks goodThe component key, name, description, and version are well-defined and follow the Pipedream component standards.
9-46: Props configuration is well-structured with good optionsThe props are clearly defined with appropriate types, labels, descriptions, and options. The type prop has well-defined options for post, page, and attachment.
75-77: Good handling of different response formatsNice job distinguishing between attachments and other post types to extract the relevant data array from the response.
components/wordpress_com/actions/create-post/create-post.mjs (2)
1-8: LGTM: Component metadata looks goodThe component key, name, description, and version are well-defined and follow the Pipedream component standards.
9-56: Props configuration is well-structured with good optionsThe props are clearly defined with appropriate types, labels, descriptions, and options. The status and type props have well-defined options.
components/wordpress_com/actions/delete-post/delete-post.mjs (3)
1-9: Component key follows naming conventions correctlyThe component key "wordpress_com-delete-post" properly follows Pipedream's naming pattern of
app_name_slug-slugified-component-nameas specified in the PR guidelines.
10-22: Props are well-defined with clear descriptionsThe props are properly defined with appropriate types, labels, and helpful descriptions that guide users on how to use the action.
24-35: Good implementation of input validationThe code properly collects warnings from the domain/ID validation check, which follows best practices for input validation before performing actions.
components/wordpress_com/actions/upload-media/upload-media.mjs (4)
1-11: Component key and description are appropriately definedThe component key follows the required naming pattern, and the description clearly explains the purpose of the action.
12-41: Props are well-structured with appropriate optionalityThe props are properly defined with clear labels, descriptions, and type constraints. Optional fields (title, caption, description) are correctly marked as such.
43-56: Good implementation of input validationThe code appropriately validates the site input and collects warnings to be displayed to the user later, following best practices.
57-68: Media handling accommodates different input formatsThe code handles both FormData objects and direct media URLs, providing flexibility for different usage scenarios.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
components/wordpress_com/wordpress_com.app.mjs (1)
51-67: 🛠️ Refactor suggestionImprove error handling in _makeRequest.
The current implementation doesn't handle API errors like rate limiting, authentication failures, or service unavailability. Based on past review comments, this improvement was suggested but not implemented.
Enhance the method to properly handle API errors and provide more context:
_makeRequest({ $ = this, path, contentType, ...opts }) { return axios($, { url: `${this._baseUrl()}${path}`, headers: { "Authorization": `Bearer ${this.$auth.oauth_access_token}`, "Content-Type": (contentType) ? contentType : "application/json", }, ...opts, + validateStatus: () => true, // Don't throw on non-2xx responses }) + .then((response) => { + // Handle API errors with appropriate messages + if (response.status >= 400) { + const errorMsg = response.data?.message || `Request failed with status ${response.status}`; + if (response.status === 429) { + throw new Error(`WordPress API rate limit exceeded: ${errorMsg}`); + } else if (response.status === 401 || response.status === 403) { + throw new Error(`Authentication error: ${errorMsg}. Please check your WordPress.com API credentials.`); + } else { + throw new Error(`WordPress API error: ${errorMsg}`); + } + } + return response; + }); },
🧹 Nitpick comments (2)
components/wordpress_com/wordpress_com.app.mjs (2)
7-45: prop definitions look good, but consider input validation.The
siteIdandpostIdprop definitions with async options are well-structured, providing a good user experience with dynamic loading. However, the description forsiteIdinstructs users "Do not include 'https://' or 'www'", which relies on user compliance rather than programmatic validation.Consider adding a validation function to automatically strip or reject invalid inputs:
siteId: { type: "string", label: "Site ID or Domain", description: "Enter a site ID or domain (e.g. testsit38.wordpress.com). Do not include 'https://' or 'www'.", + validateInput: (input) => { + if (input.includes('https://') || input.includes('http://') || input.includes('www.')) { + return "Please enter the domain without 'https://', 'http://' or 'www' prefix"; + } + return true; + }, async options() { // ... } }
152-157: Add JSDoc comments for better documentation.The methods in this file lack JSDoc comments, which would improve understanding of parameters, return values, and potential errors.
Add JSDoc comments for better documentation:
+ /** + * Lists all WordPress.com sites the authenticated user has access to + * + * @param {Object} opts - Additional options to pass to the request + * @returns {Promise<Object>} Response containing the sites array + */ listSites(opts = {}) { return this._makeRequest({ path: "/me/sites", ...opts, }); },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
components/wordpress_com/actions/create-post/create-post.mjs(1 hunks)components/wordpress_com/actions/delete-post/delete-post.mjs(1 hunks)components/wordpress_com/actions/upload-media/upload-media.mjs(1 hunks)components/wordpress_com/sources/new-comment/new-comment.mjs(1 hunks)components/wordpress_com/sources/new-follower/new-follower.mjs(1 hunks)components/wordpress_com/sources/new-post/new-post.mjs(1 hunks)components/wordpress_com/wordpress_com.app.mjs(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/wordpress_com/actions/create-post/create-post.mjs
🚧 Files skipped from review as they are similar to previous changes (5)
- components/wordpress_com/sources/new-comment/new-comment.mjs
- components/wordpress_com/actions/upload-media/upload-media.mjs
- components/wordpress_com/actions/delete-post/delete-post.mjs
- components/wordpress_com/sources/new-follower/new-follower.mjs
- components/wordpress_com/sources/new-post/new-post.mjs
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
- GitHub Check: Publish TypeScript components
🔇 Additional comments (3)
components/wordpress_com/wordpress_com.app.mjs (3)
1-2: Good job with modularizing the component.The imports look clean and appropriate. Importing common methods from a separate file promotes code reusability and maintainability.
48-50: LGTM - Clean base URL implementation.Good practice to use a method for the base URL rather than hardcoding it throughout the component.
68-77: CRUD operations implemented correctly.The implementation of
createWordpressPost,uploadWordpressMedia, anddeleteWordpressPostmethods looks good. The comment explaining the use of POST instead of DELETE for free WordPress accounts is helpful context.Also applies to: 78-89, 90-98
Fixes #15127
Polling Sources
new-post
new-follower
new-comment
Actions
create-post
upload-media
delete-post
Summary by CodeRabbit