Skip to content

Complete Freshservice integration to match Freshdesk functionality #17608

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

seynadio
Copy link

@seynadio seynadio commented Jul 14, 2025

Summary

Complete overhaul of Freshservice integration to achieve full parity with Freshdesk, adding 11 new actions, enhanced app structure, internal notes support, and improved sources.

New Actions (11 total)

  • create-ticket: Full ticket creation with all fields, attachments, custom fields
  • update-ticket: Update any ticket field + internal notes support
  • get-ticket: Retrieve individual ticket details
  • list-all-tickets: List tickets with filtering, sorting, pagination
  • create-contact: Create requesters with company association
  • create-company: Create companies with full field support
  • assign-ticket-to-agent: Assign tickets to specific agents
  • assign-ticket-to-group: Assign tickets to groups
  • close-ticket: Close tickets with resolution details
  • set-ticket-priority: Update ticket priority with validation
  • set-ticket-status: Update ticket status with validation

Enhanced Infrastructure

  • freshservice.app.mjs: Complete rewrite with all prop definitions and API methods
  • constants.mjs: Status/priority mappings and sort options
  • utils.mjs: Shared utilities for data handling
  • new-ticket source: Enhanced with proper date filtering and pagination
  • new-contact source: Complete implementation for contact monitoring
  • package.json: Updated with required dependencies (moment, async-retry)

Internal Notes Support

  • Integrated in update-ticket action using private: true
  • Uses Freshservice Notes API (/v2/tickets/{id}/notes)
  • Proper validation and error handling
  • Matches Freshdesk internal notes functionality

Test plan

  • Test all 11 actions with various scenarios
  • Test internal notes creation and privacy
  • Test prop definitions and dynamic options loading
  • Test enhanced sources with date filtering
  • Validate API endpoints and data structures
  • Remove accidental Freshdesk changes from original PR

API Coverage

Full Freshservice v2 API integration:

  • /v2/tickets (CRUD operations)
  • /v2/tickets/{id}/notes (Internal notes)
  • /v2/requesters (Contacts/Users)
  • /v2/companies (Organizations)
  • /v2/agents (Support staff)
  • /v2/groups (Team assignments)

Now has complete feature parity with Freshdesk integration!

Summary by CodeRabbit

  • New Features

    • Added actions for Freshservice: assign tickets to agents or groups, close tickets, create companies, contacts, and tickets, update tickets (including adding internal notes), set ticket status and priority, and retrieve ticket details.
    • Introduced actions to list all tickets with customizable sorting and limits.
    • Added sources to emit events for new contacts and new tickets in Freshservice.
  • Enhancements

    • Expanded Freshservice integration with comprehensive property options and API methods for managing companies, contacts, agents, groups, tickets, and notes.
    • Improved event sources with more robust pagination and deduplication.
  • Chores

    • Updated dependencies and package version for improved compatibility and features.

- Add comprehensive app with all prop definitions and API methods
- Add constants and utilities for consistent data handling
- Add all 11 actions matching Freshdesk:
  * create-ticket, update-ticket (with internal notes support)
  * get-ticket, list-all-tickets
  * create-contact, create-company
  * assign-ticket-to-agent, assign-ticket-to-group
  * close-ticket, set-ticket-priority, set-ticket-status
- Add internal notes support in update-ticket action
- Enhance new-ticket source with proper date filtering and pagination
- Add new-contact source with complete implementation
- Update package.json with required dependencies (moment, async-retry)
- Full parity with Freshdesk integration functionality
@adolfo-pd adolfo-pd added the User submitted Submitted by a user label Jul 14, 2025
@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:

Copy link

vercel bot commented Jul 14, 2025

@seynadio is attempting to deploy a commit to the Pipedreamers Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

vercel bot commented Jul 14, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
pipedream-docs-redirect-do-not-edit ⬜️ Ignored (Inspect) Jul 14, 2025 11:47am

Copy link
Contributor

coderabbitai bot commented Jul 14, 2025

Walkthrough

This update introduces a comprehensive Freshservice integration, adding multiple action modules for ticket, contact, and company management, as well as event sources for new tickets and contacts. It includes utility and constant modules, expands the Freshservice app with prop definitions and API methods, and updates dependencies in the package configuration.

Changes

Files/Groups Change Summary
actions/assign-ticket-to-agent.mjs, assign-ticket-to-group.mjs, close-ticket.mjs, create-company.mjs, create-contact.mjs, create-ticket.mjs, get-ticket.mjs, list-all-tickets.mjs, set-ticket-priority.mjs, set-ticket-status.mjs, update-ticket.mjs Added new Freshservice action modules for assigning tickets, closing tickets, creating companies/contacts/tickets, updating tickets, setting status/priority, and fetching tickets.
common/constants.mjs Introduced constants for ticket statuses, priorities, sorting, and pagination.
common/utils.mjs Added a utility function to recursively remove null/empty entries from objects and arrays.
freshservice.app.mjs Expanded with prop definitions and comprehensive API methods for Freshservice entities (companies, contacts, tickets, agents, groups, notes).
package.json Updated version to 0.1.0; upgraded "@pipedream/platform" and added "async-retry" and "moment" dependencies.
sources/new-contact.mjs Added a polling source to emit events for new Freshservice contacts, maintaining state for deduplication.
sources/new-ticket.mjs Refactored the polling source for new tickets to use paginated ticket retrieval and improved deduplication logic.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ActionModule
    participant FreshserviceApp
    participant FreshserviceAPI

    User->>ActionModule: Provide input (e.g., ticketId, agentId)
    ActionModule->>FreshserviceApp: Call API method (e.g., updateTicket)
    FreshserviceApp->>FreshserviceAPI: Make HTTP request
    FreshserviceAPI-->>FreshserviceApp: Return response
    FreshserviceApp-->>ActionModule: Return processed data
    ActionModule-->>User: Output summary and response
Loading
sequenceDiagram
    participant Source
    participant FreshserviceApp
    participant FreshserviceAPI
    participant EventStream

    Source->>FreshserviceApp: Fetch last checked timestamp
    loop Polling interval
        Source->>FreshserviceApp: Request new entities (contacts/tickets) since last check
        FreshserviceApp->>FreshserviceAPI: Paginated API requests
        FreshserviceAPI-->>FreshserviceApp: Return entities
        FreshserviceApp-->>Source: Pass entities
        Source->>EventStream: Emit events for each new entity
        Source->>FreshserviceApp: Update last checked timestamp
    end
Loading

Possibly related PRs

  • PipedreamHQ/pipedream#16450: Adds an "Assign Ticket to Agent" action module similar to the one introduced here, updating a ticket's responder via the API.

Suggested reviewers

  • michelle0927

Poem

In fields of code where tickets grow,
Rabbits hop to Freshservice, to and fro.
Actions bloom—create, assign, and close,
Contacts and companies in neat little rows.
With constants and utils, the garden expands,
Now tickets and contacts are in gentle hands!
🐇✨

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

components/freshservice/actions/assign-ticket-to-agent/assign-ticket-to-agent.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)

components/freshservice/actions/close-ticket/close-ticket.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)

components/freshservice/actions/create-company/create-company.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:255:9)
at packageResolve (node:internal/modules/esm/resolve:767:81)
at moduleResolve (node:internal/modules/esm/resolve:853:18)
at defaultResolve (node:internal/modules/esm/resolve:983:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:801:12)
at #cachedDefaultResolve (node:internal/modules/esm/loader:725:25)
at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38)
at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:309:38)
at #link (node:internal/modules/esm/module_job:202:49)

  • 13 others
✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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: 5

🔭 Outside diff range comments (1)
components/freshservice/freshservice.app.mjs (1)

286-291: Remove duplicate method getTickets.

The getTickets method is a duplicate of the listTickets method defined at lines 245-250. Both methods make the same API call to /v2/tickets.

-    async getTickets(args = {}) {
-      return this._makeRequest({
-        path: "/v2/tickets",
-        ...args,
-      });
-    },
🧹 Nitpick comments (10)
components/freshservice/common/utils.mjs (2)

1-25: Consider refining the empty string filtering logic.

The function filters out empty strings (item !== "" and obj[key] !== ""), which might be too aggressive. Empty strings could be valid values for certain API fields. Consider making this behavior configurable or more selective.

-function removeNullEntries(obj) {
+function removeNullEntries(obj, filterEmptyStrings = true) {

Then update the filtering conditions to use the parameter:

-  return obj.filter((item) => item !== null && item !== undefined && item !== "")
+  return obj.filter((item) => item !== null && item !== undefined && (!filterEmptyStrings || item !== ""))

And similarly for the object property check.


1-25: Function handles data types correctly but lacks edge case protection.

The recursive implementation correctly handles different data types. However, consider adding protection against circular references and potentially very deep nesting to prevent stack overflow errors.

-function removeNullEntries(obj) {
+function removeNullEntries(obj, seen = new WeakSet()) {
+  if (typeof obj === "object" && obj !== null) {
+    if (seen.has(obj)) {
+      return obj; // Circular reference detected
+    }
+    seen.add(obj);
+  }
components/freshservice/actions/set-ticket-priority/set-ticket-priority.mjs (1)

25-38: Consider adding error handling for the getTicketName call.

The action calls getTicketName after updating the ticket, but doesn't handle potential failures. If this call fails, the summary message won't be generated properly.

-    const ticketName = await this.freshservice.getTicketName(this.ticketId);
-    const priorityLabel = TICKET_PRIORITY[this.priority];
-    $.export("$summary", `Successfully set priority of ticket "${ticketName}" to ${priorityLabel}`);
+    try {
+      const ticketName = await this.freshservice.getTicketName(this.ticketId);
+      const priorityLabel = TICKET_PRIORITY[this.priority];
+      $.export("$summary", `Successfully set priority of ticket "${ticketName}" to ${priorityLabel}`);
+    } catch (error) {
+      const priorityLabel = TICKET_PRIORITY[this.priority];
+      $.export("$summary", `Successfully set priority of ticket ${this.ticketId} to ${priorityLabel}`);
+    }
components/freshservice/actions/close-ticket/close-ticket.mjs (1)

27-28: Consider adding error handling for the getTicketName call.

Similar to the set-ticket-priority action, this action should handle potential failures when retrieving the ticket name for the summary message.

-    const ticketName = await this.freshservice.getTicketName(this.ticketId);
-    $.export("$summary", `Successfully closed ticket "${ticketName}"`);
+    try {
+      const ticketName = await this.freshservice.getTicketName(this.ticketId);
+      $.export("$summary", `Successfully closed ticket "${ticketName}"`);
+    } catch (error) {
+      $.export("$summary", `Successfully closed ticket ${this.ticketId}`);
+    }
components/freshservice/actions/set-ticket-status/set-ticket-status.mjs (1)

34-36: Consider adding error handling for the getTicketName call.

Consistent with the other actions, this should handle potential failures when retrieving the ticket name for the summary message.

-    const ticketName = await this.freshservice.getTicketName(this.ticketId);
-    const statusLabel = TICKET_STATUS[this.status];
-    $.export("$summary", `Successfully set status of ticket "${ticketName}" to ${statusLabel}`);
+    try {
+      const ticketName = await this.freshservice.getTicketName(this.ticketId);
+      const statusLabel = TICKET_STATUS[this.status];
+      $.export("$summary", `Successfully set status of ticket "${ticketName}" to ${statusLabel}`);
+    } catch (error) {
+      const statusLabel = TICKET_STATUS[this.status];
+      $.export("$summary", `Successfully set status of ticket ${this.ticketId} to ${statusLabel}`);
+    }
+```

</blockquote></details>
<details>
<summary>components/freshservice/actions/assign-ticket-to-group/assign-ticket-to-group.mjs (2)</summary><blockquote>

`17-22`: **Consider maintaining consistent naming between prop name and propDefinition.**

The prop is named `group_id` (with underscore) but references the `groupId` propDefinition (camelCase). For consistency with the propDefinition naming convention, consider renaming the prop.

```diff
-    group_id: {
+    groupId: {
      propDefinition: [
        freshservice,
        "groupId",
      ],
    },

Then update the usage in the run method:

      data: {
-        group_id: this.group_id,
+        group_id: this.groupId,
      },

33-34: Optimize API calls and enhance the summary message.

The code makes an additional API call to get the ticket name, which may be unnecessary if the update response includes ticket details. Additionally, the summary message could be more informative by including the group name.

-    const ticketName = await this.freshservice.getTicketName(this.ticketId);
-    $.export("$summary", `Successfully assigned ticket "${ticketName}" to group`);
+    const ticketName = response.ticket?.subject || await this.freshservice.getTicketName(this.ticketId);
+    $.export("$summary", `Successfully assigned ticket "${ticketName}" to group ID ${this.group_id}`);
components/freshservice/actions/update-ticket/update-ticket.mjs (1)

97-110: Consider separating internal note creation into a dedicated action.

While the implementation is correct, combining ticket updates and internal note creation in a single action with conditional logic may confuse users. Consider creating a separate add-internal-note action for better clarity and single responsibility.

This would:

  • Simplify the action's purpose and documentation
  • Make the UI clearer for users
  • Follow the single responsibility principle
  • Allow for more focused prop definitions for each use case

Also applies to: 121-137

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

4-54: Consider refactoring to eliminate duplication between status and priority definitions.

The TICKET_STATUS/TICKET_PRIORITY objects and STATUS_OPTIONS/PRIORITY_OPTIONS arrays contain duplicate information. This could lead to maintenance issues if values need to be updated.

Consider deriving one from the other:

export const TICKET_STATUS = {
};

export const TICKET_PRIORITY = {
};

-export const STATUS_OPTIONS = [
-  {
-    label: "Open",
-    value: 2,
-  },
-  {
-    label: "Pending", 
-    value: 3,
-  },
-  {
-    label: "Resolved",
-    value: 4,
-  },
-  {
-    label: "Closed",
-    value: 5,
-  },
-];
+export const STATUS_OPTIONS = Object.entries(TICKET_STATUS).map(([value, label]) => ({
+  label,
+  value: parseInt(value),
+}));

-export const PRIORITY_OPTIONS = [
-  {
-    label: "Low",
-    value: 1,
-  },
-  {
-    label: "Medium",
-    value: 2,
-  },
-  {
-    label: "High", 
-    value: 3,
-  },
-  {
-    label: "Urgent",
-    value: 4,
-  },
-];
+export const PRIORITY_OPTIONS = Object.entries(TICKET_PRIORITY).map(([value, label]) => ({
+  label,
+  value: parseInt(value),
+}));
components/freshservice/freshservice.app.mjs (1)

172-174: Consider using a more recent default date.

The hardcoded default date of "2021-01-01T00:00:00Z" is over 4 years old. This could cause performance issues if there's a large amount of historical data to process on the first run.

Consider using a date from the last 30-90 days as the default:

    async getLastDateChecked() {
-      return await this.db.get(DB_LAST_DATE_CHECK) || "2021-01-01T00:00:00Z";
+      const thirtyDaysAgo = new Date();
+      thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
+      return await this.db.get(DB_LAST_DATE_CHECK) || thirtyDaysAgo.toISOString();
    },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e21d334 and 62e645f.

📒 Files selected for processing (17)
  • components/freshservice/actions/assign-ticket-to-agent/assign-ticket-to-agent.mjs (1 hunks)
  • components/freshservice/actions/assign-ticket-to-group/assign-ticket-to-group.mjs (1 hunks)
  • components/freshservice/actions/close-ticket/close-ticket.mjs (1 hunks)
  • components/freshservice/actions/create-company/create-company.mjs (1 hunks)
  • components/freshservice/actions/create-contact/create-contact.mjs (1 hunks)
  • components/freshservice/actions/create-ticket/create-ticket.mjs (1 hunks)
  • components/freshservice/actions/get-ticket/get-ticket.mjs (1 hunks)
  • components/freshservice/actions/list-all-tickets/list-all-tickets.mjs (1 hunks)
  • components/freshservice/actions/set-ticket-priority/set-ticket-priority.mjs (1 hunks)
  • components/freshservice/actions/set-ticket-status/set-ticket-status.mjs (1 hunks)
  • components/freshservice/actions/update-ticket/update-ticket.mjs (1 hunks)
  • components/freshservice/common/constants.mjs (1 hunks)
  • components/freshservice/common/utils.mjs (1 hunks)
  • components/freshservice/freshservice.app.mjs (2 hunks)
  • components/freshservice/package.json (2 hunks)
  • components/freshservice/sources/new-contact/new-contact.mjs (1 hunks)
  • components/freshservice/sources/new-ticket/new-ticket.mjs (2 hunks)
🧰 Additional context used
🧠 Learnings (11)
components/freshservice/package.json (1)
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14935
File: components/sailpoint/package.json:15-18
Timestamp: 2024-12-12T19:23:09.039Z
Learning: When developing Pipedream components, do not add built-in Node.js modules like `fs` to `package.json` dependencies, as they are native modules provided by the Node.js runtime.
components/freshservice/actions/create-company/create-company.mjs (3)
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
components/freshservice/sources/new-contact/new-contact.mjs (3)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15376
File: components/monday/sources/name-updated/name-updated.mjs:6-6
Timestamp: 2025-01-23T03:55:15.166Z
Learning: Source names in Monday.com components don't need to start with "New" if they emit events for updated items (e.g., "Name Updated", "Column Value Updated") rather than new items. This follows the component guidelines exception where the "New" prefix is only required when emits are limited to new items.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common.mjs:97-98
Timestamp: 2024-07-24T02:05:59.531Z
Learning: The `processTimerEvent` method in the `components/salesforce_rest_api/sources/common.mjs` file is intentionally left unimplemented to enforce that subclasses must implement this method, similar to an abstract class in object-oriented programming.
components/freshservice/actions/create-contact/create-contact.mjs (1)
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".
components/freshservice/actions/close-ticket/close-ticket.mjs (2)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
components/freshservice/actions/assign-ticket-to-group/assign-ticket-to-group.mjs (2)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
components/freshservice/actions/update-ticket/update-ticket.mjs (2)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
components/freshservice/actions/create-ticket/create-ticket.mjs (3)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".
components/freshservice/freshservice.app.mjs (1)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.
components/freshservice/actions/list-all-tickets/list-all-tickets.mjs (2)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-07-04T18:11:59.822Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12731
File: components/hackerone/actions/get-members/get-members.mjs:3-28
Timestamp: 2024-10-08T15:33:38.240Z
Learning: When exporting a summary message in the `run` method of an action, ensure the message is correctly formatted. For example, in the `hackerone-get-members` action, the correct format is `Successfully retrieved ${response.data.length} members`.
components/freshservice/sources/new-ticket/new-ticket.mjs (2)
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15376
File: components/monday/sources/name-updated/name-updated.mjs:6-6
Timestamp: 2025-01-23T03:55:15.166Z
Learning: Source names in Monday.com components don't need to start with "New" if they emit events for updated items (e.g., "Name Updated", "Column Value Updated") rather than new items. This follows the component guidelines exception where the "New" prefix is only required when emits are limited to new items.
🔇 Additional comments (15)
components/freshservice/package.json (1)

3-3: Appropriate version bump for the feature additions.

The version bump from 0.0.2 to 0.1.0 is appropriate for the scale of new features being added according to the PR objectives.

components/freshservice/actions/set-ticket-priority/set-ticket-priority.mjs (1)

1-39: Well-structured action following Pipedream conventions.

The action correctly uses prop definitions, follows the standard structure, and implements the priority setting functionality cleanly. Good use of constants for priority labels and proper API method calls.

components/freshservice/actions/set-ticket-status/set-ticket-status.mjs (1)

1-39: Excellent implementation with proper constant usage.

This action demonstrates good practices by properly importing and using the TICKET_STATUS constants. The structure is consistent with other actions and follows Pipedream conventions well.

components/freshservice/actions/create-company/create-company.mjs (1)

1-109: LGTM! Well-structured action implementation.

The action follows Pipedream best practices with proper prop definitions, data validation, and utility function usage. The conditional handling of optional arrays and custom fields is appropriate.

components/freshservice/actions/assign-ticket-to-agent/assign-ticket-to-agent.mjs (1)

1-37: LGTM! Clean and focused ticket assignment implementation.

The action properly uses propDefinition for inputs and follows the standard pattern for ticket updates. The summary message includes the ticket name for better user feedback.

components/freshservice/actions/create-contact/create-contact.mjs (2)

92-94: Excellent validation logic for contact creation.

The validation ensuring either email or phone is provided is essential for contact creation and uses the appropriate ConfigurationError for user feedback.


107-107: Good summary message format.

The summary message properly handles the optional last_name field and follows the learned pattern for successful creation messages.

components/freshservice/sources/new-contact/new-contact.mjs (2)

30-52: Well-implemented pagination generator.

The generator method properly handles pagination with hasMore logic and yields contacts individually, which is efficient for large datasets.


53-74: Robust event emission with proper state management.

The date filtering and state management prevent duplicate events while ensuring new contacts are properly tracked and emitted.

components/freshservice/actions/list-all-tickets/list-all-tickets.mjs (2)

25-32: Good parameter design with reasonable limits.

The limit parameter has appropriate default (30) and maximum (100) values, which prevents API overload while providing flexibility.


51-52: Proper summary message format.

The summary message follows the learned pattern for listing actions by showing the count of retrieved items.

components/freshservice/actions/get-ticket/get-ticket.mjs (1)

1-27: Well-implemented ticket retrieval action.

The action correctly retrieves ticket details with proper error handling using optional chaining and provides a clear summary message.

components/freshservice/sources/new-ticket/new-ticket.mjs (1)

1-84: Approve changes – ISO date format confirmed

The implementation correctly uses:

  • Async generators for paginated retrieval
  • Incremental date-based filtering with created_at
  • Moment.js formatting (.format("YYYY-MM-DDTHH:mm:ss[Z]")) which yields YYYY-MM-DDTHH:MM:SSZ, matching Freshservice API v2 requirements

All concerns addressed; ready to merge.

components/freshservice/actions/update-ticket/update-ticket.mjs (1)

140-161: Well-implemented ticket update logic with proper validation.

The update logic correctly:

  • Removes null entries before sending to API
  • Validates that at least one field is provided
  • Maps status and priority to human-readable labels in the summary
  • Provides comprehensive feedback in the summary message
components/freshservice/actions/create-ticket/create-ticket.mjs (1)

122-141: Clean implementation of ticket creation.

The run method properly:

  • Removes null entries from the data
  • Parses custom fields when provided
  • Provides informative summary with fallback to ticket ID

"@pipedream/platform": "^1.5.1"
"@pipedream/platform": "^3.0.3",
"async-retry": "^1.3.3",
"moment": "2.29.4"
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider upgrading the moment dependency to a more recent version.

The moment.js library at version 2.29.4 is from 2020 and the library has been in maintenance mode. Consider upgrading to a more recent version or evaluating modern alternatives like date-fns or native JavaScript Date methods for better performance and security.


🌐 Web query:

What is the latest version of moment.js and are there any security vulnerabilities in version 2.29.4?

💡 Result:

The latest version of Moment.js as of December 2023 is 2.30.1[4][10]. This is the most up-to-date release and is considered not to have known vulnerabilities according to recent security databases[10].

For Moment.js version 2.29.4:

  • Version 2.29.4 was specifically released to patch a key security vulnerability (CVE-2022-31129), which affected versions from 2.18.0 up to and including 2.29.3. This vulnerability had to do with inefficient regular expression parsing that could be exploited for (Re)DoS attacks (regular expression denial of service) via excessively long user-supplied input[3][4][8].
  • There are no known security vulnerabilities in version 2.29.4, as it contains the patch for CVE-2022-31129. Security advisories and changelogs confirm that updating to 2.29.4 (or any later version) resolves this vulnerability[3][4][8][10].
  • Additional mitigations, such as input length checks, are generally a good practice, but the main ReDoS issue is patched in 2.29.4[3][5][6].

In summary:

  • Latest Moment.js version: 2.30.1[4][10]
  • Vulnerabilities in 2.29.4: None currently known; 2.29.4 was released to patch all prior known vulnerabilities, especially CVE-2022-31129[3][4][8][10].

Citations:


Upgrade Moment.js to the latest patch release

moment 2.29.4 was released to patch CVE-2022-31129 and currently has no known security issues. However, the most recent Moment.js version is 2.30.1, which includes minor fixes and improvements.

• File: components/freshservice/package.json
• Change dependency to 2.30.1 (or evaluate modern alternatives like date-fns/native Date)

Proposed diff:

--- components/freshservice/package.json
+++ components/freshservice/package.json
@@ lines 19
-    "moment": "2.29.4"
+    "moment": "2.30.1"
📝 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
"moment": "2.29.4"
"moment": "2.30.1"
🤖 Prompt for AI Agents
In components/freshservice/package.json at line 19, the Moment.js dependency is
set to version 2.29.4. Update this version to 2.30.1 to include the latest minor
fixes and improvements. Alternatively, consider replacing Moment.js with modern
date libraries like date-fns or using the native Date API if feasible.

@@ -14,6 +14,8 @@
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^1.5.1"
"@pipedream/platform": "^3.0.3",
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify compatibility with the major platform upgrade.

The @pipedream/platform dependency has been upgraded from ^1.5.1 to ^3.0.3, which is a major version jump. Ensure this upgrade doesn't introduce breaking changes that could affect the existing functionality.


🌐 Web query:

What are the breaking changes between @pipedream/platform version 1.5.1 and 3.0.3?

💡 Result:

Pipedream's transition from version 1.5.1 to 3.0.3 introduced several significant changes that may affect existing workflows. Key breaking changes include:

  1. Workflow Builder Overhaul: The workflow builder underwent a major redesign, separating the building and inspecting processes. In version 1, these were combined, but in version 2 (introduced after 1.5.1), they are distinct, requiring users to switch between building and inspecting modes. (pipedream.com)

  2. Node.js Code Step Refactoring: The structure of Node.js code steps changed. Previously, code steps were defined as:

    async (event, steps) {
      // your code here
    }

    In version 2, they are now defined using the defineComponent function:

    defineComponent({
      async run({ steps, $ }) {
        // your code here
      },
    });

    This change affects how variables like event and $ are accessed. (pipedream.com)

  3. Introduction of Props: The concept of params was replaced with props for passing inputs to steps. This change impacts how data is passed and accessed within workflows. (pipedream.com)

  4. Removal of $checkpoint: The $checkpoint functionality, used to save data between workflow runs, was removed and replaced by Data Stores. (pipedream.com)

  5. Component API Changes: The Component API was updated, affecting how components are defined and interact within workflows. (pipedream.com)

For a comprehensive list of breaking changes and migration guidance, refer to Pipedream's official migration guide. (pipedream.com)

Citations:


Ensure compatibility with @pipedream/platform v3.0.3

The jump from v1.5.1 to v3.0.3 contains multiple breaking changes. Verify and update your code in components/freshservice to address:

  • Node.js code steps
    – Replace
    async (event, steps) {  }
    with
    defineComponent({
      async run({ steps, $ }) {  },
    });
  • Input handling
    – Change all uses of params to props
  • State persistence
    – Remove $checkpoint and migrate to Data Stores
  • Component definitions
    – Update against the new Component API
  • Workflow Builder changes
    – Test in both build and inspect modes per the redesigned UI

For full details and migration examples, see Pipedream’s guide:
https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai

🤖 Prompt for AI Agents
In components/freshservice/package.json at line 17, the dependency on
@pipedream/platform is updated to v3.0.3, which introduces breaking changes. To
fix this, refactor all Node.js code steps to use the new defineComponent syntax
with an async run method receiving { steps, $ } instead of the old async (event,
steps) signature. Replace all instances of params with props for input handling.
Remove any usage of $checkpoint and migrate state persistence to Data Stores.
Update component definitions to comply with the new Component API and thoroughly
test workflows in both build and inspect modes to ensure compatibility with the
redesigned UI.

const response = await this.freshservice.updateTicket({
ticketId: this.ticketId,
data: {
status: 5, // Closed
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use constants instead of hardcoded status values.

The status value 5 for "Closed" is hardcoded. Consider importing and using the TICKET_STATUS constants from the constants file for better maintainability.

+import { TICKET_STATUS } from "../../common/constants.mjs";

Then update the status assignment:

-        status: 5, // Closed
+        status: Object.keys(TICKET_STATUS).find(key => TICKET_STATUS[key] === "Closed") || 5,

Or if the constants file exports the actual status values:

-        status: 5, // Closed
+        status: TICKET_STATUS.CLOSED,

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In components/freshservice/actions/close-ticket/close-ticket.mjs at line 22,
replace the hardcoded status value 5 with the corresponding constant from the
TICKET_STATUS constants file. Import TICKET_STATUS at the top of the file if not
already imported, then assign status using TICKET_STATUS.Closed or the
appropriate constant name to improve maintainability and clarity.

Comment on lines +60 to +114
type: {
type: "string",
label: "Type",
description: "Type of the ticket",
options: [
"Incident",
"Service Request",
"Change",
"Problem",
"Release",
],
optional: true,
},
source: {
type: "string",
label: "Source",
description: "Source of the ticket",
options: [
"Email",
"Portal",
"Phone",
"Chat",
"Feedback Widget",
"Yammer",
"AWS Cloudwatch",
"Pagerduty",
"Walkup",
"Slack",
],
optional: true,
},
urgency: {
type: "string",
label: "Urgency",
description: "Urgency of the ticket",
options: [
"Low",
"Medium",
"High",
"Critical",
],
optional: true,
},
impact: {
type: "string",
label: "Impact",
description: "Impact of the ticket",
options: [
"Low",
"Medium",
"High",
"Critical",
],
optional: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify hardcoded options match current Freshservice API values.

The action hardcodes options for ticket type, source, urgency, and impact. These should be verified against the current Freshservice API to ensure they're complete and accurate.

Consider moving these options to the constants file for better maintainability:


🏁 Script executed:

#!/bin/bash
# Description: Search for other occurrences of these ticket type values to check consistency

# Search for ticket type values
echo "Searching for ticket type definitions..."
rg -A 2 "Incident|Service Request|Change|Problem|Release" --type js

# Search for source type definitions  
echo "Searching for source type definitions..."
rg -A 2 "Email|Portal|Phone|Chat|Feedback Widget" --type js

Length of output: 4291


🌐 Web query:

What are the valid ticket types, sources, urgency levels, and impact levels in Freshservice API v2?

💡 Result:

Based on Freshservice API v2 documentation and solution articles, here are the valid ticket types, sources, urgency levels, and impact levels:


Ticket Types

  • Case (prefix: CASE)
  • Query (prefix: QUERY)
  • Issue (prefix: ISSUE)
  • Request (prefix: REQ)

These types are available for business teams to categorize tickets, and all types function similarly with different prefixes for ticket IDs[9].


Ticket Sources
Below are the valid ticket source values and their corresponding numbers[1]:

Source Name Value
Email 1
Portal 2
Phone 3
Chat 4
Feedback widget 5
Yammer 6
AWS Cloudwatch 7
Pagerduty 8
Walkup 9
Slack 10

Urgency and Impact Levels
Freshservice allows organizations to set custom urgency and impact options, but the most common and default values are typically:

  • Low
  • Medium
  • High
  • Urgent

These values are used in the Priority Matrix to automatically determine a ticket’s priority based on the combination of urgency and impact selected[2][6]. The actual values or labels can be configured in your Freshservice admin settings, but these four levels are standard defaults[2][6]. You can confirm the exact values available in your system via the Field Manager under Ticket Fields in the admin menu[2][6].


Summary Table

Property Values (Default/Typical) Notes
Ticket Type Case, Query, Issue, Request Prefixes CASE, QUERY, ISSUE, REQ
Source Email (1), Portal (2), Phone (3), Chat (4), Feedback widget (5), Yammer (6), AWS Cloudwatch (7), Pagerduty (8), Walkup (9), Slack (10) Use integer values in API
Urgency Low, Medium, High, Urgent Can be customized per organization
Impact Low, Medium, High, Urgent Can be customized per organization

For the exact list of urgency and impact values available in your Freshservice instance, use the GET /api/v2/ticket_fields endpoint[10]. This will return all possible values configured for your account.


Further Notes

  • Urgency and Impact are typically used together in a Priority Matrix to control ticket priority automatically[2][6].
  • All ticket types can be related as parent or child tickets to each other[9].

Citations:


Update hardcoded Freshservice ticket options to match API v2

The hardcoded values in components/freshservice/actions/create-ticket/create-ticket.mjs (lines 60–114) don’t align with Freshservice API v2 defaults:

• Ticket Types
– Current: Incident, Service Request, Change, Problem, Release
– API v2: Case, Query, Issue, Request

• Urgency & Impact
– Current: Low, Medium, High, Critical
– API v2 defaults: Low, Medium, High, Urgent

• Sources
– Matches API defaults (Email, Portal, Phone, Chat, Feedback widget, Yammer, AWS Cloudwatch, PagerDuty, Walkup, Slack)

Recommended fixes:

  • Replace type.options with ["Case","Query","Issue","Request"]
  • Change the highest value in urgency.options and impact.options from "Critical" to "Urgent"
  • Move all four option-arrays into a shared constants file (e.g. components/freshservice/constants.js) or fetch them dynamically via GET /api/v2/ticket_fields.

Example snippet:

--- create-ticket.mjs
+++ create-ticket.mjs
@@ type: {
-  options: [
-    "Incident","Service Request","Change","Problem","Release",
-  ],
+  options: ["Case","Query","Issue","Request"],
@@ urgency: {
-  options: ["Low","Medium","High","Critical"],
+  options: ["Low","Medium","High","Urgent"],
@@ impact: {
-  options: ["Low","Medium","High","Critical"],
+  options: ["Low","Medium","High","Urgent"],
🤖 Prompt for AI Agents
In components/freshservice/actions/create-ticket/create-ticket.mjs between lines
60 and 114, update the hardcoded ticket option arrays to align with Freshservice
API v2 defaults. Replace the type.options array with
["Case","Query","Issue","Request"], and change the highest values in
urgency.options and impact.options from "Critical" to "Urgent". Additionally,
move all four option arrays (type, source, urgency, impact) into a shared
constants file like components/freshservice/constants.js or implement dynamic
fetching from GET /api/v2/ticket_fields to avoid hardcoding these values.

Comment on lines +103 to +110
const contacts = await this.getContacts({
params: {
page: page + 1,
per_page: PAGE_SIZE,
company_id: companyId,
},
});
return contacts?.map((contact) => ({
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the API response structure for contacts.

The contactEmail propDefinition uses the contacts response directly without destructuring, while other similar methods destructure the response (e.g., { companies }, { tickets }). This inconsistency suggests the response structure might be different or there's an error.


🏁 Script executed:

#!/bin/bash
# Check how the getContacts response is used elsewhere in the codebase
rg -A 5 "getContacts\(" components/freshservice/

Length of output: 2021


🌐 Web query:

What is the response structure of the Freshservice API v2 /requesters endpoint?

💡 Result:

The Freshservice API v2 /requesters endpoint returns its data in JSON format, providing detailed information about requester objects. The response structure depends on whether you are fetching a list of requesters or a single requester:

1. Getting a List of Requesters (GET /api/v2/requesters)

The response contains an array of requester objects, typically wrapped in a property like requesters. Each object includes fields such as:

  • id: Unique ID of the requester
  • first_name and last_name
  • email
  • mobile_phone
  • created_at, updated_at
  • other requester-specific fields

Example structure:

{
  "requesters": [
    {
      "id": 123456,
      "first_name": "John",
      "last_name": "Doe",
      "email": "john.doe@example.com",
      "mobile_phone": "1234567890",
      "created_at": "2023-01-01T12:34:56Z",
      "updated_at": "2023-06-01T09:15:00Z"
      // ...more fields...
    },
    // ...more requester objects...
  ]
}

Depending on pagination, you may also see metadata such as total_count, per_page, and page.

2. Getting a Single Requester (GET /api/v2/requesters/[id])

The response returns a single requester object, usually keyed as requester, with the same fields as above:

{
  "requester": {
    "id": 123456,
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@example.com"
    // ...more fields...
  }
}

3. Common Response Features

  • Only JSON is supported in V2[7].
  • HTTP status codes and error bodies are used for error handling[5][7].
  • All endpoints require HTTPS[7].
  • Resource embedding is supported in some endpoints (like tickets—using include=requester), but for /requesters you get full requester objects directly[1][7].

4. Supported Methods

  • GET /api/v2/requesters (list all requesters, with optional query parameters)
  • GET /api/v2/requesters/[id] (get a specific requester)
  • POST, PUT, DELETE for creating, updating, and deleting requesters[4].

5. Example Fields

The default fields for a requester JSON object can include:

  • id
  • first_name
  • last_name
  • email
  • mobile_phone
  • work_phone
  • job_title
  • department_ids
  • created_at
  • updated_at
  • active (boolean)
  • custom_fields (object of custom attributes)

6. Error Structure

Errors are returned with appropriate HTTP status codes and a JSON error body:

{
  "code": "invalid_parameters",
  "message": "Email is required."
}

[5][7]

For exact up-to-date schema details and additional fields, always refer to the official Freshservice API documentation, as the platform can evolve and custom fields may be present depending on your Freshservice configuration[4][5][7].

Citations:


🏁 Script executed:

#!/bin/bash
# Verify usage and response handling in freshservice.app.mjs

echo "----- getCompanies usage -----"
rg -n "getCompanies\(" -A5 components/freshservice/freshservice.app.mjs || true

echo "----- getTickets usage -----"
rg -n "getTickets\(" -A5 components/freshservice/freshservice.app.mjs || true

echo "----- getAgents usage -----"
rg -n "getAgents\(" -A5 components/freshservice/freshservice.app.mjs || true

echo "----- getGroups usage -----"
rg -n "getGroups\(" -A5 components/freshservice/freshservice.app.mjs || true

echo "----- getContacts usage -----"
rg -n "getContacts\(" -A5 components/freshservice/freshservice.app.mjs || true

echo "----- contactEmail propDefinition -----"
rg -n "contactEmail" -A10 components/freshservice || true

Length of output: 3192


Destructure requesters from getContacts response
The Freshservice API’s /v2/requesters endpoint wraps its list in a requesters property, so getContacts() returns an object—not an array—causing contacts.map to fail. Other list methods correctly destructure their arrays (e.g., { companies }, { agents }, { groups }). Please update the contactEmail propDefinition accordingly.

Files to update:

  • components/freshservice/freshservice.app.mjs (around lines 101–108)

Suggested diff:

@@ components/freshservice/freshservice.app.mjs:101
-        const contacts = await this.getContacts({
+        const { requesters: contacts } = await this.getContacts({
           params: {
             page: page + 1,
             per_page: PAGE_SIZE,
             company_id: companyId,
           },
         });
-        return contacts?.map((contact) => ({
+        return contacts.map((contact) => ({
           id: contact.id,
           label: contact.email,
         }));
📝 Committable suggestion

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

Suggested change
const contacts = await this.getContacts({
params: {
page: page + 1,
per_page: PAGE_SIZE,
company_id: companyId,
},
});
return contacts?.map((contact) => ({
const { requesters: contacts } = await this.getContacts({
params: {
page: page + 1,
per_page: PAGE_SIZE,
company_id: companyId,
},
});
return contacts.map((contact) => ({
id: contact.id,
label: contact.email,
}));
🤖 Prompt for AI Agents
In components/freshservice/freshservice.app.mjs around lines 101 to 108, the
getContacts() method returns an object with a requesters property containing the
array, not the array directly. To fix the issue, destructure the requesters
array from the getContacts() response before mapping over it. Update the code to
extract { requesters } from the response and then map over requesters instead of
contacts. Also, adjust the contactEmail propDefinition if it relies on this data
structure.

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.

3 participants