Skip to content

Conversation

@PrajwalLokhande2003
Copy link
Contributor

@PrajwalLokhande2003 PrajwalLokhande2003 commented Nov 21, 2025

WHY

Summary by CodeRabbit

  • New Features
    • Added six new Google Sheets actions: add/update/delete conditional format rules, add protected ranges, set data validation, and merge cells.
    • Converted New Comments, New Row Added, New Updates, and New Worksheet sources from instant to polling-based detection for improved reliability.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Nov 21, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
pipedream-docs-redirect-do-not-edit Ignored Ignored Nov 21, 2025 0:31am

@pipedream-component-development
Copy link
Collaborator

Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified.

@pipedream-component-development
Copy link
Collaborator

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:

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Walkthrough

Adds six new Google Sheets action modules for conditional formatting, protected ranges, cell merging, and data validation operations. Simultaneously refactors four event sources from instant webhook-based detection to polling-based detection using timers, introducing database state management and comparison logic.

Changes

Cohort / File(s) Summary
New Google Sheets Actions (Formatting & Rules)
components/google_sheets/actions/add-conditional-format-rule/add-conditional-format-rule.mjs, components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs, components/google_sheets/actions/delete-conditional-format-rule/delete-conditional-format-rule.mjs
Adds three modules for managing conditional format rules. Add and update support both boolean rules (with text formatting) and gradient rules (with color interpolation). Delete removes rules by index. All construct batchUpdate requests with range parsing and RGB color handling.
New Google Sheets Actions (Range & Data Operations)
components/google_sheets/actions/merge-cells/merge-cells.mjs, components/google_sheets/actions/add-protected-range/add-protected-range.mjs, components/google_sheets/actions/set-data-validation/set-data-validation.mjs
Adds three modules for cell operations. Merge-cells combines specified ranges with configurable merge type. Add-protected-range restricts editing with editor lists. Set-data-validation applies validation rules with user-entered values. All parse ranges and execute batchUpdate requests.
Polling Source Refactoring (Instant → Polling)
components/google_sheets/sources/new-comment/new-comment.mjs, components/google_sheets/sources/new-row-added/new-row-added.mjs, components/google_sheets/sources/new-updates/new-updates.mjs, components/google_sheets/sources/new-worksheet/new-worksheet.mjs
Refactors four event sources from instant webhook-based to timer-based polling. Removes httpBase composition and introduces explicit props (db, http, google_sheets). Each implements polling logic with database state comparison, data-fetching helpers, and emit on changes.
Package Metadata
components/google_sheets/package.json
Bumps version from 0.10.0 to 0.11.0.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant Source
    participant DB as Database
    participant API as Google Sheets API
    
    rect rgb(230, 240, 250)
    Note over Source: Polling Cycle (Timer-triggered)
    User->>Source: Timer fires
    Source->>DB: Get stored state (IDs/data/count)
    Source->>API: Fetch current sheet data/metadata
    API-->>Source: Return current state
    Source->>Source: Compare: stored vs. current
    
    alt Changes Detected
        Source->>Source: Compute diff/new items
        Source->>User: Emit event(s) with payload
        Source->>DB: Update stored state
    else No Changes
        Source->>Source: Skip emit
    end
    end
Loading
sequenceDiagram
    autonumber
    participant User
    participant Action as Conditional Format Action
    participant Parser as Range Parser
    participant GoogleSheets as Google Sheets API
    
    rect rgb(240, 250, 230)
    Note over Action: Add/Update Conditional Format Rule
    User->>Action: Provide range, condition, formatting
    Action->>Parser: Parse range (A1:B10)
    Parser-->>Action: Return row/col indices
    
    alt Formatting Type
        Note over Action: Boolean Rule path
        Action->>Action: Build condition + format (bold, color, etc.)
    else 
        Note over Action: Gradient Rule path
        Action->>Action: Build min/mid/max points with colors
    end
    
    Action->>Action: Parse RGB (JSON string or object)
    Action->>GoogleSheets: batchUpdate with rule
    GoogleSheets-->>Action: Return response
    Action->>User: Export summary + response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Conditional formatting rules (add-conditional-format-rule.mjs, update-conditional-format-rule.mjs, delete-conditional-format-rule.mjs): Verify correctness of gradient vs. boolean rule branching, RGB color parsing (JSON vs. object handling), and range-to-index transformation logic across all three modules.
  • Polling source refactoring (all four sources): Confirm database state management is correct, comparison logic accurately detects changes, and edge cases (first run, empty sheets, concurrent modifications) are handled properly.
  • Protected range editor list (add-protected-range.mjs): Verify that protectors array is correctly serialized and that user permissions are enforced as intended.
  • Cross-cutting concern: Ensure consistent error handling and logging patterns across new actions and refactored sources; check that ConfigurationError is used appropriately for invalid inputs.

Suggested reviewers

  • luancazarine

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is incomplete—it contains only the template structure with the 'WHY' heading but no actual content, leaving the placeholder comment '' unaddressed. Complete the description by filling in the 'WHY' section with details explaining the motivation, context, and purpose of adding these 6 new Google Sheets actions and refactoring the polling sources.
Title check ❓ Inconclusive The title 'Add action in google sheet' is vague and generic—it lacks specificity about which actions are being added and does not convey the actual scope of changes (6 new actions plus source refactoring). Provide a more specific and descriptive title that reflects the primary change, such as 'Add Google Sheets actions for conditional formatting, data validation, and protected ranges' or 'Add multiple Google Sheets actions and refactor sources to polling-based implementation'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 22

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e67e47a and cfcdb6e.

📒 Files selected for processing (11)
  • components/google_sheets/actions/add-conditional-format-rule/add-conditional-format-rule.mjs (1 hunks)
  • components/google_sheets/actions/add-protected-range/add-protected-range.mjs (1 hunks)
  • components/google_sheets/actions/delete-conditional-format-rule/delete-conditional-format-rule.mjs (1 hunks)
  • components/google_sheets/actions/merge-cells/merge-cells.mjs (1 hunks)
  • components/google_sheets/actions/set-data-validation/set-data-validation.mjs (1 hunks)
  • components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs (1 hunks)
  • components/google_sheets/package.json (1 hunks)
  • components/google_sheets/sources/new-comment/new-comment.mjs (3 hunks)
  • components/google_sheets/sources/new-row-added/new-row-added.mjs (1 hunks)
  • components/google_sheets/sources/new-updates/new-updates.mjs (1 hunks)
  • components/google_sheets/sources/new-worksheet/new-worksheet.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
components/google_sheets/actions/add-protected-range/add-protected-range.mjs (2)
components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs (2)
  • request (218-232)
  • response (234-234)
components/google_sheets/google_sheets.app.mjs (4)
  • startRow (142-142)
  • endRow (143-145)
  • startCol (138-138)
  • endCol (139-141)
components/google_sheets/actions/delete-conditional-format-rule/delete-conditional-format-rule.mjs (2)
components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs (2)
  • request (218-232)
  • response (234-234)
components/google_sheets/actions/add-conditional-format-rule/add-conditional-format-rule.mjs (2)
  • request (206-218)
  • response (219-219)
components/google_sheets/actions/add-conditional-format-rule/add-conditional-format-rule.mjs (2)
components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs (4)
  • rule (142-152)
  • parseRgbColor (153-162)
  • request (218-232)
  • response (234-234)
components/google_sheets/google_sheets.app.mjs (4)
  • startRow (142-142)
  • endRow (143-145)
  • startCol (138-138)
  • endCol (139-141)
components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs (2)
components/google_sheets/google_sheets.app.mjs (4)
  • startRow (142-142)
  • endRow (143-145)
  • startCol (138-138)
  • endCol (139-141)
components/google_sheets/actions/delete-conditional-format-rule/delete-conditional-format-rule.mjs (2)
  • request (47-59)
  • response (60-60)
components/google_sheets/actions/set-data-validation/set-data-validation.mjs (4)
components/google_sheets/actions/update-conditional-format-rule/update-conditional-format-rule.mjs (2)
  • request (218-232)
  • response (234-234)
components/google_sheets/actions/add-protected-range/add-protected-range.mjs (2)
  • request (81-106)
  • response (107-107)
components/google_sheets/actions/merge-cells/merge-cells.mjs (2)
  • request (67-85)
  • response (86-86)
components/google_sheets/google_sheets.app.mjs (4)
  • startRow (142-142)
  • endRow (143-145)
  • startCol (138-138)
  • endCol (139-141)
components/google_sheets/sources/new-row-added/new-row-added.mjs (1)
components/google_sheets/sources/new-updates/new-updates.mjs (4)
  • response (33-36)
  • response (45-51)
  • response (60-66)
  • stateKey (127-127)
components/google_sheets/actions/merge-cells/merge-cells.mjs (2)
components/google_sheets/actions/set-data-validation/set-data-validation.mjs (2)
  • request (90-117)
  • response (118-118)
components/google_sheets/google_sheets.app.mjs (4)
  • startRow (142-142)
  • endRow (143-145)
  • startCol (138-138)
  • endCol (139-141)
components/google_sheets/sources/new-updates/new-updates.mjs (2)
components/google_sheets/sources/new-row-added/new-row-added.mjs (5)
  • response (39-42)
  • stateKey (72-72)
  • stateKey (82-82)
  • stateKey (92-92)
  • stateKey (102-102)
components/google_sheets/sources/new-worksheet/new-worksheet.mjs (3)
  • response (30-36)
  • stateKey (63-63)
  • stateKey (72-72)
components/google_sheets/sources/new-worksheet/new-worksheet.mjs (2)
components/google_sheets/sources/new-row-added/new-row-added.mjs (5)
  • response (39-42)
  • stateKey (72-72)
  • stateKey (82-82)
  • stateKey (92-92)
  • stateKey (102-102)
components/google_sheets/sources/new-updates/new-updates.mjs (4)
  • response (33-36)
  • response (45-51)
  • response (60-66)
  • stateKey (127-127)
🔇 Additional comments (10)
components/google_sheets/sources/new-comment/new-comment.mjs (4)

14-19: LGTM: Reasonable timer configuration.

The 60-second polling interval is a good balance between responsiveness and API rate limit considerations for comment detection.


64-67: LGTM: Clean timer-based implementation.

The simplified run() method is appropriate for timer-based polling. The architectural shift from event-driven (httpBase) to timer-driven is implemented correctly here.

Note: This is part of a broader architectural change from instant webhook-based detection to polling-based detection. Ensure this change is intentional and documented for users who may be migrating from the previous version.


45-52: Verify API signature and improve error handling.

Several concerns with this implementation:

  1. API signature verification needed: Confirm that this.app.listComments(sheetID, lastTs) is the correct method signature and that it accepts lastTs as a filter parameter.
  2. Silent failure: The try/catch block only logs errors to the console. Users won't be notified of authentication failures, rate limits, or other API errors.
  3. Undefined lastTs on first run: The first time this runs, lastTs will be undefined. Verify that the API handles this correctly (e.g., returns all comments or applies a sensible default).

Consider improving error handling to surface issues to users:

   } catch (error) {
-    console.error("Error fetching comments:", error);
+    console.error("Error fetching comments:", error);
+    throw new Error(`Failed to fetch comments from Google Sheets: ${error.message}`);
   }

Run this script to verify the API method signature:


53-62: Verify comment ordering assumptions.

Line 57 sets lastTs from comments[0], assuming that the API returns comments in reverse chronological order (newest first). The comments are then reversed at line 58 to emit events in chronological order (oldest to newest).

Verify that app.listComments returns comments sorted by createdTime in descending order (newest first). If the ordering is different or undefined, this logic will fail to track the correct last timestamp.

Run this script to check the implementation and documentation:

components/google_sheets/sources/new-row-added/new-row-added.mjs (4)

6-10: LGTM: Metadata correctly reflects polling behavior.

The name change to "Polling", version bump to 0.3.0, and explicit description about bottom-row detection accurately communicate the new implementation approach.


58-64: LGTM: Helper correctly maps row data to object.

The implementation appropriately handles missing values by defaulting to empty strings. Note that any columns beyond the header count will be ignored, which is reasonable behavior for this use case.


134-152: Verify ID uniqueness for dedupe strategy.

The event ID is constructed as ${spreadsheet_id}-${sheet_name}-row-${rowNumber} (line 148), and the dedupe strategy is "unique" (line 10). If a user deletes rows and then adds new ones, the same row number could be reused, potentially causing the dedupe mechanism to suppress legitimate new events.

Verify that reusing row numbers after deletion doesn't cause dedupe issues. Consider whether a timestamp or sequence number should be included in the ID for true uniqueness:

  id: `${spreadsheet_id}-${sheet_name}-row-${rowNumber}`,

Could become:

  id: `${spreadsheet_id}-${sheet_name}-row-${rowNumber}-${Date.now()}`,

However, this would prevent deduplication of the same event, so the current approach may be intentional depending on the desired behavior.


130-160: Verify edge case handling for row deletions and insertions.

The detection logic assumes rows are only added to the bottom and never deleted or inserted elsewhere. If a user deletes rows from the middle of the sheet, the row count will decrease, and on the next poll, the logic won't detect this change (line 130 checks currentRows.length > storedRowCount).

Consider documenting this limitation in the description or adding a warning. If rows can be deleted, the current approach will silently miss the deletion event.

Run the following test scenario to verify behavior:

  1. Add 5 rows to a sheet (should emit 5 events)
  2. Delete 2 rows from the middle
  3. Add 1 row to the bottom
  4. Expected: Should emit 1 event for the new row, but row numbers may be incorrect
components/google_sheets/package.json (1)

3-3: Version bump is appropriate and scoped correctly

Incrementing the package version to 0.11.0 matches the addition of new public actions/sources and requires no further changes in this file.

components/google_sheets/sources/new-updates/new-updates.mjs (1)

41-54: Unused and probably invalid getLastModifiedTime helper

getLastModifiedTime calls the spreadsheets endpoint with fields: "spreadsheet_metadata.last_update_time", but:

  • This helper is never used anywhere in the source.
  • The requested field path doesn’t match standard Sheets API metadata fields and is likely to 400/404 if invoked.

Consider removing this method entirely until there is a concrete use case, or implementing it with a verified field path and wiring it into the polling logic.

Please confirm the correct field path from the Sheets API docs before using this helper in future changes.

Comment on lines +159 to +204
this.formattingType === "GRADIENT_RULE" ?
rule.gradientRule = {
minpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MIN",
},
midpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MID",
},
maxpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MAX",
},
} :
rule.booleanRule = {
condition: {
type: this.conditionType,
values: this.conditionValues?.map((v) => ({
userEnteredValue: v,
})) || [],
},
format: {
backgroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
textFormat: {
...this.textFormat,
foregroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
bold: this.bold,
italic: this.italic,
strikethrough: this.strikethrough,
},
},
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Rebuild gradientRule to match Sheets API contract.
value: "MIN", "MID", "MAX" and reusing one interpolation type for every point violate the InterpolationPoint schema, causing 400 invalidArgument responses. Emit MIN/MAX points without values, and only include a midpoint when the caller supplies a valid type/value pair.

-    this.formattingType === "GRADIENT_RULE" ?
-      rule.gradientRule = {
-        minpoint: {
-          colorStyle: {
-            rgbColor: parseRgbColor(this.rgbColor),
-          },
-          type: this.interpolationPointType,
-          value: "MIN",
-        },
-        midpoint: {
-          colorStyle: {
-            rgbColor: parseRgbColor(this.rgbColor),
-          },
-          type: this.interpolationPointType,
-          value: "MID",
-        },
-        maxpoint: {
-          colorStyle: {
-            rgbColor: parseRgbColor(this.rgbColor),
-          },
-          type: this.interpolationPointType,
-          value: "MAX",
-        },
-      } :
+    this.formattingType === "GRADIENT_RULE" ?
+      rule.gradientRule = {
+        minpoint: {
+          colorStyle: { rgbColor: parseRgbColor(this.rgbColor) },
+          type: "MIN",
+        },
+        ...(this.interpolationPointType && this.conditionValues?.length ? {
+          midpoint: {
+            colorStyle: { rgbColor: parseRgbColor(this.rgbColor) },
+            type: this.interpolationPointType,
+            value: this.conditionValues[0],
+          },
+        } : {}),
+        maxpoint: {
+          colorStyle: { rgbColor: parseRgbColor(this.rgbColor) },
+          type: "MAX",
+        },
+      } :

(developers.google.com)

📝 Committable suggestion

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

Suggested change
this.formattingType === "GRADIENT_RULE" ?
rule.gradientRule = {
minpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MIN",
},
midpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MID",
},
maxpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MAX",
},
} :
rule.booleanRule = {
condition: {
type: this.conditionType,
values: this.conditionValues?.map((v) => ({
userEnteredValue: v,
})) || [],
},
format: {
backgroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
textFormat: {
...this.textFormat,
foregroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
bold: this.bold,
italic: this.italic,
strikethrough: this.strikethrough,
},
},
};
this.formattingType === "GRADIENT_RULE" ?
rule.gradientRule = {
minpoint: {
colorStyle: { rgbColor: parseRgbColor(this.rgbColor) },
type: "MIN",
},
...(this.interpolationPointType && this.conditionValues?.length ? {
midpoint: {
colorStyle: { rgbColor: parseRgbColor(this.rgbColor) },
type: this.interpolationPointType,
value: this.conditionValues[0],
},
} : {}),
maxpoint: {
colorStyle: { rgbColor: parseRgbColor(this.rgbColor) },
type: "MAX",
},
} :
rule.booleanRule = {
condition: {
type: this.conditionType,
values: this.conditionValues?.map((v) => ({
userEnteredValue: v,
})) || [],
},
format: {
backgroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
textFormat: {
...this.textFormat,
foregroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
bold: this.bold,
italic: this.italic,
strikethrough: this.strikethrough,
},
},
};
🤖 Prompt for AI Agents
components/google_sheets/actions/add-conditional-format-rule/add-conditional-format-rule.mjs
lines 159-204: the gradientRule construction violates the Sheets
InterpolationPoint schema by setting value:"MIN"/"MID"/"MAX" and reusing one
interpolation type for every point; rebuild gradientRule to match the API by
emitting minPoint and maxPoint without value fields (include only colorStyle and
type), and include midpoint only when the caller provides both a valid
interpolation type and a midpoint value (use those for midpoint.type and
midpoint.value); ensure property names and casing match the Sheets API
(minPoint/midPoint/maxPoint) and remove any hard-coded "MIN"/"MID"/"MAX" value
strings so the resulting gradientRule conforms and avoids 400 invalidArgument
errors.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you test this?

Comment on lines +11 to +23
db: "$.service.db",
http: "$.interface.http",
google_sheets: {
type: "app",
app: "google_sheets",
label: "Google Sheets",
description: "Google Sheets account to access spreadsheets",
},
sheet_name: {
type: "string",
label: "Sheet Name",
description: "The name of the sheet to monitor (e.g., 'Sheet1')",
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

spreadsheet_id is used but never declared as a prop

Multiple methods destructure or reference this.spreadsheet_id (getSheetData, getLastModifiedTime, getAllSheetMetadata, run), but spreadsheet_id is not defined under props. At runtime this will be undefined, so all Sheets API requests will target .../spreadsheets/undefined, breaking the source.

Add an explicit spreadsheet_id prop consistent with other sources (e.g. new-worksheet):

   props: {
     db: "$.service.db",
     http: "$.interface.http",
     google_sheets: {
       type: "app",
       app: "google_sheets",
       label: "Google Sheets",
       description: "Google Sheets account to access spreadsheets",
     },
+    spreadsheet_id: {
+      type: "string",
+      label: "Spreadsheet ID",
+      description: "The Google Sheets spreadsheet ID",
+    },
     sheet_name: {
       type: "string",
       label: "Sheet Name",
       description: "The name of the sheet to monitor (e.g., 'Sheet1')",
     },
   },

This will align the source with other components and make the requests valid.

Also applies to: 26-37, 56-63, 120-125

🤖 Prompt for AI Agents
In components/google_sheets/sources/new-updates/new-updates.mjs around lines
11-23 (also referenced at lines 26-37, 56-63, 120-125), the component is missing
a props entry for spreadsheet_id so this.spreadsheet_id is undefined at runtime;
add an explicit spreadsheet_id prop (type: "string", label: "Spreadsheet ID",
description similar to other sources) alongside sheet_name and google_sheets so
all methods that destructure or reference this.spreadsheet_id receive a valid
value and API calls target the correct spreadsheet.

Comment on lines +46 to +55
formatSheetData(sheet) {
const { properties } = sheet;
return {
sheet_id: properties.sheetId,
title: properties.title,
index: properties.index,
sheet_type: properties.sheetType || "GRID",
grid_properties: properties.gridProperties,
created_at: new Date().toISOString(),
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

First run semantics and created_at field may mislead consumers

This polling source emits events for all existing worksheets on the first run:

  • storedSheetIds starts empty, so every sheet is treated as “new”.
  • formatSheetData sets created_at to new Date().toISOString(), and run adds a separate timestamp field also set to “now”.

In a polling context, these timestamps represent “detected at” rather than the true worksheet creation time, but the field name created_at and the summary “New worksheet created” may suggest otherwise.

If backwards compatibility with the previous instant source is important, consider:

  • Seeding storedSheetIds on first run without emitting, or
  • Clearly documenting that the first run produces synthetic “new worksheet” events for pre-existing sheets, and that created_at / timestamp reflect detection time.

You might also want to rename created_at to something like detected_at to reduce confusion for downstream consumers.

Also applies to: 76-109

🤖 Prompt for AI Agents
In components/google_sheets/sources/new-worksheet/new-worksheet.mjs around lines
46-55 (and similarly 76-109), the code sets created_at to the current time and
emits every existing sheet on first run which can mislead consumers into
thinking these are true creation timestamps; either (A) change the field name
from created_at to detected_at (and update any “New worksheet created” summary
to “New worksheet detected”) so timestamps represent detection time, or (B)
implement first-run seeding of storedSheetIds (populate storedSheetIds from the
API without emitting events) so only genuinely new sheets are emitted; pick one
approach, update all references (timestamp fields, summaries/messages, and
tests/docs) consistently, and add a comment noting the chosen semantics.

Copy link
Collaborator

@jcortes jcortes left a comment

Choose a reason for hiding this comment

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

Hi @PrajwalLokhande2003 Thanks for this great contribution. I've just reviwed your PR it is looking good in general however there are some changes I need you to do before QA process. So in general I would like to know if you tested all these new components you have implemented and when it comes to sources please don't change the source strategy like from Instant meaning Webhook to Polling. If there is no polling equivalent you can create a new source with that strategy instead.

Comment on lines +159 to +204
this.formattingType === "GRADIENT_RULE" ?
rule.gradientRule = {
minpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MIN",
},
midpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MID",
},
maxpoint: {
colorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
type: this.interpolationPointType,
value: "MAX",
},
} :
rule.booleanRule = {
condition: {
type: this.conditionType,
values: this.conditionValues?.map((v) => ({
userEnteredValue: v,
})) || [],
},
format: {
backgroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
textFormat: {
...this.textFormat,
foregroundColorStyle: {
rgbColor: parseRgbColor(this.rgbColor),
},
bold: this.bold,
italic: this.italic,
strikethrough: this.strikethrough,
},
},
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you test this?

Comment on lines +47 to +75
validationType: {
type: "string",
label: "Validation Type",
description: "The type of data validation",
options: [
"NUMBER_GREATER",
"NUMBER_GREATER_THAN_EQ",
"NUMBER_LESS_THAN_EQ",
"NUMBER_LESS",
"TEXT_CONTAINS",
"TEXT_NOT_CONTAINS",
"DATE_EQUAL_TO",
"ONE_OF_LIST",
"DATE_AFTER",
"DATE_ON_OR_AFTER",
"DATE_BEFORE",
"DATE_ON_OR_BEFORE",
"DATE_BETWEEN",
"TEXT_STARTS_WITH",
"TEXT_ENDS_WITH",
"TEXT_EQUAL_TO",
"TEXT_NOT_EQUAL_TO",
"CUSTOM_FORMULA",
"NUMBER_EQUAL_TO",
"NUMBER_NOT_EQUAL_TO",
"NUMBER_BETWEEN",
"NUMBER_NOT_BETWEEN",
],
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you test this?

@@ -1,16 +1,30 @@
import httpBase from "../common/http-based/sheet.mjs";
import app from "../../google_sheets.app.mjs";
Copy link
Collaborator

Choose a reason for hiding this comment

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

My recommendation here is to leave all the webhook sources as they are and if you want to give support to polling, please create a new one. for example there is one named new-row-added which it is webhook based and its equivalent is new-row-added-polling so if you find any of the polling sources are failing you can fix them instead

key: "google_sheets-new-updates",
type: "source",
name: "New Updates (Instant)",
name: "New Updates (Polling)",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please don't do this, the source was meant to be as a webhook, if there is no equivalent polling source you can create a new one and name it google_sheets-new-updates-polling instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

User submitted Submitted by a user

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ACTION] Google Sheets - Provide polling options as an alternative to current webhook based ones

5 participants