-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
base: master
Are you sure you want to change the base?
Complete Freshservice integration to match Freshdesk functionality #17608
Conversation
- 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
Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified. |
@seynadio is attempting to deploy a commit to the Pipedreamers Team on Vercel. A member of the Team first needs to authorize it. |
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
WalkthroughThis update introduces 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
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
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
Possibly related PRs
Suggested reviewers
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
components/freshservice/actions/assign-ticket-to-agent/assign-ticket-to-agent.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs components/freshservice/actions/close-ticket/close-ticket.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs components/freshservice/actions/create-company/create-company.mjsOops! Something went wrong! :( ESLint: 8.57.1 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
components/freshservice/freshservice.app.mjs (1)
286-291
: Remove duplicate methodgetTickets
.The
getTickets
method is a duplicate of thelistTickets
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 !== ""
andobj[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 andSTATUS_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
📒 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 confirmedThe 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 yieldsYYYY-MM-DDTHH:MM:SSZ
, matching Freshservice API v2 requirementsAll 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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 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:
- 1: https://momentjs.com/docs/
- 2: https://forum.camunda.io/t/moment-js-vulnerability-for-version-2-29-4/39554
- 3: https://vulert.com/vuln-db/npm-moment-27082
- 4: https://github.com/moment/moment/blob/develop/CHANGELOG.md
- 5: Moment.js 2.29.4 CVE-2022-31129 primefaces/primefaces#8968
- 6: https://jira.atlassian.com/browse/BAM-22255
- 7: https://www.nuget.org/packages/Moment.js/2.25.2
- 8: Update moment version 2.29.4 to fix CVE-2022-31129 derekprior/momentjs-rails#65
- 9: https://nvd.nist.gov/vuln/detail/cve-2022-24785
- 10: https://security.snyk.io/package/npm/moment
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.
"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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 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:
-
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)
-
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) -
Introduction of Props: The concept of
params
was replaced withprops
for passing inputs to steps. This change impacts how data is passed and accessed within workflows. (pipedream.com) -
Removal of
$checkpoint
: The$checkpoint
functionality, used to save data between workflow runs, was removed and replaced by Data Stores. (pipedream.com) -
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:
- 1: https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai
- 2: https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai
- 3: https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai
- 4: https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai
- 5: https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai
- 6: https://pipedream.com/docs/deprecated/migrate-from-v1?utm_source=openai
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
– Replacewithasync (event, steps) { … }
defineComponent({ async run({ steps, $ }) { … }, });
- Input handling
– Change all uses ofparams
toprops
- 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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.
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, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 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 |
---|---|
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:
- 1: https://api.freshservice.com
- 2: https://support.freshservice.com/support/solutions/articles/50000000431-how-to-set-the-priority-of-the-tickets-automatically-
- 3: https://bathartisanmarket.com/freshservice-api-v2-documentation/
- 4: https://support.freshservice.com/support/solutions/articles/50000004099-analytics-glossary
- 5: https://developers.freshdesk.com/api/
- 6: https://support.freshservice.com/support/solutions/folders/50000000040
- 7: https://support.freshservice.com/support/solutions/articles/50000004220-introducing-upgraded-apis-freshservice-support
- 8: https://docs.workato.com/connectors/freshservice/update-ticket-action.html
- 9: https://support.freshservice.com/support/solutions/articles/50000005527-what-is-a-ticket-type-or-prefix-
- 10: https://support.freshservice.com/support/solutions/folders/50000000029
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
andimpact.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.
const contacts = await this.getContacts({ | ||
params: { | ||
page: page + 1, | ||
per_page: PAGE_SIZE, | ||
company_id: companyId, | ||
}, | ||
}); | ||
return contacts?.map((contact) => ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 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
- 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
- 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:
- 1: https://zuplo.com/blog/2025/05/08/freshservice-api
- 2: https://developers.freshworks.com/docs/tutorials/intermediate/request-method/lets-make-api-request/
- 3: https://developer.freshdesk.com/api/v1
- 4: https://developers.freshworks.com/docs/app-sdk/v3.0/service_user/rest-apis/
- 5: https://support.freshservice.com/support/solutions/articles/50000004220-introducing-upgraded-apis-freshservice-support
- 6: https://community.freshworks.com/api-and-webhooks-11406/index3.html
- 7: https://api.freshservice.com
- 8: https://community.atlassian.com/forums/Opsgenie-questions/Freshservice-API-V2/qaq-p/2115087
- 9: https://community.freshworks.com/apps-and-marketplace-integrations-11358/include-requester-details-in-custom-ticket-views-api-37541
- 10: https://developers.freshdesk.com/api/
🏁 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.
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.
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)
Enhanced Infrastructure
Internal Notes Support
private: true
/v2/tickets/{id}/notes
)Test plan
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
Enhancements
Chores