Skip to content

feat(integrations): Add ClickSend integration provider #316

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 2 commits into
base: main
Choose a base branch
from

Conversation

SteliosMav
Copy link

Describe your changes

Description:

This PR introduces the ClickSend integration template to the integration-templates repository.

Summary of changes:

  • Created a new integration for ClickSend following Nango best practices.
  • Properly structured actions and syncs according to Nango's Custom Integration Guide.
  • Fully linted and verified against the project’s ESLint rules.
  • Added an appropriate README.md file with setup instructions.
  • Followed folder and file organization standards consistent with existing integration templates.
  • Utilized MCP features through Cursor IDE to enhance code quality, maintain context, and ensure consistency across files.
  • Ensured API endpoints match ClickSend’s official developer documentation.
  • Tested the integration manually via unit testing and local environment validation.
  • No breaking changes introduced.

Issue ticket number and link

Checklist before requesting a review (skip if just adding/editing APIs & templates)

  • I added tests, otherwise the reason is:

Only the sms-history sync does not yet have a test file.
This is because it uses the paginate, which requires the provider to be fully registered first.
Currently, since ClickSend is not yet added to the live providers, it causes a provider existence validation error.
I plan to add the test for sms-history as soon as the provider is merged.

All other actions and syncs interact via direct proxy endpoints, which do not require provider existence validation, allowing them to have working tests already.

  • External API requests have retries
  • Pagination is used where appropriate
  • The built in nango.paginate call is used instead of a while (true) loop
  • Third party requests are NOT parallelized (this can cause issues with rate limits)
  • If a sync requires metadata the nango.yaml has auto_start: false
  • If the sync is a full sync then track_deletes: true is set
  • I followed the best practices and guidelines from the Writing Integration Scripts doc

Copy link
Contributor

coderabbitai bot commented Apr 25, 2025

Walkthrough

This change introduces a new integration for ClickSend, encompassing configuration, implementation, documentation, schema definitions, and comprehensive testing. The integration is declared in both flows.yaml and a dedicated nango.yaml, specifying two actions—send-sms (to send SMS messages) and fetch-account (to retrieve account information)—along with a sync operation sms-history for incremental retrieval of SMS message history. Data models for SMS input, SMS messages, and account information are defined in TypeScript interfaces, JSON Schema, and Zod validation schemas. The implementation includes action handlers, data mapping functions, and a sync script, all supported by mock data and Vitest-based unit tests. Extensive documentation in markdown format details each action and sync, including endpoint specifications, request/response schemas, and changelog references. No existing code or models are modified; all additions are new and self-contained within the ClickSend integration.

Suggested labels

Automation

✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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.

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

🧹 Nitpick comments (15)
integrations/clicksend/tests/clicksend-fetch-account.test.ts (1)

12-18: Consider adding edge case tests

While the happy path test is good, consider adding tests for error scenarios such as API failures or malformed responses to ensure robust error handling.

it('should output the action output that is expected', async () => {
    const input = await nangoMock.getInput();
    const response = await runAction(nangoMock, input);
    const output = await nangoMock.getOutput();

    expect(response).toEqual(output);
});

+it('should handle API errors gracefully', async () => {
+    // Modify the mock to simulate an API error
+    nangoMock.proxy.mockResolvedValueOnce({
+        status: 500,
+        data: { error: 'Internal Server Error' }
+    });
+    
+    const input = await nangoMock.getInput();
+    
+    // The action should throw an ActionError with appropriate message
+    await expect(runAction(nangoMock, input)).rejects.toThrow();
+});
integrations/clicksend/actions/fetch-account.md (2)

22-22: Fix markdown syntax for heading.

The markdown linter flagged an issue with using emphasis instead of a heading. Replace the emphasis with a proper heading.

-_No request parameters_
+### No request parameters
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

22-22: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)


26-26: Fix markdown syntax for heading.

The markdown linter flagged an issue with using emphasis instead of a heading. Replace the emphasis with a proper heading.

-_No request body_
+### No request body
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

26-26: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

integrations/clicksend/actions/fetch-account.ts (2)

5-5: Avoid using void for an unused input parameter.
The _input?: void signature can be confusing—consider removing the unused parameter entirely or typing it as undefined to improve readability.

-export default async function runAction(nango: NangoAction, _input?: void): Promise<Account> {
+export default async function runAction(nango: NangoAction): Promise<Account> {
🧰 Tools
🪛 Biome (1.9.4)

[error] 5-5: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


7-11: Explicitly include an empty params object in the proxy config.
Following the established pattern for proxy calls, adding params: {} signals there are no query parameters and keeps the shape consistent across integrations.

 const response = await nango.proxy({
     endpoint: '/account',
+    params: {},
     method: 'GET',
     retries: 3
 });
integrations/clicksend/syncs/sms-history.md (3)

24-24: Add missing space after punctuation.
Ensure sentences are separated properly by a space: change time.If to time. If.

- ... a specific point in time.If not provided...
+ ... a specific point in time. If not provided...
🧰 Tools
🪛 LanguageTool

[style] ~24-~24: This phrase is redundant. Consider writing “point” or “time”.
Context: ...fetch records modified after a specific point in time.If not provided, all records are return...

(MOMENT_IN_TIME)


26-26: Correct pluralization.
Change “An array of string” to “An array of strings” for grammatical accuracy.

- **ids:** `(optional, string[])` An array of string containing...
+ **ids:** `(optional, string[])` An array of strings containing...
🧰 Tools
🪛 LanguageTool

[uncategorized] ~26-~26: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...ray of string containing a list of your records IDs. The list will be filtered to inclu...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)


9-9: Use plain text instead of emphasis for “None.”
Avoid italicizing _None_; use unformatted text to improve clarity.

- - **Scopes:** _None_
+ - **Scopes:** None
integrations/clicksend/actions/send-sms.md (1)

2-2: Use consistent capitalization for SMS.
Update the heading from “Send Sms” to “Send SMS” to match the acronym style used elsewhere.

- # Send Sms
+ # Send SMS
integrations/clicksend/syncs/sms-history.ts (1)

6-6: Consider using a more specific type for params

While Record<string, any> works, consider using a more specific type for better type safety, such as Record<string, string | number> since you're only adding timestamps.

-const params: Record<string, any> = {};
+const params: Record<string, string | number> = {};
integrations/clicksend/tests/clicksend-send-sms.test.ts (1)

5-19: Consider adding more test cases

The test is well-structured but only covers the happy path. Consider adding test cases for:

  • Invalid input validation
  • Error handling scenarios
  • Edge cases (e.g., empty fields)

This would improve test coverage and ensure robustness.

demo-github-integration/syncs/github-issue-example.ts (4)

1-1: Consider importing specific types

Your import statement is using a relative path ('../../models'). For better maintenance, consider using path aliases if your project supports them, or import specific types directly from their source files.


16-16: Use TypeScript type guards for safer type checking

The current type filtering relies on property checks without proper type narrowing.

- const issues: any[] = issueBatch.filter((issue: any) => !('pull_request' in issue));
+ const issues: GitHubIssue[] = issueBatch.filter((issue: GitHubIssue): issue is GitHubIssue => 
+   !('pull_request' in issue));

32-35: Consider adding record count metrics

The current implementation logs the number of issues processed per repository, but doesn't track the total issues synced.

+ let totalIssueCount = 0;

// Inside the repository loop
  if (mappedIssues.length > 0) {
      await nango.batchSave(mappedIssues, 'GithubIssue');
      await nango.log(`Sent ${mappedIssues.length} issues from ${repo.owner.login}/${repo.name}`);
+     totalIssueCount += mappedIssues.length;
  }

// At the end of the fetchData function
+ await nango.log(`Total GitHub issues synced: ${totalIssueCount}`);

9-14: Consider adding rate limit protection for the GitHub API

GitHub has strict rate limits. Add retry configuration to handle potential rate limit errors.

const proxyConfig = {
    endpoint: `/repos/${repo.owner.login}/${repo.name}/issues`,
    paginate: {
        limit: LIMIT
    },
+   retries: 3,
+   retryOn: [429, 503]
};
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7284276 and 314fc36.

⛔ Files ignored due to path filters (1)
  • dist/github-issue-example-demo-github-integration.js is excluded by !**/dist/**
📒 Files selected for processing (25)
  • .nango/schema.json (1 hunks)
  • .nango/schema.ts (1 hunks)
  • demo-github-integration/syncs/github-issue-example.ts (1 hunks)
  • flows.yaml (1 hunks)
  • integrations/clicksend/.nango/schema.json (1 hunks)
  • integrations/clicksend/.nango/schema.ts (1 hunks)
  • integrations/clicksend/actions/fetch-account.md (1 hunks)
  • integrations/clicksend/actions/fetch-account.ts (1 hunks)
  • integrations/clicksend/actions/send-sms.md (1 hunks)
  • integrations/clicksend/actions/send-sms.ts (1 hunks)
  • integrations/clicksend/mappers/to-account.ts (1 hunks)
  • integrations/clicksend/mappers/to-sms.ts (1 hunks)
  • integrations/clicksend/mocks/fetch-account/output.json (1 hunks)
  • integrations/clicksend/mocks/nango/get/proxy/account/fetch-account/abd756729884886e6a97f89f107907c4d96aa044.json (1 hunks)
  • integrations/clicksend/mocks/nango/post/proxy/sms/send/send-sms/ef821ad18258311a60ec6e84cd2316729825303d.json (1 hunks)
  • integrations/clicksend/mocks/send-sms/input.json (1 hunks)
  • integrations/clicksend/mocks/send-sms/output.json (1 hunks)
  • integrations/clicksend/nango.yaml (1 hunks)
  • integrations/clicksend/schema.zod.ts (1 hunks)
  • integrations/clicksend/syncs/sms-history.md (1 hunks)
  • integrations/clicksend/syncs/sms-history.ts (1 hunks)
  • integrations/clicksend/tests/clicksend-fetch-account.test.ts (1 hunks)
  • integrations/clicksend/tests/clicksend-send-sms.test.ts (1 hunks)
  • integrations/clicksend/types.ts (1 hunks)
  • nango.yaml (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`integrations/**/**.ts`: - Use TypeScript best practices and ensure typings are strictly defined. - Use comments to explain logic and link to external API documentation. - Place en...

integrations/**/**.ts: - Use TypeScript best practices and ensure typings are strictly defined.

  • Use comments to explain logic and link to external API documentation.
  • Place endpoint URLs as comments above API requests.
  • Avoid modifying arguments and prefer returning new values.
  • Create a types.ts file containing typed third-party API responses.
  • Proxy calls should use retries (default: 10).
  • Use await nango.log() instead of console.log for logging.
  • Use the params property in proxy calls instead of appending params onto the endpoint.
  • Use nango.paginate wherever possible for pagination.
  • Always use ProxyConfiguration for proxy request configurations.
  • Validate inputs/outputs using zod.
  • Ensure date inputs are valid and converted using new Date() to the provider's expected format.

Syncs

  • The fetchData function must be the default export and placed at the top.
  • Always paginate requests to ensure all records are retrieved.
  • Avoid parallel requests to maintain the retry policy and prevent rate limits.
  • Mapping logic should be in a dedicated function.
  • Shared mapping logic should be stored in a mappers directory.
  • Mapper files should follow the mappers/to-{entity}.ts naming convention.
  • Avoid type casting and rely on TypeScript's type checking.
  • If the sync is incremental, use nango.lastSyncDate.

Actions

  • The runAction function must be the default export and placed at the top.
  • Use ActionError only for specific error messages, otherwise rely on script failure.

Example:

throw new nango.ActionError<ActionErrorResponse>({
  message: 'Missing some parameter that will prevent the action from successfully running'
});

TypeScript Development Guidelines

Syncs

  • fetchData must be the default export at the top of the file
  • Always paginate requests to retrieve all records
  • Avoid parallelizing requests (defeats retry policy and rate limiting)
  • Do not wrap syncs in try-catch blocks (Nango handles error reporting)
  • Use dedicated mapper functions for data transformation:
  • Place shared mappers in a mappers directory
  • Name files as mappers/to-${entity} (e.g., mappers/to-employee.ts)
  • Avoid type casting to leverage TypeScript benefits:
  • For incremental syncs, use nango.lastSyncDate

Actions

  • runAction must be the default export at the top of the file
  • Only use ActionError for specific error messages:
  • Always return objects, not arrays
  • Always define API calls using a typed ProxyConfiguration object with retries set to 3:
  • When implementing pagination in actions, always return a cursor-based response to allow users to paginate through results:
  • integrations/clicksend/tests/clicksend-fetch-account.test.ts
  • integrations/clicksend/types.ts
  • integrations/clicksend/mappers/to-sms.ts
  • integrations/clicksend/actions/send-sms.ts
  • integrations/clicksend/actions/fetch-account.ts
  • integrations/clicksend/schema.zod.ts
  • integrations/clicksend/mappers/to-account.ts
  • integrations/clicksend/tests/clicksend-send-sms.test.ts
  • integrations/clicksend/syncs/sms-history.ts
`integrations/**/nango.yaml`: - If `sync_type: full`, then the sync should also have `track_deletes: true`. - If the sync requires metadata, set `auto_start: false` and document th...

integrations/**/nango.yaml: - If sync_type: full, then the sync should also have track_deletes: true.

  • If the sync requires metadata, set auto_start: false and document the metadata as an input in nango.yaml.

  • Scopes should be explicitly documented.

  • If sync_type: full, then the sync should also have track_deletes: true

  • If the sync requires metadata, then the sync should be set to auto_start: false. The metadata should be documented as an input in the nango.yaml

  • Scopes should be documented

  • For optional properties in models, use the ? suffix after the property name

  • Endpoints should be concise and simple, not necessarily reflecting the exact third-party API path

  • Model names and endpoint paths should not be duplicated within an integration

  • When adding a new integration, take care to not remove unrelated entries in the nango.yaml

  • For enum values in models, do not use quotes around the values

  • integrations/clicksend/nango.yaml
🧬 Code Graph Analysis (5)
integrations/clicksend/mappers/to-sms.ts (2)
integrations/clicksend/types.ts (1)
  • ClickSendSms (1-30)
integrations/clicksend/.nango/schema.ts (1)
  • Sms (11-19)
integrations/clicksend/actions/send-sms.ts (3)
integrations/clicksend/.nango/schema.ts (2)
  • ClickSendSmsInput (6-9)
  • Sms (11-19)
integrations/clicksend/types.ts (1)
  • ClickSendSms (1-30)
integrations/clicksend/mappers/to-sms.ts (1)
  • toSms (11-23)
integrations/clicksend/actions/fetch-account.ts (3)
integrations/clicksend/.nango/schema.ts (1)
  • Account (21-31)
integrations/clicksend/types.ts (1)
  • ClickSendAccount (32-62)
integrations/clicksend/mappers/to-account.ts (1)
  • toAccount (15-27)
integrations/clicksend/mappers/to-account.ts (2)
integrations/clicksend/types.ts (1)
  • ClickSendAccount (32-62)
integrations/clicksend/.nango/schema.ts (1)
  • Account (21-31)
demo-github-integration/syncs/github-issue-example.ts (2)
integrations/clicksend/syncs/sms-history.ts (1)
  • fetchData (5-39)
.nango/schema.ts (1)
  • GithubIssue (6-17)
🪛 markdownlint-cli2 (0.17.2)
integrations/clicksend/actions/fetch-account.md

22-22: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)


26-26: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

integrations/clicksend/syncs/sms-history.md

30-30: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

🪛 Biome (1.9.4)
integrations/clicksend/actions/fetch-account.ts

[error] 5-5: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🪛 LanguageTool
integrations/clicksend/syncs/sms-history.md

[uncategorized] ~22-~22: You might be missing the article “the” here.
Context: ...ed_after parameter is less precise than cursor, as multiple records may share the same...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[style] ~24-~24: This phrase is redundant. Consider writing “point” or “time”.
Context: ...fetch records modified after a specific point in time.If not provided, all records are return...

(MOMENT_IN_TIME)


[uncategorized] ~26-~26: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...ray of string containing a list of your records IDs. The list will be filtered to inclu...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)

🪛 Gitleaks (8.21.2)
integrations/clicksend/mocks/nango/get/proxy/account/fetch-account/abd756729884886e6a97f89f107907c4d96aa044.json

66-66: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (25)
.nango/schema.ts (1)

6-17: Interface structure looks correct

The GithubIssue interface properly defines all necessary fields with appropriate types for GitHub issue data storage. The use of proper TypeScript types including Date objects for timestamps follows best practices.

integrations/clicksend/mocks/send-sms/input.json (1)

1-4: Mock input looks appropriate

The input JSON provides a valid test case with an international phone number format and a test message body, which aligns with the expected input for a send-SMS action.

integrations/clicksend/mocks/send-sms/output.json (1)

1-9: Mock output structure looks correct

The output JSON correctly models a ClickSend SMS response with all the expected fields: unique ID, phone numbers, message content, status, and timestamps. This matches what we would expect from the ClickSend API.

integrations/clicksend/mocks/fetch-account/output.json (1)

1-11: Account mock data looks appropriate

The account data structure includes all expected fields for a ClickSend account with proper formatting for identifiers, contact information, and numeric values like balance. This provides a good test case for the fetch-account action.

integrations/clicksend/tests/clicksend-fetch-account.test.ts (1)

5-19: Test implementation looks solid

The test correctly initializes the NangoActionMock with proper parameters, executes the action with mock input, and validates the response against expected output. This ensures the fetch-account action functions correctly.

integrations/clicksend/mappers/to-sms.ts (1)

1-23: Well-implemented mapper function with proper type definitions.

This mapper function correctly transforms a ClickSendSms object from the API response into our standardized internal Sms model. The date conversion from UNIX timestamp to ISO string is properly implemented, and all required fields are mapped.

integrations/clicksend/actions/fetch-account.md (1)

1-51: Documentation is clear and comprehensive.

The overall documentation provides excellent information about the fetch-account action, including its purpose, endpoint details, and response format.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

22-22: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)


26-26: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

integrations/clicksend/actions/send-sms.ts (1)

1-26: Overall implementation follows best practices.

The action follows best practices by using a typed ProxyConfiguration object, setting retries, providing API documentation, and using the mapper function to standardize the response format.

integrations/clicksend/actions/fetch-account.ts (1)

6-6: Documentation link placement is correct.
The API reference URL sits immediately above the proxy call, aiding future maintainers.

integrations/clicksend/mappers/to-account.ts (1)

15-27: Mapping logic is correct and well-structured.
The toAccount function properly converts and formats fields (e.g., user_idid, concatenating names) and aligns with the internal Account schema.

integrations/clicksend/syncs/sms-history.ts (3)

8-10: Excellent handling of lastSyncDate conversion

The conversion from date to Unix timestamp is correctly implemented, ensuring proper pagination from the last sync point.


12-26: Well-configured proxy with proper documentation and pagination

The proxy configuration properly includes:

  • API endpoint documentation link
  • Correctly configured pagination settings
  • Appropriate retry count (10)
  • Well-structured parameters

This follows best practices for Nango integrations.


28-38: Good implementation of pagination and data processing

The code correctly:

  • Uses nango.paginate for efficient pagination
  • Validates response structure
  • Maps data using the dedicated mapper function
  • Only saves when there's data to save

This is an optimal implementation of the sync pattern.

integrations/clicksend/types.ts (2)

1-30: Comprehensive SMS type definition

The ClickSendSms interface is well-structured with:

  • Proper typing for all fields
  • Comprehensive status union type
  • Clear documentation for optional fields
  • Appropriate handling of varying field types (string | null, etc.)

This provides strong typing for the API integration.


32-62: Well-defined Account interface with placeholders for future expansion

The ClickSendAccount interface is thorough and includes appropriate documentation for fields that may need expansion in the future. The use of Record<string, unknown> with explanatory comments is a good approach for fields with unknown structure.

integrations/clicksend/schema.zod.ts (3)

4-7: Minimal and effective input validation

The input schema correctly validates the required fields (to and body) for sending an SMS.


9-27: Thorough SMS schema with well-defined status literals

The SMS schema properly:

  • Defines all required fields with appropriate types
  • Uses a union of literals for the status field
  • Includes timestamp fields with string validation

This ensures strong validation for SMS data objects.


29-39: Properly structured account schema

The account schema correctly defines all required fields with appropriate string validations.

integrations/clicksend/nango.yaml (2)

3-20: Actions configuration looks solid
The send-sms and fetch-account actions are well-defined with method, path, input/output types, and grouping.


21-33: Sync configuration is correct
The incremental sms-history sync is properly defined with sync_type: incremental, track_deletes: false, scheduling, and auto_start: true.

integrations/clicksend/.nango/schema.json (1)

33-35: Verify completeness of Sms.status enum
Please confirm whether "SUCCESS" is a valid message-level status from ClickSend. If so, update the enum to include "SUCCESS"; otherwise adjust mocks/tests to use a supported value.

integrations/clicksend/.nango/schema.ts (1)

16-16: Align TypeScript union with JSON schema
If you decide to add "SUCCESS" to the JSON schema, update this union accordingly:

-    status: 'QUEUED' | 'COMPLETED' | 'SCHEDULED' | 'WAIT_APPROVAL' | 'FAILED' | 'CANCELLED' | 'CANCELLED_AFTER_REVIEW' | 'RECEIVED' | 'SENT';
+    status: 'QUEUED' | 'COMPLETED' | 'SCHEDULED' | 'WAIT_APPROVAL' | 'FAILED' | 'CANCELLED' | 'CANCELLED_AFTER_REVIEW' | 'RECEIVED' | 'SENT' | 'SUCCESS';
flows.yaml (3)

3434-3452: Integration Structure: Actions Block Looks Correct
The clicksend integration’s actions section is well-structured, with clear endpoint definitions (/sms/send, /account), versioning, groups, and matching input/output types. Indentation and naming conventions align with existing templates.


3453-3466: Sync Configuration: Verify Incremental Sync Details
The sms-history sync is marked as incremental and scheduled every half hour. Please confirm that the underlying sync implementation defines and uses a cursor field (e.g., createdAt or pagination token) so the resume logic works as intended. Ensure the YAML properties here match your nango.paginate call and any custom parameters in sms-history.ts.


3467-3490: Models Block: Confirm Field Mappings
The ClickSendSmsInput, Sms, and Account models enumerate all expected properties. Double-check that these fields exactly mirror the API response keys and your JSON schema in integrations/clicksend/.nango/schema.json to prevent runtime validation errors.

@SteliosMav
Copy link
Author

Following the changes introduced here, where the base URL was updated (removing /v3 from the base URL because it isn't part of it), I'm about to make another commit. This next one will include small adjustments to add /v3 to the sync and action endpoints, along with a few additional fixes suggested by CodeRabbitAI.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
integrations/clicksend/actions/send-sms.ts (1)

26-33: LGTM! Added error handling for missing response data.

The error handling for missing response data has been properly implemented.

🧹 Nitpick comments (5)
integrations/clicksend/actions/fetch-account.ts (2)

5-5: Consider using undefined instead of void for input parameter type

The static analysis tool flagged the use of void as a type parameter. In TypeScript, void is typically used for return types that don't return a value, not as a parameter type.

-export default async function runAction(nango: NangoAction, _input?: void): Promise<Account> {
+export default async function runAction(nango: NangoAction, _input?: undefined): Promise<Account> {
🧰 Tools
🪛 Biome (1.9.4)

[error] 5-5: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


13-13: Consider adding type validation for the API response

While the typings provide structure, there's no runtime validation of the API response. Consider using zod to validate the structure of the API response before processing it.

import { clickSendAccountSchema } from '../schema.zod.js';

// Replace line 13 with:
const data = response.data.data;
const validationResult = clickSendAccountSchema.safeParse(data);
if (!validationResult.success) {
    await nango.log('Failed to validate account data', { error: validationResult.error });
    throw new Error('Invalid account data received from ClickSend API');
}
const clickSendAccount: ClickSendAccount = validationResult.data;
integrations/clicksend/mappers/to-sms.ts (1)

19-22: Add clarification about identical timestamp fields.

The createdAt and updatedAt fields are both derived from the same date property. Consider adding a comment to clarify that this is intentional and that ClickSend doesn't provide separate creation and update timestamps.

        // UNIX timestamp to ISO date
        createdAt: new Date(message.date * 1000).toISOString(),
+       // ClickSend doesn't provide separate update timestamps, using the same date
        updatedAt: new Date(message.date * 1000).toISOString()
integrations/clicksend/syncs/sms-history.md (2)

22-22: Fix grammatical error in description.

There's a missing "the" article before "cursor".

-modified_after parameter is less precise than cursor, as multiple records may share the same
+modified_after parameter is less precise than the cursor, as multiple records may share the same
🧰 Tools
🪛 LanguageTool

[uncategorized] ~22-~22: You might be missing the article “the” here.
Context: ...ed_after parameter is less precise than cursor, as multiple records may share the same...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


24-24: Add space after period in sentence.

There's a missing space between sentences.

-fetch records modified after a specific point in time.If not provided, all records are returned.
+fetch records modified after a specific point in time. If not provided, all records are returned.
🧰 Tools
🪛 LanguageTool

[style] ~24-~24: This phrase is redundant. Consider writing “point” or “time”.
Context: ...fetch records modified after a specific point in time.If not provided, all records are return...

(MOMENT_IN_TIME)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 314fc36 and a50e81d.

📒 Files selected for processing (14)
  • flows.yaml (1 hunks)
  • integrations/clicksend/.nango/schema.json (1 hunks)
  • integrations/clicksend/.nango/schema.ts (1 hunks)
  • integrations/clicksend/actions/fetch-account.ts (1 hunks)
  • integrations/clicksend/actions/send-sms.md (1 hunks)
  • integrations/clicksend/actions/send-sms.ts (1 hunks)
  • integrations/clicksend/mappers/to-sms.ts (1 hunks)
  • integrations/clicksend/mocks/nango/get/proxy/v3/account/fetch-account/6dc41d02e1c27b5788531bfdf2583a8cc821a4e0.json (1 hunks)
  • integrations/clicksend/mocks/nango/post/proxy/v3/sms/send/send-sms/e2c198d02ddeb067302cec37ce1d85b60a4e4e7e.json (1 hunks)
  • integrations/clicksend/nango.yaml (1 hunks)
  • integrations/clicksend/schema.zod.ts (1 hunks)
  • integrations/clicksend/syncs/sms-history.md (1 hunks)
  • integrations/clicksend/syncs/sms-history.ts (1 hunks)
  • integrations/clicksend/types.ts (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • integrations/clicksend/mocks/nango/post/proxy/v3/sms/send/send-sms/e2c198d02ddeb067302cec37ce1d85b60a4e4e7e.json
  • integrations/clicksend/mocks/nango/get/proxy/v3/account/fetch-account/6dc41d02e1c27b5788531bfdf2583a8cc821a4e0.json
  • flows.yaml
🚧 Files skipped from review as they are similar to previous changes (6)
  • integrations/clicksend/syncs/sms-history.ts
  • integrations/clicksend/types.ts
  • integrations/clicksend/.nango/schema.ts
  • integrations/clicksend/nango.yaml
  • integrations/clicksend/schema.zod.ts
  • integrations/clicksend/.nango/schema.json
🧰 Additional context used
📓 Path-based instructions (1)
`integrations/**/**.ts`: - Use TypeScript best practices and ensure typings are strictly defined. - Use comments to explain logic and link to external API documentation. - Place en...

integrations/**/**.ts: - Use TypeScript best practices and ensure typings are strictly defined.

  • Use comments to explain logic and link to external API documentation.
  • Place endpoint URLs as comments above API requests.
  • Avoid modifying arguments and prefer returning new values.
  • Create a types.ts file containing typed third-party API responses.
  • Proxy calls should use retries (default: 10).
  • Use await nango.log() instead of console.log for logging.
  • Use the params property in proxy calls instead of appending params onto the endpoint.
  • Use nango.paginate wherever possible for pagination.
  • Always use ProxyConfiguration for proxy request configurations.
  • Validate inputs/outputs using zod.
  • Ensure date inputs are valid and converted using new Date() to the provider's expected format.

Syncs

  • The fetchData function must be the default export and placed at the top.
  • Always paginate requests to ensure all records are retrieved.
  • Avoid parallel requests to maintain the retry policy and prevent rate limits.
  • Mapping logic should be in a dedicated function.
  • Shared mapping logic should be stored in a mappers directory.
  • Mapper files should follow the mappers/to-{entity}.ts naming convention.
  • Avoid type casting and rely on TypeScript's type checking.
  • If the sync is incremental, use nango.lastSyncDate.

Actions

  • The runAction function must be the default export and placed at the top.
  • Use ActionError only for specific error messages, otherwise rely on script failure.

Example:

throw new nango.ActionError<ActionErrorResponse>({
  message: 'Missing some parameter that will prevent the action from successfully running'
});

TypeScript Development Guidelines

Syncs

  • fetchData must be the default export at the top of the file
  • Always paginate requests to retrieve all records
  • Avoid parallelizing requests (defeats retry policy and rate limiting)
  • Do not wrap syncs in try-catch blocks (Nango handles error reporting)
  • Use dedicated mapper functions for data transformation:
  • Place shared mappers in a mappers directory
  • Name files as mappers/to-${entity} (e.g., mappers/to-employee.ts)
  • Avoid type casting to leverage TypeScript benefits:
  • For incremental syncs, use nango.lastSyncDate

Actions

  • runAction must be the default export at the top of the file
  • Only use ActionError for specific error messages:
  • Always return objects, not arrays
  • Always define API calls using a typed ProxyConfiguration object with retries set to 3:
  • When implementing pagination in actions, always return a cursor-based response to allow users to paginate through results:
  • integrations/clicksend/actions/send-sms.ts
  • integrations/clicksend/mappers/to-sms.ts
  • integrations/clicksend/actions/fetch-account.ts
🧬 Code Graph Analysis (3)
integrations/clicksend/actions/send-sms.ts (4)
integrations/clicksend/.nango/schema.ts (2)
  • ClickSendSendSmsInput (6-9)
  • Sms (11-19)
integrations/clicksend/schema.zod.ts (1)
  • clickSendSendSmsInputSchema (4-7)
integrations/clicksend/types.ts (1)
  • ClickSendSms (1-30)
integrations/clicksend/mappers/to-sms.ts (1)
  • toSms (11-23)
integrations/clicksend/mappers/to-sms.ts (2)
integrations/clicksend/types.ts (1)
  • ClickSendSms (1-30)
integrations/clicksend/.nango/schema.ts (1)
  • Sms (11-19)
integrations/clicksend/actions/fetch-account.ts (3)
integrations/clicksend/.nango/schema.ts (1)
  • Account (21-31)
integrations/clicksend/types.ts (1)
  • ClickSendAccount (32-62)
integrations/clicksend/mappers/to-account.ts (1)
  • toAccount (15-27)
🪛 Biome (1.9.4)
integrations/clicksend/actions/fetch-account.ts

[error] 5-5: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🪛 markdownlint-cli2 (0.17.2)
integrations/clicksend/actions/send-sms.md

22-22: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

integrations/clicksend/syncs/sms-history.md

30-30: Emphasis used instead of a heading
null

(MD036, no-emphasis-as-heading)

🪛 LanguageTool
integrations/clicksend/syncs/sms-history.md

[uncategorized] ~22-~22: You might be missing the article “the” here.
Context: ...ed_after parameter is less precise than cursor, as multiple records may share the same...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[style] ~24-~24: This phrase is redundant. Consider writing “point” or “time”.
Context: ...fetch records modified after a specific point in time.If not provided, all records are return...

(MOMENT_IN_TIME)

🔇 Additional comments (5)
integrations/clicksend/actions/fetch-account.ts (2)

7-11: The endpoint should include /v3 explicitly

According to the PR objectives, a recent update to the base URL removed /v3, requiring endpoints to explicitly include it. However, I notice your endpoint already includes /v3/account, which means this implementation already incorporates the planned adjustment.


7-16: The function follows appropriate error handling patterns

The code correctly uses the proxy method with retries set to 3, allowing Nango's built-in error handling to manage failures. The response structure and mapping logic are properly implemented.

integrations/clicksend/mappers/to-sms.ts (1)

25-50: LGTM! Well-structured status mapping function.

The status mapping function provides a robust handling of all possible status values with appropriate error handling for unknown values.

integrations/clicksend/actions/send-sms.ts (2)

6-8: LGTM! Proper input validation implemented.

The input validation using Zod schema follows the coding guidelines and ensures input data correctness.


18-24: LGTM! Proper proxy configuration setup.

The proxy configuration correctly includes retries and the API endpoint documentation URL as a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant