Skip to content

[Components] xendit #16278 #16385

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

Merged
merged 8 commits into from
Apr 28, 2025
Merged

[Components] xendit #16278 #16385

merged 8 commits into from
Apr 28, 2025

Conversation

luancazarine
Copy link
Collaborator

@luancazarine luancazarine commented Apr 21, 2025

Resolves - #16278

Summary by CodeRabbit

  • New Features

    • Introduced Xendit integration with actions to create invoices, create payouts, and check payment status.
    • Added support for polling and emitting new invoice events from Xendit.
    • Provided dynamic selection of payment request IDs and enhanced pagination for large data sets.
  • Enhancements

    • Added configurable notification, locale, and payment method options for invoices.
    • Improved configuration with new constants and utility functions for data parsing.
  • Documentation

    • Updated documentation site with new permanent redirects for component contribution guides.
  • Chores

    • Updated Xendit package dependencies and versioning for improved compatibility.
    • Removed obsolete app definition and adjusted package main entry point.

dannyroosevelt and others added 3 commits April 21, 2025 18:11
Sources
 - New Invoice

Actions
 - Create Invoice
 - Create Payout
 - Get Payment Status
@luancazarine luancazarine linked an issue Apr 21, 2025 that may be closed by this pull request
Copy link

vercel bot commented Apr 21, 2025

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

Name Status Preview Comments Updated (UTC)
docs-v2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 28, 2025 5:03pm
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
pipedream-docs ⬜️ Ignored (Inspect) Apr 28, 2025 5:03pm
pipedream-docs-redirect-do-not-edit ⬜️ Ignored (Inspect) Apr 28, 2025 5:03pm

Copy link
Contributor

coderabbitai bot commented Apr 21, 2025

Walkthrough

This set of changes introduces a new Xendit integration, including app logic, actions, sources, utilities, and constants. It adds modules for creating invoices and payouts, retrieving payment statuses, and emitting new invoice events. The Xendit app logic is implemented in a new .mjs file, supporting API calls and pagination. Supporting files provide constants and utility functions. Test data and source event handling are also included. The .gitignore and a previous TypeScript app file are removed. The package manifest is updated for dependencies and versioning. Additionally, new permanent redirect rules are added to the Next.js documentation configuration.

Changes

File(s) Change Summary
components/xendit/.gitignore Deleted .gitignore file that previously ignored .js, .mjs, and dist directory.
components/xendit/app/xendit.app.ts Deleted previous TypeScript app definition for Xendit.
components/xendit/xendit.app.mjs Added new Xendit app logic with API methods, authentication, and pagination.
components/xendit/actions/create-invoice/create-invoice.mjs
components/xendit/actions/create-payout/create-payout.mjs
components/xendit/actions/get-payment-status/get-payment-status.mjs
Added new action modules for creating invoices, creating payouts, and getting payment status via Xendit API.
components/xendit/common/constants.mjs Added constants for invoice notifications, locales, payment methods, and a numeric limit.
components/xendit/common/utils.mjs Added utility function for parsing JSON objects/arrays from strings.
components/xendit/sources/common/base.mjs Added base source component for event polling and incremental event emission.
components/xendit/sources/new-invoice/new-invoice.mjs Added new source component for emitting events when a new invoice is created.
components/xendit/sources/new-invoice/test-event.mjs Added test event data representing a sample invoice.
components/xendit/package.json Updated package version, entry point, removed files array, and added dependencies.
docs-v2/next.config.mjs Added four new permanent redirect rules for component documentation paths.

Sequence Diagram(s)

Loading
sequenceDiagram
    participant User
    participant ActionModule
    participant XenditApp
    participant XenditAPI

    User->>ActionModule: Provide input (e.g., create invoice)
    ActionModule->>XenditApp: Call API method with input
    XenditApp->>XenditAPI: Make HTTP request
    XenditAPI-->>XenditApp: Return API response
    XenditApp-->>ActionModule: Return processed response
    ActionModule-->>User: Return result/summary
Loading
sequenceDiagram
    participant SourceComponent
    participant XenditApp
    participant XenditAPI
    participant EventConsumer

    loop Polling Interval
        SourceComponent->>XenditApp: listInvoices (with cursor)
        XenditApp->>XenditAPI: Make HTTP request
        XenditAPI-->>XenditApp: Return invoices
        XenditApp-->>SourceComponent: Return data
        SourceComponent->>EventConsumer: Emit new invoice events
    end

Possibly related PRs

Suggested labels

ai-assisted

Suggested reviewers

  • lcaresia

Poem

A hop and a skip, new features appear,
Xendit now listens, emits, and draws near.
Invoices and payouts, events on the run,
Constants and helpers—oh, what fun!
Redirects are tidy, the docs now align,
This bunny’s delighted—your code’s looking fine!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

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

docs-v2/next.config.mjs

Oops! Something went wrong! :(

ESLint: 8.57.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsonc-eslint-parser' imported from /eslint.config.mjs
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 533ec93 and 21ceb70.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • docs-v2/next.config.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs-v2/next.config.mjs
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: pnpm publish
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Publish TypeScript components
✨ 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.

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Sorry, something went wrong.

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

🧹 Nitpick comments (8)
docs-v2/next.config.mjs (1)

339-358: Add a descriptive comment for this redirect block

For clarity and long‑term maintainability, consider inserting a brief comment above these entries—e.g.:

// Redirect legacy component docs into the new contributing section

This will help future readers quickly understand the intent of this group of rules.

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

14-133: Consider removing the empty line and check for duplicate payment methods.

There's an empty line after the array declaration (line 15), and "CREDIT_CARD" appears multiple times in the array (lines 16, 38, 70, 81, 91). If these duplicates are intentional (perhaps representing different regions), consider organizing them into categorized sub-objects for clarity.

 export const PAYMENT_METHODS_OPTIONS = [
-
   "CREDIT_CARD",
   "BCA",
   // ... other payment methods

Additionally, consider organizing by region if that's what the duplicate CREDIT_CARD entries represent:

// Example alternative structure (not a required change)
export const PAYMENT_METHODS_BY_REGION = {
  GLOBAL: ["CREDIT_CARD"],
  INDONESIA: ["BCA", "BNI", /* ... */],
  PHILIPPINES: ["7ELEVEN", "CEBUANA", /* ... */],
  // other regions...
};

export const PAYMENT_METHODS_OPTIONS = [
  ...PAYMENT_METHODS_BY_REGION.GLOBAL,
  ...PAYMENT_METHODS_BY_REGION.INDONESIA,
  // ... other regions
];
components/xendit/xendit.app.mjs (1)

30-38: Simplify the template literal in auth method.

The template literal in the _getAuth method is unnecessary since there's no additional string interpolation.

 _getAuth() {
   return {
-    "username": `${this.$auth.secret_key}`,
+    "username": this.$auth.secret_key,
     "password": "",
   };
 }
components/xendit/common/utils.mjs (1)

1-24: Enhance error handling in parseObject function.

The parseObject utility is well-implemented for parsing JSON strings with good handling of different input types. However, there are two potential improvements:

  1. Consider adding warning logs when JSON parsing fails to help with debugging.
  2. Be cautious with the falsy check on line 2 as it will return undefined for falsy values like empty strings or the number 0, which might be valid inputs in some contexts.
 export const parseObject = (obj) => {
-  if (!obj) return undefined;
+  if (obj === null || obj === undefined) return undefined;

   if (Array.isArray(obj)) {
     return obj.map((item) => {
       if (typeof item === "string") {
         try {
           return JSON.parse(item);
         } catch (e) {
+          console.warn(`Failed to parse JSON string: ${item}`, e);
           return item;
         }
       }
       return item;
     });
   }
   if (typeof obj === "string") {
     try {
       return JSON.parse(obj);
     } catch (e) {
+      console.warn(`Failed to parse JSON string: ${obj}`, e);
       return obj;
     }
   }
   return obj;
 };
components/xendit/actions/create-invoice/create-invoice.mjs (3)

21-25: Consider using numeric type for amount.

The amount property is defined as a string type, while it represents a numeric value. Although this might be intentional for handling precise decimal values, consider whether a "number" type would be more appropriate to ensure proper validation.

 amount: {
-  type: "string",
+  type: "number",
   label: "Amount",
   description: "Amount on the invoice. Min and max amounts are stated [here](https://docs.xendit.co/xeninvoice/payment-channels). The amount should be inclusive of any fees and or items that you may choose to include. If there is a difference between this amount and the sum of the price in the `items` parameters and or `fees` parameter, Xendit will refer to this amount parameter to create invoice. Do take note: if the currency or default currency is IDR and the amount includes decimals (e.g IDR 4550.50), the amount will be truncated to IDR 4550.",
 },

56-61: Clarify the expected format for addresses input.

The property type is defined as "string[]", but based on the description and usage of parseObject in line 152, it appears users should input a JSON-formatted string. Consider clarifying the expected format in the description or adjusting the type definition.

 addresses: {
   type: "string[]",
   label: "Addresses",
-  description: "A list of objects of customer's addresses",
+  description: "A list of objects of customer's addresses. Each object should contain address details. Input as stringified JSON array.",
   optional: true,
 },

121-126: Improve description for items array input format.

Similar to the addresses property, the items property expects a JSON-formatted string that will be parsed with parseObject. Consider clarifying the expected format in the description to guide users.

 items: {
   type: "string[]",
   label: "Items",
-  description: "Array of items JSON objects describing the item(s) purchased. Max array size: 75. Mandatory for PayLater payment method. [See the documentation](https://developers.xendit.co/api-reference/#create-invoice) for further details.",
+  description: "Array of items JSON objects describing the item(s) purchased. Input as stringified JSON array. Max array size: 75. Mandatory for PayLater payment method. [See the documentation](https://developers.xendit.co/api-reference/#create-invoice) for further details.",
   optional: true,
 },
components/xendit/actions/create-payout/create-payout.mjs (1)

37-41: Consider using numeric type for amount.

Similar to the create-invoice action, the amount property is defined as a string type while representing a numeric value. Consider whether a "number" type would be more appropriate for validation.

 amount: {
-  type: "string",
+  type: "number",
   label: "Amount",
   description: "Amount to be sent to the destination account. Should be a multiple of the minimum increment for the selected channel.",
 },
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 545b143 and 89fd64e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • components/xendit/.gitignore (0 hunks)
  • components/xendit/actions/create-invoice/create-invoice.mjs (1 hunks)
  • components/xendit/actions/create-payout/create-payout.mjs (1 hunks)
  • components/xendit/actions/get-payment-status/get-payment-status.mjs (1 hunks)
  • components/xendit/app/xendit.app.ts (0 hunks)
  • components/xendit/common/constants.mjs (1 hunks)
  • components/xendit/common/utils.mjs (1 hunks)
  • components/xendit/package.json (1 hunks)
  • components/xendit/sources/common/base.mjs (1 hunks)
  • components/xendit/sources/new-invoice/new-invoice.mjs (1 hunks)
  • components/xendit/sources/new-invoice/test-event.mjs (1 hunks)
  • components/xendit/xendit.app.mjs (1 hunks)
  • docs-v2/next.config.mjs (1 hunks)
💤 Files with no reviewable changes (2)
  • components/xendit/.gitignore
  • components/xendit/app/xendit.app.ts
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: pnpm publish
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: Lint Code Base
🔇 Additional comments (28)
docs-v2/next.config.mjs (1)

339-358: Redirect rules for component docs are configured correctly

The newly added entries precisely target the legacy /components/guidelines/, /components/actions-quickstart/, /components/sources-quickstart/, and /components/typescript/ paths, sending users to the updated /components/contributing/... routes without overlap or conflict with existing patterns.

components/xendit/common/constants.mjs (3)

1-2: LGTM: Good use of constants for pagination limits.

The LIMIT constant is appropriately defined and will provide consistency when used across the integration components.


3-7: LGTM: Well-defined notification options.

The INVOICE_NOTIFICATION_OPTIONS array is clearly defined with the available notification channels for Xendit invoices.


9-12: LGTM: Locale options clearly defined.

The LOCALE_OPTIONS array appropriately lists the supported locales for the Xendit integration.

components/xendit/xendit.app.mjs (5)

1-3: LGTM: Good imports.

Properly importing the axios from the platform and reusing the LIMIT constant from your constants file.


4-7: LGTM: Proper app definition.

The app type and name are correctly specified.


8-28: LGTM: Well-implemented dynamic property with pagination support.

The paymentRequestId property is well-defined with a clear label, description, and async options function that handles pagination via the after_id parameter.


39-47: LGTM: Well-implemented request method.

The _makeRequest method properly constructs the API request with the URL, authentication, and additional options.


48-81: LGTM: Comprehensive API method implementations.

The methods for interacting with Xendit's API endpoints are well-organized and follow a consistent pattern.

components/xendit/package.json (3)

3-3: LGTM: Appropriate version bump.

Bumping the version from 0.0.3 to 0.1.0 reflects the significant update with the introduction of new integration components.


5-5: LGTM: Updated main entry point.

The main entry point has been updated to reflect the new file structure.


15-17: LGTM: Required dependency added.

The @pipedream/platform dependency is correctly added, which is necessary for the axios import used in the app component.

components/xendit/sources/new-invoice/test-event.mjs (1)

1-45: Well-structured test event data

The test event contains a comprehensive representation of a Xendit invoice with all necessary fields including ID, status, merchant details, payment options, and timestamps. This provides a good example for testing the "New Invoice Created" source component.

components/xendit/sources/common/base.mjs (4)

16-22: LGTM: Clean state management implementation

The database methods for getting and setting the last processed event timestamp are simple and effective.


43-49: Good chronological ordering of events

Reversing the array before emission ensures events are emitted in chronological order (oldest first), which is a good practice for event processing pipelines.


52-59: Well-designed lifecycle hooks

The deployment hook emits initial events with a reasonable limit of 25, while the run method handles ongoing event emission. This pattern is effective for source components that need historical and real-time data.


22-50:

❓ Verification inconclusive

Verify sorting assumption in emitEvent method

This implementation assumes that the API returns items sorted by creation date in descending order (newest first). If this assumption is incorrect, the break condition at line 35 may prematurely stop processing valid events.


🏁 Script executed:

#!/bin/bash
# Check if the Xendit API documentation or implementation confirms the sort order
grep -r "sort" --include="*.mjs" components/xendit/

Length of output: 51


Verify sort order assumption in emitEvent

This method assumes that xendit.paginate() returns items in descending order by created. If that isn’t guaranteed, the break inside the for await loop may stop processing valid events.

• Confirm in the Xendit API/SDK documentation whether responses are sorted by created descending.
• If the API doesn’t guarantee this order, explicitly sort the results before applying the break, for example:

const items = await collect(response);
items.sort((a, b) => Date.parse(b.created) - Date.parse(a.created));

File: components/xendit/sources/common/base.mjs (lines 22–50)

components/xendit/sources/new-invoice/new-invoice.mjs (3)

4-11: Proper component metadata

The component has appropriate metadata including a descriptive name, documentation link, and correct deduplication strategy.


12-23: Clean extension of base methods

The component correctly extends the base component by overriding specific methods while preserving the core functionality. The getFunction, getCursor, and getSummary methods have appropriate implementations for invoice processing.


24-24: Well-integrated test event

The component properly integrates the sample event data from test-event.mjs for developer testing.

components/xendit/actions/get-payment-status/get-payment-status.mjs (2)

3-17: Well-defined action properties

The action has appropriate metadata and correctly uses prop definitions from the Xendit app for the payment request ID.


18-26: Effective implementation of the payment status retrieval

The run method properly passes the execution context and payment request ID to the Xendit API, and provides a useful summary message with the payment status. The implementation correctly returns the full response for further processing.

components/xendit/actions/create-invoice/create-invoice.mjs (4)

8-13: Well-structured action definition with clear documentation link.

The action definition includes a descriptive name, version, and a helpful link to the Xendit API documentation, making it easy for users to reference the underlying API details.


133-138: Ensure consistent handling of object properties.

The metadata property is defined as an object type, but unlike other object properties, it's not passed through the parseObject utility in line 167. Ensure this is intentional and that the handling is consistent.

Is this intentional? Other properties like items, fees, etc. use parseObject, but metadata is passed directly. Please verify that this is the correct approach for handling the metadata property.


140-169: Well-structured API request with proper field mapping.

The run method effectively maps all input properties to the appropriate Xendit API fields, using the parseObject utility when needed for JSON-formatted strings. The nested structure for customer details and notification preferences is well-organized.


171-173: Helpful success message with invoice ID.

The export of a summary message with the invoice ID provides clear feedback to the user about the successful creation of the invoice.

components/xendit/actions/create-payout/create-payout.mjs (2)

3-8: Well-structured action definition with clear documentation link.

The action definition includes a descriptive name, version, and a helpful link to the Xendit API documentation, which provides good context for users.


102-104: Helpful success message with payout ID.

The export of a summary message with the payout ID provides clear feedback to the user about the successful creation of the payout.

michelle0927
michelle0927 previously approved these changes Apr 22, 2025
Copy link
Collaborator

@michelle0927 michelle0927 left a comment

Choose a reason for hiding this comment

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

LGTM!

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@luancazarine
Copy link
Collaborator Author

/approve

@luancazarine luancazarine merged commit ceb196f into master Apr 28, 2025
11 checks passed
@luancazarine luancazarine deleted the issue-16278 branch April 28, 2025 19:11
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.

[Components] xendit
3 participants