-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[Components] google_search_console : add “Retrieve Site Performance” & “Submit URL for Indexing” actions #16378
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 two new actions for the Google Search Console component: one to submit URLs for indexing via the Google Indexing API, and another to retrieve site performance analytics data. Each action includes new implementation modules, detailed documentation, and input validation logic. Utility and validation methods are added to a shared module, and local test scripts with supporting data and mocks are provided for development and validation. The component's main app file is updated to incorporate the new methods, and the package version is incremented to 0.7.0. Documentation is expanded to describe the new actions and testing setup. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Action
participant GoogleAPI
User->>Action: Provide input (siteUrl, etc.)
Action->>Action: Validate and trim input
Action->>GoogleAPI: Make authenticated API request
GoogleAPI-->>Action: Return API response
Action-->>User: Return summary and raw response
Assessment against linked issues
Suggested labels
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/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.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. |
|
Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:
|
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: 9
🧹 Nitpick comments (32)
components/google_search_console/tests/mockery-dollar.mjs (1)
1-1: Fix typo in comment. The word "Immitiates" is misspelled; it should be "Imitates".components/google_search_console/common/utils.mjs (2)
23-23: Fix typo in comment. Change "rimmed" to "trimmed" to accurately describe the behavior oftrimIfString.
4-21: Guard against inherited properties and optimize loops.
Usingfor…incan iterate over prototype properties; consider switching toObject.keys()and replace the blacklist array with aSetfor better performance and clarity.-export function removeCustomPropFields(input) { - const blacklist = ["extendedType", "postBody"]; - const clean = {}; - - for (const key in input) { - const prop = input[key]; - const cloned = {}; - - for (const field in prop) { - if (!blacklist.includes(field)) { - cloned[field] = prop[field]; - } - }; - - clean[key] = cloned; - }; - - return clean; -} +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; +}components/google_search_console/actions/submit-url-for-indexing/README.md (1)
1-31: Clear and comprehensive documentation.The README is well-structured and provides excellent information about the action's purpose, use cases, internals, authentication requirements, and endpoint.
Consider formatting the bare URLs as proper markdown links for better adherence to markdown best practices:
-Requires OAuth 2.0 with this scope: https://www.googleapis.com/auth/indexing +Requires OAuth 2.0 with this scope: [https://www.googleapis.com/auth/indexing](https://www.googleapis.com/auth/indexing) -https://indexing.googleapis.com/v3/urlNotifications:publish +[https://indexing.googleapis.com/v3/urlNotifications:publish](https://indexing.googleapis.com/v3/urlNotifications:publish)🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
27-27: Bare URL used
null(MD034, no-bare-urls)
31-31: Bare URL used
null(MD034, no-bare-urls)
components/google_search_console/tests/methods/test-checkIfUrlValid.mjs (2)
5-6: Fix typo in comment.There's a small typo in the comment.
-// Any other case from bogus data shoul lead to throw +// Any other case from bogus data should lead to throw
55-96: Robust test logic with minor enhancement opportunities.The test provides comprehensive coverage of various URL formats and edge cases, which aligns well with the PR's focus on robust input validation.
Consider adding a check to ensure
bogusCaseexists invalidCasesbefore trying to access it to prevent potential undefined property access:console.log ("=============="); let result; const testArg = bogus[bogusCase].value; const extendedType = bogus[bogusCase].extendedType; try { console.log("ENTERED VALUE", testArg, "of extended type ", extendedType); result = methods.checkIfUrlValid(testArg); } catch(err) { if (err.isCustom) { console.log ("------- \x1b[32m EXPECTED THROW PASS!\x1b[0m", "Custom error was thrown as expected" ); console.log(); } else { console.log ("--- \x1b[31m HARD FAIL! \x1b[0m", "UNEXPECTED ERROR WAS THROWN"); console.log (err); counterOfFails++; }; continue; } + // Skip validation if this case isn't in our validCases mapping + if (!validCases[bogusCase]) { + console.log ("--- \x1b[33m SKIPPED! \x1b[0m", "No expected values defined for this case"); + continue; + } const pass = (result.warnings.length === validCases[bogusCase].warnings )&& (result.url === validCases[bogusCase].url);components/google_search_console/tests/README.md (1)
1-44: Well-organized testing documentation.This README provides clear information about the test suite structure and purpose. The explicit notes about the tests being for local development only and that they can be safely deleted are particularly helpful.
Fix the markdown linting issues by removing extra spaces after the hash marks in headings:
-# Local Tests Directory +# Local Tests Directory -## Folder Structure +## Folder Structure🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
1-1: Multiple spaces after hash on atx style heading
null(MD019, no-multiple-space-atx)
8-8: Multiple spaces after hash on atx style heading
null(MD019, no-multiple-space-atx)
components/google_search_console/tests/methods/test-throwIfNotYMDDashDate.mjs (3)
15-15: Incorrect console log messageThe console log message indicates "Running checkUrl() tests..." but this script is testing the
throwIfNotYMDDashDatefunction, notcheckUrl().-console.log("Running checkUrl() tests..."); +console.log("Running throwIfNotYMDDashDate() tests...");
7-10: Improve test coverage with more valid test casesThe test only defines one valid test case (
aValidYMDDashDate). Consider adding more valid date formats to ensure comprehensive test coverage.const validCases = { aValidYMDDashDate: bogus.aValidYMDDashDate.value, + // Add more valid test cases + // For example: + anotherValidDate: "2023-01-01", + validLeapYearDate: "2024-02-29", };
61-63: Add overall test pass/fail statusThe test reports the total number of failures but doesn't clearly indicate whether the overall test suite passed or failed. Add a clear pass/fail indicator based on the counter value.
console.log ("OOOOOOOOOOOOOOOOOOOOOOOOOOOO"); console.log ("TOTAL FAILS = ", counterOfFails); +console.log (counterOfFails === 0 ? "\x1b[32mALL TESTS PASSED!\x1b[0m" : "\x1b[31mTEST SUITE FAILED!\x1b[0m"); console.log ("OOOOOOOOOOOOOOOOOOOOOOOOOOOO"); +process.exit(counterOfFails > 0 ? 1 : 0); // Exit with appropriate code for CI/CD integrationcomponents/google_search_console/tests/get-token.mjs (3)
9-9: Fix typo in placeholder textThere's a typo in the client ID placeholder.
-const clientId = "*CLIEN ID HERE*"; +const clientId = "*CLIENT ID HERE*";
56-56: Fix incomplete placeholder formatThe client secret placeholder is missing the closing asterisk.
- client_secret: "*CLIENT SECRET HERE", + client_secret: "*CLIENT SECRET HERE*",
4-23: Add token storage capability for reuse in testsThe current script displays the tokens in the console, but doesn't save them for later use in tests. Consider adding an option to save tokens to a local file (excluded from git) for test reuse.
// Bare-bones OAuth script to fetch a token. // For testing purposes only — no timeouts, no browser response. // Manually terminate the script from the console when finished. import open from "open"; import http from "http"; +import fs from "fs"; +import path from "path"; +// Optional: Save tokens to a local file for reuse in tests +const SAVE_TOKENS = true; +const TOKEN_FILE_PATH = path.join(process.cwd(), '.google_tokens.json'); // --- Google OAuth Config --- const clientId = "*CLIENT ID HERE*"; const redirectUri = "http://localhost:3000"; const scopes = [ "https://www.googleapis.com/auth/webmasters.readonly", "https://www.googleapis.com/auth/indexing", ].join(" "); +// Function to save tokens to a local file +function saveTokens(tokens) { + if (!SAVE_TOKENS) return; + try { + fs.writeFileSync(TOKEN_FILE_PATH, JSON.stringify(tokens, null, 2)); + console.log(`Tokens saved to ${TOKEN_FILE_PATH}`); + console.log('IMPORTANT: This file contains sensitive credentials. Do not commit it to version control.'); + } catch (err) { + console.error('Failed to save tokens:', err); + } +}And in the token response handler:
.then((data) => { if (data.access_token) { console.log("🎉 Tokens received!"); console.log("Access Token:", data.access_token); console.log("Refresh Token:", data.refresh_token); console.log("Expires In:", data.expires_in); + saveTokens({ + access_token: data.access_token, + refresh_token: data.refresh_token, + expires_in: data.expires_in, + created_at: Date.now() + }); console.log("✅ Token retrieval complete. Shutting down server..."); process.exit(0); } else {components/google_search_console/tests/action-tests/test-submit-url-for-indexing.mjs (4)
64-64: Replace hardcoded token placeholder with instructionsThe current placeholder for the token doesn't include clear instructions on how to replace it or where to get a valid token.
- Authorization: `Bearer *HARDCODED TOKEN HERE*`, + Authorization: `Bearer YOUR_ACCESS_TOKEN`, // Replace with a token from get-token.mjs with scope: "https://www.googleapis.com/auth/indexing"
76-76: Improve error message clarityThe current error message concatenates warnings with an unusual delimiter "!" which could be confusing to users.
- throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + warnings.join("*!*")); + const warningStr = warnings.length > 0 ? ` Warnings: ${warnings.join(", ")}` : ""; + throw new Error(`Failed to fetch data (${thrower.whoThrew} error): ${error.message}.${warningStr}`);
80-80: Improve warning display in summary messageSimilar to the error message, the summary message concatenates warnings with an unusual delimiter.
- $.export("$summary", ` URL submitted to Google: ${this.siteUrl}` + warnings.join("*!*")); + const warningStr = warnings.length > 0 ? ` (Warnings: ${warnings.join(", ")})` : ""; + $.export("$summary", `URL submitted to Google: ${this.siteUrl}${warningStr}`);
50-52: Avoid modifying URL check result directlyThe code directly accesses the URL check result's warnings property and manipulates it. Consider using a more robust approach.
- const urlCheck = gsConsole.methods.checkIfUrlValid(this.siteUrl); // TEST ONLY. Replace to "this" - - if (urlCheck.warnings) warnings.push(...urlCheck.warnings); + const urlCheck = gsConsole.methods.checkIfUrlValid(this.siteUrl); // TEST ONLY. Replace to "this" + + // Safely extract warnings if they exist + if (urlCheck && urlCheck.warnings && Array.isArray(urlCheck.warnings)) { + warnings.push(...urlCheck.warnings); + }components/google_search_console/actions/retrieve-site-performance-data/README.md (4)
1-1: Fix markdown heading formattingThere are multiple spaces after the hash symbol in the heading, which is flagged by markdown linting.
-# Google Search Console – Site Performance (Analytics) Action +# Google Search Console – Site Performance (Analytics) Action🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
1-1: Multiple spaces after hash on atx style heading
null(MD019, no-multiple-space-atx)
12-12: Fix multiple markdown heading formatting issuesAll section headings have multiple spaces after the hash, which is flagged by markdown linting.
-## Use Cases +## Use Cases -## Internals +## Internals -## Auth +## Auth -## Endpoint +## EndpointAlso applies to: 20-20, 31-31, 36-36
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
12-12: Multiple spaces after hash on atx style heading
null(MD019, no-multiple-space-atx)
33-33: Fix bare URLs in markdownThe markdown linter flags bare URLs. Consider enclosing them in angle brackets or using markdown link syntax.
-Requires OAuth 2.0 with the following scope: https://www.googleapis.com/auth/webmasters.readonly +Requires OAuth 2.0 with the following scope: `https://www.googleapis.com/auth/webmasters.readonly` -https://searchconsole.googleapis.com/webmasters/v3/sites/{siteUrl}/searchAnalytics/query +`https://searchconsole.googleapis.com/webmasters/v3/sites/{siteUrl}/searchAnalytics/query` - "siteUrl": "https://falc1.com/soda_can", + "siteUrl": "https://example.com/page",Also applies to: 37-37, 48-48
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
33-33: Bare URL used
null(MD034, no-bare-urls)
40-109: Improve example payload formattingThe example JSON payload lacks proper code block formatting and contains unnecessary comments within the JSON structure, which could confuse users trying to copy and modify it.
Consider reformatting the example as:
## 📦 Example Request Payload +```json { - // The site you want to query data for. - // Must be verified in your Google Search Console account. "siteUrl": "https://example.com/page", - // The start date of the reporting period (inclusive), in YYYY-MM-DD format. "startDate": "2025-12-22", - // The end date of the reporting period (inclusive), in YYYY-MM-DD format. "endDate": "2025-12-31", - // The dimensions you want to break down the data by. - // Valid values: "query", "page", "country", "device", "searchAppearance", "date". - // Order matters — it affects how rows are grouped in the response. "dimensions": ["query", "page", "country", "device"], - // The type of search data to include. - // Valid values: "web", "image", "video", "news", "googleNews", "discover" "searchType": "web", - // Maximum number of rows to return (1–25,000) "rowLimit": 10, - // Optional: Skips the first N rows — used for pagination. "startRow": 0, - // Optional: How to group data. - // "auto" = Google's default grouping. - // "byPage" = Group by page (useful for getting per-page breakdowns). "aggregationType": "auto", - // Optional: Data freshness filter. - // "final" = Only finalized data (more accurate). - // "all" = Includes fresh but possibly incomplete data. "dataState": "final", - // Optional filter group(s) to restrict which rows are returned. - // Each group applies logical AND/OR across its filters. "dimensionFilterGroups": [ { - // Logical grouping operator for the filters inside this group. - // "and" = all filters must match - // "or" = any filter can match "groupType": "and", - // List of individual filters to apply within the group "filters": [ { - // Which dimension to filter by (must match a dimension in your request) "dimension": "query", - // Filter operator — e.g., "equals", "contains", "notEquals", etc. "operator": "contains", - // Value to match against "expression": "example" }, { "dimension": "country", "operator": "equals", "expression": "USA" } ] } ] } +``` +### Field Descriptions + +- **siteUrl**: The site you want to query data for. Must be verified in your Google Search Console account. +- **startDate**: The start date of the reporting period (inclusive), in YYYY-MM-DD format. +- **endDate**: The end date of the reporting period (inclusive), in YYYY-MM-DD format. +- **dimensions**: The dimensions you want to break down the data by. Valid values: "query", "page", "country", "device", "searchAppearance", "date". Order matters — it affects how rows are grouped in the response. +- **searchType**: The type of search data to include. Valid values: "web", "image", "video", "news", "googleNews", "discover" +- **rowLimit**: Maximum number of rows to return (1–25,000) +- **startRow**: Optional: Skips the first N rows — used for pagination. +- **aggregationType**: Optional: How to group data. "auto" = Google's default grouping. "byPage" = Group by page (useful for getting per-page breakdowns). +- **dataState**: Optional: Data freshness filter. "final" = Only finalized data (more accurate). "all" = Includes fresh but possibly incomplete data. +- **dimensionFilterGroups**: Optional filter group(s) to restrict which rows are returned. Each group applies logical AND/OR across its filters. + - **groupType**: Logical grouping operator for the filters inside this group. "and" = all filters must match, "or" = any filter can match + - **filters**: List of individual filters to apply within the group + - **dimension**: Which dimension to filter by (must match a dimension in your request) + - **operator**: Filter operator — e.g., "equals", "contains", "notEquals", etc. + - **expression**: Value to match against🧰 Tools
🪛 LanguageTool
[uncategorized] ~109-~109: Loose punctuation mark.
Context: ...ssion": "USA" } ] } ] }(UNLIKELY_OPENING_PUNCTUATION)
🪛 markdownlint-cli2 (0.17.2)
48-48: Bare URL used
null(MD034, no-bare-urls)
components/google_search_console/actions/submit-url-for-indexing/submit-url-for-indexing.mjs (4)
8-8: Import formatting and organization can be improved.The spacing after
trimIfStringimport is inconsistent. Consider adding a comma after the import.-import {trimIfString } from "../../common/utils.mjs" +import { trimIfString } from "../../common/utils.mjs"
60-60: Fix extra space in Authorization header.There's an extra space between "Bearer" and the token which could potentially cause authentication issues.
- Authorization: `Bearer ${this.gsConsole.$auth.oauth_access_token}`, + Authorization: `Bearer ${this.gsConsole.$auth.oauth_access_token}`,
78-79: Improve error message readability.The warning separator might make error messages difficult to read. Consider adding a space before warnings are appended.
- throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + warnings.join("*!*")); + throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + (warnings.length ? " " + warnings.join("*!*") : ""));
82-82: Improve summary message readability.Similar to the error message, consider adding a space before appending warnings.
- $.export("$summary", ` URL submitted to Google: ${this.siteUrl}` + warnings.join("*!*")); + $.export("$summary", ` URL submitted to Google: ${this.siteUrl}` + (warnings.length ? " " + warnings.join("*!*") : ""));components/google_search_console/actions/retrieve-site-performance-data/retrieve-site-performance-data.mjs (2)
183-183: Consider improving error message readability.Similar to the submit-url action, the error message could be more readable with proper spacing before warnings.
- throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + warnings.join("*!*")); + throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + (warnings.length ? " " + warnings.join("*!*") : ""));
188-188: Improve summary message readability.The summary message could be more readable with proper spacing before warnings.
- $.export("$summary", ` Fetched ${response.rows?.length || 0} rows of data. ` + warnings.join("*!*")); + $.export("$summary", ` Fetched ${response.rows?.length || 0} rows of data. ` + (warnings.length ? " " + warnings.join("*!*") : ""));components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs (3)
179-180: Remove debugging console.log statements.Production code should not contain debugging statements. Consider removing or using a conditional debug flag.
- console.log("===VALUE", this[propName]); // TEST ONLY
198-199: Remove another debugging console.log statement.Production code should not contain debugging statements.
- console.log(" SUCCESS"); // TEST ONLY
223-223: Add warnings to the error message.Unlike the actual implementation, the test code doesn't append warnings to the error message, which means the test doesn't fully match the production behavior.
- throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. `); + throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + (warnings.length ? " " + warnings.join("*!*") : ""));components/google_search_console/common/methods.mjs (2)
171-237: URL validation is comprehensive but has inconsistent return format.The
checkIfUrlValidfunction returns an object{ warnings, url }while other validators return the validated value directly. This inconsistency could lead to unexpected behavior when using these functions interchangeably.Consider either:
- Renaming to
validateUrland returning just the URL like other validators- Making all validators return the
{ warnings, value }format🧰 Tools
🪛 Biome (1.9.4)
[error] 189-189: 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)
303-305: Error handling in parseIfJsonString could be improved.Consider keeping the original error as the cause of the new error for better debugging.
- this.throwCustomError( `Can not parse JSON. Error : ${err}` + this._reasonMsg(reason)) + const error = new Error(`Can not parse JSON: ${err.message}` + this._reasonMsg(reason)); + error.cause = err; + error.isCustom = true; + throw error;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
components/google_search_console/README.md(1 hunks)components/google_search_console/actions/retrieve-site-performance-data/README.md(1 hunks)components/google_search_console/actions/retrieve-site-performance-data/retrieve-site-performance-data.mjs(1 hunks)components/google_search_console/actions/submit-url-for-indexing/README.md(1 hunks)components/google_search_console/actions/submit-url-for-indexing/submit-url-for-indexing.mjs(1 hunks)components/google_search_console/common/methods.mjs(1 hunks)components/google_search_console/common/utils.mjs(1 hunks)components/google_search_console/google_search_console.app.mjs(1 hunks)components/google_search_console/tests/README.md(1 hunks)components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs(1 hunks)components/google_search_console/tests/action-tests/test-submit-url-for-indexing.mjs(1 hunks)components/google_search_console/tests/get-token.mjs(1 hunks)components/google_search_console/tests/methods/bogus-data/bogus-data-google-date.mjs(1 hunks)components/google_search_console/tests/methods/bogus-data/bogus-data-url.mjs(1 hunks)components/google_search_console/tests/methods/test-checkIfUrlValid.mjs(1 hunks)components/google_search_console/tests/methods/test-throwIfNotYMDDashDate.mjs(1 hunks)components/google_search_console/tests/mockery-dollar.mjs(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
components/google_search_console/actions/submit-url-for-indexing/README.md
27-27: Bare URL used
null
(MD034, no-bare-urls)
31-31: Bare URL used
null
(MD034, no-bare-urls)
components/google_search_console/tests/README.md
1-1: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
8-8: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
components/google_search_console/actions/retrieve-site-performance-data/README.md
1-1: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
12-12: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
20-20: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
31-31: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
33-33: Bare URL used
null
(MD034, no-bare-urls)
36-36: Multiple spaces after hash on atx style heading
null
(MD019, no-multiple-space-atx)
37-37: Bare URL used
null
(MD034, no-bare-urls)
48-48: Bare URL used
null
(MD034, no-bare-urls)
🪛 LanguageTool
components/google_search_console/actions/retrieve-site-performance-data/README.md
[uncategorized] ~109-~109: Loose punctuation mark.
Context: ...ssion": "USA" } ] } ] }
(UNLIKELY_OPENING_PUNCTUATION)
🪛 Biome (1.9.4)
components/google_search_console/common/methods.mjs
[error] 189-189: 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)
🔇 Additional comments (8)
components/google_search_console/google_search_console.app.mjs (1)
1-2: Well-structured integration of shared methods.The approach of importing validation methods from a common module and integrating them with the spread operator is clean and maintainable. This pattern promotes code reuse and ensures consistent validation behavior across the component's actions.
Also applies to: 8-8
components/google_search_console/actions/submit-url-for-indexing/submit-url-for-indexing.mjs (1)
33-48: The validation and warning handling looks robust.The approach of accumulating warnings without blocking execution aligns well with the PR objective of identifying suspicious but not clearly invalid inputs.
components/google_search_console/actions/retrieve-site-performance-data/retrieve-site-performance-data.mjs (3)
27-99: Well-structured prop metadata with comprehensive validation.The approach of defining extended metadata separately from standard Pipedream props enables rich validation while maintaining UI compatibility. The
postBodyflag efficiently marks which props should be included in the API request.
119-127: This approach to JSON validation is robust.Handling both object and string inputs for
dimensionFilterGroupsprovides good flexibility for users, whether they're configuring through the UI or programmatically.
141-160: The validation loop is elegant and handles optional fields correctly.The loop efficiently processes all props using their metadata, respecting optional fields and accumulating warnings without blocking execution.
components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs (1)
1-18: Well-documented test file with clear instructions.The header comments clearly explain the purpose of this file and how to use it, which is excellent for maintainability.
components/google_search_console/common/methods.mjs (2)
8-12: Good approach for custom error handling.Adding the
isCustomflag to errors makes it easier to distinguish between internal validation errors and external API errors.
255-284: The validateUserInput function is well designed.Using a mapping object to dispatch to the appropriate validator based on type is a clean approach and makes adding new validators easy.
components/google_search_console/tests/methods/bogus-data/bogus-data-url.mjs
Outdated
Show resolved
Hide resolved
components/google_search_console/tests/methods/bogus-data/bogus-data-google-date.mjs
Outdated
Show resolved
Hide resolved
components/google_search_console/tests/methods/test-throwIfNotYMDDashDate.mjs
Outdated
Show resolved
Hide resolved
components/google_search_console/tests/action-tests/test-submit-url-for-indexing.mjs
Outdated
Show resolved
Hide resolved
components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs
Outdated
Show resolved
Hide resolved
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 (5)
components/google_search_console/common/methods.mjs (4)
94-102: 🛠️ Refactor suggestionMethod implementation is inverted from what its name suggests.
Similar to the array validation method, the name suggests it throws when the input is not an object, but the implementation returns the input when it is an object and throws otherwise.
Rename the method to match its behavior:
- throwIfNotObject(input, reason) { + validateObject(input, reason) { if( typeof input === "object" && input !== null && !Array.isArray(input)){ return input; }; this.throwCustomError(`Invalid argument type. Expected an object ` + this._reasonMsg(reason)); },
189-189:⚠️ Potential issueFix misleading character class in regex.
The character class contains zero-width joiners which can't be matched correctly in a character class.
Replace with alternation as recommended by the static analysis tool:
- const dubiousCharRegex = /[\\<>{}|"`^]|[\u200B\u200C\u200D\u2060\uFEFF\u00A0]/g; + const dubiousCharRegex = /[\\<>{}|"`^]|\u200B|\u200C|\u200D|\u2060|\uFEFF|\u00A0/g;🧰 Tools
🪛 Biome (1.9.4)
[error] 189-189: 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)
63-70: 🛠️ Refactor suggestionMethod names don't match implementation logic.
The method name
throwIfNotArraysuggests it throws when the condition isn't met, but it returns the input when the condition is met and throws otherwise. This creates confusion about the expected behavior.Rename the method to better reflect its behavior:
- throwIfNotArray(input, reason) { + validateArray(input, reason) { if (!Array.isArray(input)) { this.throwCustomError(`Invalid argument type. Expected an array ` + this._reasonMsg(reason)); }; return input; },
109-117: 🛠️ Refactor suggestionMethod name contradicts its implementation.
The naming pattern continues to be inconsistent with the implementation. The method returns the input when it is an object or array, rather than throwing when it's not.
Rename for clarity:
-throwIfNotObjectOrArray(input, reason) { +validateObjectOrArray(input, reason) { if( typeof input === "object" && input !== null){ return input; }; this.throwCustomError(`Invalid argument type. Expected an object or array` + this._reasonMsg(reason)); },components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs (1)
211-214:⚠️ Potential issueReplace hardcoded token with environment variable.
Hardcoded tokens—even placeholders—risk accidental commits of real credentials.
Load tokens from environment variables instead:
- Authorization: `Bearer *HARDCODED TOKEN HERE*`, + Authorization: `Bearer ${process.env.GSC_API_TOKEN}`,Add a
.env.examplefile withGSC_API_TOKEN=your_token_hereand ensure.envis in.gitignore.
🧹 Nitpick comments (2)
components/google_search_console/common/methods.mjs (1)
232-235: Return trimmed URL for consistency.The method trims the input URL for validation but returns the original untrimmed URL, which could lead to inconsistencies.
Return the trimmed version for consistency:
return { warnings : warnings, - url : input, + url : trimmedInput, };components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs (1)
179-179: Remove debug logging statement.This console log is useful for development but should be removed or commented out before submission.
- console.log("===VALUE", this[propName]); + // console.log("===VALUE", this[propName]);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
components/google_search_console/actions/retrieve-site-performance-data/README.md(1 hunks)components/google_search_console/actions/retrieve-site-performance-data/retrieve-site-performance-data.mjs(1 hunks)components/google_search_console/actions/submit-url-for-indexing/submit-url-for-indexing.mjs(1 hunks)components/google_search_console/common/methods.mjs(1 hunks)components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs(1 hunks)components/google_search_console/tests/action-tests/test-submit-url-for-indexing.mjs(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- components/google_search_console/actions/retrieve-site-performance-data/README.md
- components/google_search_console/actions/submit-url-for-indexing/submit-url-for-indexing.mjs
- components/google_search_console/tests/action-tests/test-submit-url-for-indexing.mjs
- components/google_search_console/actions/retrieve-site-performance-data/retrieve-site-performance-data.mjs
🧰 Additional context used
🪛 Biome (1.9.4)
components/google_search_console/common/methods.mjs
[error] 189-189: 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)
🔇 Additional comments (3)
components/google_search_console/common/methods.mjs (1)
265-273: Good implementation of validator selection.The validator mapping approach makes the code maintainable and easy to extend. The use of extended types is a nice design that allows specialized validation beyond basic types.
components/google_search_console/tests/action-tests/test-retrieve-site-performance-data.mjs (2)
31-69: Well-structured test data with comprehensive coverage.The test data covers all required fields and includes optional parameters with valid values, making it an excellent test case for the action.
167-199: Good validation loop with warning accumulation.The validation approach is robust and user-friendly:
- Trims string inputs
- Skips optional empty fields
- Validates inputs with appropriate validators
- Accumulates warnings instead of failing immediately
- Builds the request body dynamically
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 (5)
components/google_search_console/common/tests/methods/test-throwIfNotYMDDashDate.mjs (2)
6-9: Consider expanding test coverage with additional valid cases.The
validCasesobject only contains a single test case. Adding more explicit valid test cases would improve test coverage and make the validation logic more robust.const validCases = { aValidYMDDashDate: bogus.aValidYMDDashDate.value, + // Add more valid cases with expected results + aValidFutureDate: "2030-01-01", + aValidPastDate: "2000-12-31", };
15-52: Consider using a standard testing framework.The custom test harness with console logs works but lacks the structure and reporting capabilities of standard testing frameworks. Consider migrating to Jest, Mocha, or another testing framework for more maintainable tests.
For example, with Jest:
import methods from "../../common/methods.mjs"; import bogus from "./bogus-data/bogus-data-google-date.mjs"; describe('throwIfNotYMDDashDate', () => { // Test valid cases test.each([ ['aValidYMDDashDate', bogus.aValidYMDDashDate.value], ])('valid date %s returns expected result', (testName, value) => { expect(methods.throwIfNotYMDDashDate(value)).toBe(value); }); // Test invalid cases test.each( Object.entries(bogus) .filter(([key]) => key !== 'aValidYMDDashDate') .map(([key, data]) => [key, data.value, data.extendedType]) )('invalid date %s throws custom error', (testName, value, type) => { expect(() => methods.throwIfNotYMDDashDate(value)).toThrow(); }); });components/google_search_console/common/tests/methods/test-checkIfUrlValid.mjs (1)
51-89: Consider using a standard testing framework.Similar to the previous file, consider migrating this custom test harness to a standard testing framework like Jest or Mocha for better maintainability and reporting.
For example with Jest:
import methods from "../../../common/methods.mjs"; import bogus from "./bogus-data/bogus-data-url.mjs"; describe('checkIfUrlValid', () => { // Test valid cases test.each([ ['aValidHttpsUrl', bogus.aValidHttpsUrl.value, 0, bogus.aValidHttpsUrl.value], ['aValidUrlWithoutProtocol', bogus.aValidUrlWithoutProtocol.value, 1, bogus.aValidUrlWithoutProtocol.value], // Add more test cases... ])('valid URL %s returns expected result', (testName, url, warningCount, normalizedUrl) => { const result = methods.checkIfUrlValid(url); expect(result.warnings.length).toBe(warningCount); expect(result.url).toBe(normalizedUrl); }); // Test invalid cases that should throw test.each( // Filter for cases that should throw // ... )('invalid URL %s throws custom error', (testName, url) => { expect(() => methods.checkIfUrlValid(url)).toThrow(); }); });components/google_search_console/common/tests/action-tests/test-retrieve-site-performance-data.mjs (1)
35-39: Future test dates may cause issues with the API.The test data includes future dates (2025), which may be rejected by the Google Search Console API. Consider using dates in the past for more reliable testing.
// Required - startDate: "2025-12-22", - endDate: "2025-12-31", + startDate: "2023-01-01", + endDate: "2023-01-31",components/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.mjs (1)
53-53: Confusing inline comment.The comment "TEST ONLY. Replace to 'this'" is ambiguous and doesn't clearly indicate what should be replaced in production code.
- const urlCheck = gsConsole.methods.checkIfUrlValid(this.siteUrl); // TEST ONLY. Replace to "this" + const urlCheck = gsConsole.methods.checkIfUrlValid(this.url); // In production code, use the correct property name
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
components/google_search_console/common/tests/README.md(1 hunks)components/google_search_console/common/tests/action-tests/test-retrieve-site-performance-data.mjs(1 hunks)components/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.mjs(1 hunks)components/google_search_console/common/tests/get-token.mjs(1 hunks)components/google_search_console/common/tests/methods/bogus-data/bogus-data-google-date.mjs(1 hunks)components/google_search_console/common/tests/methods/bogus-data/bogus-data-url.mjs(1 hunks)components/google_search_console/common/tests/methods/test-checkIfUrlValid.mjs(1 hunks)components/google_search_console/common/tests/methods/test-throwIfNotYMDDashDate.mjs(1 hunks)components/google_search_console/common/tests/mockery-dollar.mjs(1 hunks)
✅ Files skipped from review due to trivial changes (5)
- components/google_search_console/common/tests/mockery-dollar.mjs
- components/google_search_console/common/tests/README.md
- components/google_search_console/common/tests/methods/bogus-data/bogus-data-url.mjs
- components/google_search_console/common/tests/get-token.mjs
- components/google_search_console/common/tests/methods/bogus-data/bogus-data-google-date.mjs
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
🔇 Additional comments (5)
components/google_search_console/common/tests/methods/test-checkIfUrlValid.mjs (2)
6-45: Well-defined test cases covering diverse URL formats.The test includes a comprehensive set of valid cases with expected warnings and normalized URLs for various URL formats including:
- Valid HTTP/HTTPS URLs
- URLs without protocols
- URLs with dubious characters
- Malformed slashes
This thorough approach ensures robust validation.
75-78: Robust validation checking both warnings and URL normalization.The test correctly validates both aspects of the URL validation function:
- The number of warnings generated
- The normalized URL output
This dual validation ensures the function provides both proper feedback and correctly handles the URL.
components/google_search_console/common/tests/action-tests/test-retrieve-site-performance-data.mjs (3)
1-18: Clear documentation for local test runner.The file header provides excellent documentation explaining the purpose, usage requirements, and limitations of the test runner. This helps developers understand how to use it safely for local debugging.
189-213: Comprehensive validation and prop processing logic.The input processing loop effectively:
- Validates user inputs with appropriate validation rules
- Collects warnings without blocking execution for suspicious inputs
- Populates the request body with validated values
- Handles optional props appropriately
This robust approach ensures API requests are well-formed while providing clear feedback.
233-239: Good error handling with detailed context.The error handling logic:
- Distinguishes between internal validation errors and API errors
- Includes accumulated warnings in the error message
- Preserves the original error message for debugging
This helps developers quickly identify whether issues come from input validation or the external API.
components/google_search_console/common/tests/methods/test-throwIfNotYMDDashDate.mjs
Show resolved
Hide resolved
...ents/google_search_console/common/tests/action-tests/test-retrieve-site-performance-data.mjs
Show resolved
Hide resolved
components/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.mjs
Show resolved
Hide resolved
components/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.mjs
Show resolved
Hide resolved
components/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.mjs
Outdated
Show resolved
Hide resolved
components/google_search_console/common/tests/action-tests/test-submit-url-for-indexing.mjs
Show resolved
Hide resolved
michelle0927
left a comment
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.
Thanks for your contribution! Ready for QA!
|
@michelle0927 Cool. Thanks =) |
Fixes #15016
Note
I’d love to contribute more in the future — so if anything I’ve done here is non-idiomatic or misaligned with Pipedream practices, , I’m genuinely happy to adjust and improve.
What’s Included
This PR introduces two new actions for the Google Search Console integration:
Retrieve Site Performance Data
Fetches search analytics with flexible filtering, dimensions, and pagination.
Submit URL for Indexing
⚠️ Note: The standard Google Search Console app does not include the required Indexing API scope so this action was tested using a manually generated token with appropriate permissions.
Notifies Google that a page's content has been updated.
Input Validation Philosophy
These actions include input validation before sending requests to the external API, and they clearly identify which field caused the error when one is detected.
While some users may expect to receive raw API errors (e.g. 400, 403, etc.), this validation is intentionally scoped to catch only definitely invalid inputs — not to override meaningful errors from the external service.
For inputs that appear suspicious but are not clearly invalid, the action does not block execution. Instead, it issues a warning in the UI to help users catch potential issues early without interrupting the workflow.
Examples of Validation Behavior
🛑 Inputs That Throw an Error
These inputs are considered definitely invalid, and the action will block execution:
These inputs are suspicious but not clearly invalid. The action continues execution, but a warning is shown in the $summary:
These issues are often mishandled by APIs or lead to unclear responses like "invalid url" or "bad request".
Catching them early improves clarity, avoids unnecessary requests, and helps users debug faster.
I’m aware this introduces a layer of abstraction over the API’s native error handling, and I’m happy to revisit this if it becomes a problem.
However, I believe the trade-off is justified — especially in light of the Pipedream documentation:
✅ Testing Notes
These actions were tested both locally (via custom test runners in the /tests folder) and through the Pipedream UI using real authenticated accounts and verified sites.
Test coverage includes:
📁 About the /tests Folder
You’ll notice a /tests folder included in this PR.
It contains local test runners and helper scripts used to simulate the $ context and invoke the actions outside the Pipedream platform.
While not required for production, it:
Thanks again for the awesome platform!
Summary by CodeRabbit