Skip to content

Conversation

@GTFalcao
Copy link
Collaborator

@GTFalcao GTFalcao commented Aug 21, 2025

Closes #18117

This was created specifically for the email use case, as the action becomes overly complex when dealing with all engagement types

Summary by CodeRabbit

  • New Features

    • Added a HubSpot action to fetch emails associated with a contact, company, or deal.
    • Lets you request additional email fields and set a result limit (default 20; range 1–100).
    • Returns emails sorted by most recent and shows clear success or "no emails" summaries.
    • Includes a default set of common email fields (timestamp, subject, body, direction, status, attachments, headers).
  • Chores

    • Bumped HubSpot component version to 1.6.0.

@vercel
Copy link

vercel bot commented Aug 21, 2025

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

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
pipedream-docs Ignored Ignored Aug 21, 2025 11:31pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Aug 21, 2025 11:31pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 21, 2025

Walkthrough

Adds a new HubSpot action to fetch emails associated with a given CRM object, introduces default email property constants, and bumps the HubSpot package version.

Changes

Cohort / File(s) Summary
New action: Get Associated Emails
components/hubspot/actions/get-associated-emails/get-associated-emails.mjs
Adds an action that retrieves emails associated with a specified objectType and objectId; supports additionalProperties and limit; fetches associations, batch-gets email objects, sorts by hs_timestamp desc, exports a summary, and returns the emails.
Constants for email properties
components/hubspot/common/constants.mjs
Adds DEFAULT_EMAIL_PROPERTIES array export containing core HubSpot email fields (e.g., hs_timestamp, hs_email_subject, hs_email_text, etc.).
Package version bump
components/hubspot/package.json
Increments @pipedream/hubspot package version from 1.5.0 to 1.6.0.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant A as Get Associated Emails Action
  participant HS as HubSpot API

  U->>A: Provide objectType, objectId, additionalProperties, limit
  A->>A: Compose properties = DEFAULT_EMAIL_PROPERTIES + additionalProperties
  A->>HS: getAssociations(objectType, objectId -> toObjectType="emails", limit)
  alt No associations
    A-->>U: summary: "No emails found with this association", return []
  else Associations found
    A->>HS: batchGetObjects(objectType="emails", inputs(ids), properties)
    HS-->>A: email objects
    A->>A: Sort emails by hs_timestamp desc
    A-->>U: summary: "Successfully retrieved N email(s)", return emails
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Implement "Get Associated Engagements" action with associated object props and engagementType prop (#18117) Implemented an emails action; no engagementType prop and no engagements-specific logic.
Use HubSpot engagements endpoint per provided docs (#18117) Changes use email associations and batch email retrieval, not the engagements API.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Add "Get Associated Emails" action (components/hubspot/actions/get-associated-emails/get-associated-emails.mjs) The linked issue requested an engagements action; this implements emails instead.
Add DEFAULT_EMAIL_PROPERTIES constant (components/hubspot/common/constants.mjs) Introduces email-specific properties unrelated to implementing engagements.
Bump package version to 1.6.0 (components/hubspot/package.json) Version bump applies broadly and does not implement the requested engagements functionality.

Poem

I hop through code with eager paws,
Fetching emails and sorting laws.
Timestamps sparkle, results in view—
Engagements wait; I’ll build them too. 🐇✉️

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e4ae1c6 and b956907.

📒 Files selected for processing (1)
  • components/hubspot/actions/get-associated-emails/get-associated-emails.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/hubspot/actions/get-associated-emails/get-associated-emails.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Lint Code Base
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 18117-hubspot-new-action

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 2

🧹 Nitpick comments (9)
components/hubspot/common/constants.mjs (1)

175-184: Default email property set may be heavy and include PII; consider slimming the defaults

hs_email_html and hs_email_headers can be large and may include PII. Since the action already supports additionalProperties, consider a leaner default set to reduce payload and accidental exposure, leaving heavy fields opt-in.

Apply this diff if you want a lighter default:

 const DEFAULT_EMAIL_PROPERTIES = [
   "hs_timestamp",
   "hs_email_direction",
-  "hs_email_html",
   "hs_email_status",
   "hs_email_subject",
   "hs_email_text",
   "hs_attachment_ids",
-  "hs_email_headers",
 ];
components/hubspot/actions/get-associated-emails/get-associated-emails.mjs (8)

4-10: Scope aligns with “emails” only; linked issue requests a generic engagements action

This action fulfills the email use case, but Issue #18117 asked for a generic “Get Associated Engagements” with an engagementType prop. Consider a follow-up generic action (or a shared internal helper) that this action can reuse, to fully close the issue and prevent duplication across email/meetings/calls/etc.

Would you like me to propose a small internal helper (e.g., getAssociatedEngagements) and a generic action scaffold?


7-7: Description/link accuracy

The description references the generic “search” docs, while this action uses associations + batch read. Clarify wording and mention custom objects since includeCustom: true is enabled.

Apply this diff to tighten the copy:

-  description: "Retrieves emails associated with a specific object (contact, company, or deal). [See the documentation](https://developers.hubspot.com/docs/reference/api/crm/search)",
+  description: "Retrieves emails associated with a HubSpot object (contact, company, deal, or custom object). See HubSpot docs on associations and CRM objects.",

20-22: Prop description: call out custom objects explicitly

Minor copy improvement to match includeCustom: true.

-      description: "The type of the object the emails are associated with",
+      description: "Type of the associated object (contact, company, deal, or custom object)",

23-34: Avoid mixing type with propDefinition for the same prop

In Pipedream components, propDefinition usually sets the type. The explicit type: "string" can be redundant or conflict with the definition. Safer to rely solely on propDefinition.

     objectId: {
-      type: "string",
       label: "Object ID",
       description: "The ID of the object to get associated emails for",
       propDefinition: [
         hubspot,
         "objectIds",
         ({ objectType }) => ({
           objectType,
         }),
       ],
     },

52-55: Deduplicate properties to avoid repeated fields

If users pass properties already in the defaults, we’ll send duplicates unnecessarily. Use a Set.

-    const properties = [
-      ...DEFAULT_EMAIL_PROPERTIES,
-      ...(this.additionalProperties || []),
-    ];
+    const properties = [...new Set([
+      ...DEFAULT_EMAIL_PROPERTIES,
+      ...(this.additionalProperties || []),
+    ])];

71-74: Clarify empty-results check

if (!results?.length > 0) is truthy for empty arrays, but relies on tricky operator precedence. Prefer the clearer if (!results?.length).

-    if (!results?.length > 0) {
+    if (!results?.length) {
       $.export("$summary", "No emails found with this association");
       return [];
     }

76-79: Deduplicate associated IDs before batch fetching

Guard against duplicate associations returning the same email ID.

-    const emailIds = results.map((association) => ({
-      id: association.toObjectId,
-    }));
+    const uniqueIds = [...new Set(results.map((a) => a.toObjectId))];
+    const emailIds = uniqueIds.map((id) => ({ id }));

90-95: Sorting by hs_timestamp is fine; consider a stable tie-breaker

Optional: For equal timestamps or missing values, tie-break by id to keep results deterministic across runs.

Example:

-    const sortedEmails = emails?.sort((a, b) => {
+    const sortedEmails = emails?.sort((a, b) => {
       const timestampA = new Date(a.properties?.hs_timestamp || 0).getTime();
       const timestampB = new Date(b.properties?.hs_timestamp || 0).getTime();
-      return timestampB - timestampA;
+      if (timestampB !== timestampA) return timestampB - timestampA;
+      return String(b.id ?? "").localeCompare(String(a.id ?? ""));
     }) || [];
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8427b38 and b41f4e2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • components/hubspot/actions/get-associated-emails/get-associated-emails.mjs (1 hunks)
  • components/hubspot/common/constants.mjs (2 hunks)
  • components/hubspot/package.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
components/hubspot/actions/get-associated-emails/get-associated-emails.mjs (1)
components/hubspot/common/constants.mjs (1)
  • DEFAULT_EMAIL_PROPERTIES (175-184)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Lint Code Base
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
🔇 Additional comments (4)
components/hubspot/package.json (1)

3-3: Minor version bump aligns with a new action — LGTM

Adding a new action warrants a minor bump. No other changes here.

components/hubspot/common/constants.mjs (1)

239-241: Exporting DEFAULT_EMAIL_PROPERTIES is consistent and useful

Making the default email properties available to other actions/utilities looks good.

components/hubspot/actions/get-associated-emails/get-associated-emails.mjs (2)

61-69: Associations fetch looks correct

Using toObjectType: "emails" with a limit is consistent with the flow of first collecting associated IDs.

Also verify that the association result shape contains toObjectId in your helper’s return (some APIs return toObjectId vs. nested structures). The script above will help find the helper implementation.


96-101: Nice: succinct summary and return shape

Exporting a concise summary and returning the sorted array matches Pipedream action UX expectations.

Copy link
Collaborator

@michelle0927 michelle0927 left a comment

Choose a reason for hiding this comment

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

LGTM!

@vunguyenhung vunguyenhung merged commit e56c1e0 into master Aug 25, 2025
9 of 10 checks passed
@vunguyenhung vunguyenhung deleted the 18117-hubspot-new-action branch August 25, 2025 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ACTION] HubSpot Get Associated Engagements

4 participants