- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.5k
[Components] taxjar #13392 #15907
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
[Components] taxjar #13392 #15907
Conversation
| The latest updates on your projects. Learn more about Vercel for Git ↗︎ 3 Skipped Deployments
 | 
| WalkthroughThis PR removes the TaxJar component’s  Changes
 Sequence Diagram(s)sequenceDiagram
    participant U as User/Caller
    participant A as Action Module
    participant App as TaxJar App Module
    participant API as TaxJar API
    U->>A: Invoke action (e.g., Calculate Sales Tax)
    A->>App: Call corresponding API method (calculateSalesTax, createCustomer, validateAddress)
    App->>API: HTTP POST Request to TaxJar endpoint
    API-->>App: Return API response
    App-->>A: Pass response along with summary
    A-->>U: Return full response and confirmation
Possibly related PRs
 Suggested labels
 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
 Scope: all 2 workspace projects Tip ⚡🧪 Multi-step agentic review comment chat (experimental)
 ✨ 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: 
 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: 2
🧹 Nitpick comments (5)
components/taxjar/actions/create-customer/create-customer.mjs (1)
1-82: Consider adding error handlingThe action is well-structured with appropriate properties and API request formatting. However, the success message on line 79 is output without checking if the response indicates success. Consider adding error handling to ensure accurate feedback.
You could enhance the error handling by adding a try-catch block or checking the response status:
async run({ $ }) { const response = await this.app.createCustomer({ $, data: { customer_id: this.customerId, exemption_type: this.exemptionType, name: this.name, country: this.country, state: this.state, zip: this.zip, city: this.city, street: this.street, }, }); - $.export("$summary", `Successfully created customer with ID ${this.customerId}`); + if (response && response.customer) { + $.export("$summary", `Successfully created customer with ID ${this.customerId}`); + } else { + $.export("$summary", `Request completed, but customer creation status couldn't be verified`); + } return response; },components/taxjar/actions/validate-address/validate-address.mjs (1)
48-61: Add defensive check for addresses arrayThe success message on line 59 assumes that
response.addressesexists and is an array. Add a defensive check to prevent potential runtime errors if the API response is different than expected.async run({ $ }) { const response = await this.app.validateAddress({ $, data: { country: this.country, state: this.state, zip: this.zip, city: this.city, street: this.street, }, }); - $.export("$summary", `Successfully sent the request and found ${response.addresses.length} address matches`); + const addressCount = response?.addresses?.length || 0; + $.export("$summary", `Successfully sent the request and found ${addressCount} address matches`); return response; },components/taxjar/taxjar.app.mjs (3)
89-98: Convert financial values to number typeThe
amountandshippingprops are defined as strings, which could lead to precision issues when performing financial calculations. Consider changing these to numeric types for more accurate calculations.amount: { - type: "string", + type: "number", label: "Amount", description: "Total amount of the order, excluding shipping", }, shipping: { - type: "string", + type: "number", label: "Shipping", description: "Total amount of shipping for the order", },
87-87: Fix typo in toState descriptionThere's a typo in the description of the
toStateproperty where "shipped yo" should be "shipped to".- description: "The two-letter ISO state code where the order shipped yo, i.e.: `CA`", + description: "The two-letter ISO state code where the order shipped to, i.e.: `CA`",
114-117: Add API key validationThe code directly uses the API key without checking if it exists. Adding validation will provide a better error message if the authentication is not set up correctly.
url: this._baseUrl() + path, headers: { - Authorization: `Bearer ${this.$auth.api_key}`, + Authorization: `Bearer ${this.$auth.api_key || ""}`, ...headers, },Additionally, consider adding a validation check before making the request:
async _makeRequest(opts = {}) { const { $ = this, path, headers, ...otherOpts } = opts; + + if (!this.$auth.api_key) { + throw new Error("TaxJar API key is required. Please add an API key to this connection."); + } return axios($, {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
- pnpm-lock.yamlis excluded by- !**/pnpm-lock.yaml
📒 Files selected for processing (8)
- components/taxjar/.gitignore(0 hunks)
- components/taxjar/actions/calculate-sales-tax/calculate-sales-tax.mjs(1 hunks)
- components/taxjar/actions/create-customer/create-customer.mjs(1 hunks)
- components/taxjar/actions/validate-address/validate-address.mjs(1 hunks)
- components/taxjar/app/taxjar.app.ts(0 hunks)
- components/taxjar/common/constants.mjs(1 hunks)
- components/taxjar/package.json(1 hunks)
- components/taxjar/taxjar.app.mjs(1 hunks)
💤 Files with no reviewable changes (2)
- components/taxjar/app/taxjar.app.ts
- components/taxjar/.gitignore
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: pnpm publish
- GitHub Check: Verify TypeScript components
- GitHub Check: Publish TypeScript components
🔇 Additional comments (3)
components/taxjar/common/constants.mjs (1)
1-8: Well-structured constants moduleThe constants module is cleanly defined with appropriate exemption types for TaxJar. This centralized approach will help maintain consistency across the application when referencing these exemption types.
components/taxjar/package.json (1)
3-17: Version update and dependency changes look appropriateThe version bump from 0.0.2 to 0.1.0 makes sense given the addition of new functionality. The simplification of the main entry point and addition of the platform dependency also look good.
components/taxjar/taxjar.app.mjs (1)
2-2:✅ Verification successful
Verify constants import and implementation
The code imports a constants module, but we don't see the contents of this file in the review. Make sure the
constants.mjsfile is properly implemented and includes all required constants likeEXEMPTION_TYPESused on line 17.
🏁 Script executed:
#!/bin/bash # Check if the constants file exists and print its contents if [ -f "components/taxjar/common/constants.mjs" ]; then echo "Constants file exists:" cat "components/taxjar/common/constants.mjs" else echo "Constants file not found!" fiLength of output: 263
Constants File Verified
The constants file exists at
components/taxjar/common/constants.mjsand correctly exports an object with theEXEMPTION_TYPESarray. The implementation meets the requirements referenced on line 17 oftaxjar.app.mjs. No further changes are needed.
| import app from "../../taxjar.app.mjs"; | ||
|  | ||
| export default { | ||
| key: "taxjar-calculate-sales-tax", | ||
| name: "Calculate Sales Tax", | ||
| description: "Shows the sales tax that should be collected for a given order. [See the documentation](https://developers.taxjar.com/api/reference/#taxes)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| props: { | ||
| app, | ||
| exemptionType: { | ||
| propDefinition: [ | ||
| app, | ||
| "exemptionType", | ||
| ], | ||
| }, | ||
| fromCountry: { | ||
| propDefinition: [ | ||
| app, | ||
| "fromCountry", | ||
| ], | ||
| }, | ||
| fromZip: { | ||
| propDefinition: [ | ||
| app, | ||
| "fromZip", | ||
| ], | ||
| }, | ||
| fromState: { | ||
| propDefinition: [ | ||
| app, | ||
| "fromState", | ||
| ], | ||
| }, | ||
| fromCity: { | ||
| propDefinition: [ | ||
| app, | ||
| "fromCity", | ||
| ], | ||
| }, | ||
| fromStreet: { | ||
| propDefinition: [ | ||
| app, | ||
| "fromStreet", | ||
| ], | ||
| }, | ||
| toCountry: { | ||
| propDefinition: [ | ||
| app, | ||
| "toCountry", | ||
| ], | ||
| }, | ||
| toZip: { | ||
| propDefinition: [ | ||
| app, | ||
| "toZip", | ||
| ], | ||
| }, | ||
| toState: { | ||
| propDefinition: [ | ||
| app, | ||
| "toState", | ||
| ], | ||
| }, | ||
| amount: { | ||
| propDefinition: [ | ||
| app, | ||
| "amount", | ||
| ], | ||
| }, | ||
| shipping: { | ||
| propDefinition: [ | ||
| app, | ||
| "shipping", | ||
| ], | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.app.calculateSalesTax({ | ||
| $, | ||
| data: { | ||
| exemption_type: this.exemptionType, | ||
| from_country: this.fromCountry, | ||
| from_zip: this.fromZip, | ||
| from_state: this.fromState, | ||
| from_city: this.fromCity, | ||
| from_street: this.fromStreet, | ||
| to_country: this.toCountry, | ||
| to_zip: this.toZip, | ||
| to_state: this.toState, | ||
| amount: this.amount, | ||
| shipping: this.shipping, | ||
| }, | ||
| }); | ||
| $.export("$summary", `Successfully calculated sales tax. Amount to collect: ${response.tax.amount_to_collect}`); | ||
| return response; | ||
| }, | ||
| }; | 
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
Enhance error handling and add validation checks
The overall structure of this action is well-organized and follows Pipedream's component model correctly. However, there are some improvements needed for robustness:
- The run method should include error handling to gracefully handle API failures
- The summary message doesn't verify if response.tax.amount_to_collectexists before accessing it
  async run({ $ }) {
-   const response = await this.app.calculateSalesTax({
-     $,
-     data: {
-       exemption_type: this.exemptionType,
-       from_country: this.fromCountry,
-       from_zip: this.fromZip,
-       from_state: this.fromState,
-       from_city: this.fromCity,
-       from_street: this.fromStreet,
-       to_country: this.toCountry,
-       to_zip: this.toZip,
-       to_state: this.toState,
-       amount: this.amount,
-       shipping: this.shipping,
-     },
-   });
-   $.export("$summary", `Successfully calculated sales tax. Amount to collect: ${response.tax.amount_to_collect}`);
-   return response;
+   try {
+     const response = await this.app.calculateSalesTax({
+       $,
+       data: {
+         exemption_type: this.exemptionType,
+         from_country: this.fromCountry,
+         from_zip: this.fromZip,
+         from_state: this.fromState,
+         from_city: this.fromCity,
+         from_street: this.fromStreet,
+         to_country: this.toCountry,
+         to_zip: this.toZip,
+         to_state: this.toState,
+         amount: this.amount,
+         shipping: this.shipping,
+       },
+     });
+     
+     const amountToCollect = response?.tax?.amount_to_collect || 0;
+     $.export("$summary", `Successfully calculated sales tax. Amount to collect: ${amountToCollect}`);
+     return response;
+   } catch (error) {
+     $.export("$summary", "Failed to calculate sales tax");
+     throw error;
+   }
  },📝 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.
| import app from "../../taxjar.app.mjs"; | |
| export default { | |
| key: "taxjar-calculate-sales-tax", | |
| name: "Calculate Sales Tax", | |
| description: "Shows the sales tax that should be collected for a given order. [See the documentation](https://developers.taxjar.com/api/reference/#taxes)", | |
| version: "0.0.1", | |
| type: "action", | |
| props: { | |
| app, | |
| exemptionType: { | |
| propDefinition: [ | |
| app, | |
| "exemptionType", | |
| ], | |
| }, | |
| fromCountry: { | |
| propDefinition: [ | |
| app, | |
| "fromCountry", | |
| ], | |
| }, | |
| fromZip: { | |
| propDefinition: [ | |
| app, | |
| "fromZip", | |
| ], | |
| }, | |
| fromState: { | |
| propDefinition: [ | |
| app, | |
| "fromState", | |
| ], | |
| }, | |
| fromCity: { | |
| propDefinition: [ | |
| app, | |
| "fromCity", | |
| ], | |
| }, | |
| fromStreet: { | |
| propDefinition: [ | |
| app, | |
| "fromStreet", | |
| ], | |
| }, | |
| toCountry: { | |
| propDefinition: [ | |
| app, | |
| "toCountry", | |
| ], | |
| }, | |
| toZip: { | |
| propDefinition: [ | |
| app, | |
| "toZip", | |
| ], | |
| }, | |
| toState: { | |
| propDefinition: [ | |
| app, | |
| "toState", | |
| ], | |
| }, | |
| amount: { | |
| propDefinition: [ | |
| app, | |
| "amount", | |
| ], | |
| }, | |
| shipping: { | |
| propDefinition: [ | |
| app, | |
| "shipping", | |
| ], | |
| }, | |
| }, | |
| async run({ $ }) { | |
| const response = await this.app.calculateSalesTax({ | |
| $, | |
| data: { | |
| exemption_type: this.exemptionType, | |
| from_country: this.fromCountry, | |
| from_zip: this.fromZip, | |
| from_state: this.fromState, | |
| from_city: this.fromCity, | |
| from_street: this.fromStreet, | |
| to_country: this.toCountry, | |
| to_zip: this.toZip, | |
| to_state: this.toState, | |
| amount: this.amount, | |
| shipping: this.shipping, | |
| }, | |
| }); | |
| $.export("$summary", `Successfully calculated sales tax. Amount to collect: ${response.tax.amount_to_collect}`); | |
| return response; | |
| }, | |
| }; | |
| import app from "../../taxjar.app.mjs"; | |
| export default { | |
| key: "taxjar-calculate-sales-tax", | |
| name: "Calculate Sales Tax", | |
| description: "Shows the sales tax that should be collected for a given order. [See the documentation](https://developers.taxjar.com/api/reference/#taxes)", | |
| version: "0.0.1", | |
| type: "action", | |
| props: { | |
| app, | |
| exemptionType: { | |
| propDefinition: [ | |
| app, | |
| "exemptionType", | |
| ], | |
| }, | |
| fromCountry: { | |
| propDefinition: [ | |
| app, | |
| "fromCountry", | |
| ], | |
| }, | |
| fromZip: { | |
| propDefinition: [ | |
| app, | |
| "fromZip", | |
| ], | |
| }, | |
| fromState: { | |
| propDefinition: [ | |
| app, | |
| "fromState", | |
| ], | |
| }, | |
| fromCity: { | |
| propDefinition: [ | |
| app, | |
| "fromCity", | |
| ], | |
| }, | |
| fromStreet: { | |
| propDefinition: [ | |
| app, | |
| "fromStreet", | |
| ], | |
| }, | |
| toCountry: { | |
| propDefinition: [ | |
| app, | |
| "toCountry", | |
| ], | |
| }, | |
| toZip: { | |
| propDefinition: [ | |
| app, | |
| "toZip", | |
| ], | |
| }, | |
| toState: { | |
| propDefinition: [ | |
| app, | |
| "toState", | |
| ], | |
| }, | |
| amount: { | |
| propDefinition: [ | |
| app, | |
| "amount", | |
| ], | |
| }, | |
| shipping: { | |
| propDefinition: [ | |
| app, | |
| "shipping", | |
| ], | |
| }, | |
| }, | |
| async run({ $ }) { | |
| try { | |
| const response = await this.app.calculateSalesTax({ | |
| $, | |
| data: { | |
| exemption_type: this.exemptionType, | |
| from_country: this.fromCountry, | |
| from_zip: this.fromZip, | |
| from_state: this.fromState, | |
| from_city: this.fromCity, | |
| from_street: this.fromStreet, | |
| to_country: this.toCountry, | |
| to_zip: this.toZip, | |
| to_state: this.toState, | |
| amount: this.amount, | |
| shipping: this.shipping, | |
| }, | |
| }); | |
| const amountToCollect = response?.tax?.amount_to_collect || 0; | |
| $.export("$summary", `Successfully calculated sales tax. Amount to collect: ${amountToCollect}`); | |
| return response; | |
| } catch (error) { | |
| $.export("$summary", "Failed to calculate sales tax"); | |
| throw error; | |
| } | |
| }, | |
| }; | 
| async _makeRequest(opts = {}) { | ||
| const { | ||
| $ = this, | ||
| path, | ||
| headers, | ||
| ...otherOpts | ||
| } = opts; | ||
| return axios($, { | ||
| ...otherOpts, | ||
| url: this._baseUrl() + path, | ||
| headers: { | ||
| Authorization: `Bearer ${this.$auth.api_key}`, | ||
| ...headers, | ||
| }, | ||
| }); | ||
| }, | 
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
Enhance _makeRequest method with better error handling
The current implementation of _makeRequest doesn't handle API errors explicitly. Improving error handling will make debugging easier when API calls fail.
  async _makeRequest(opts = {}) {
    const {
      $ = this,
      path,
      headers,
      ...otherOpts
    } = opts;
-   return axios($, {
-     ...otherOpts,
-     url: this._baseUrl() + path,
-     headers: {
-       Authorization: `Bearer ${this.$auth.api_key}`,
-       ...headers,
-     },
-   });
+   try {
+     return await axios($, {
+       ...otherOpts,
+       url: this._baseUrl() + path,
+       headers: {
+         Authorization: `Bearer ${this.$auth.api_key}`,
+         ...headers,
+       },
+     });
+   } catch (error) {
+     const status = error.response?.status;
+     const statusText = error.response?.statusText;
+     const errorMsg = error.response?.data?.error || error.message;
+     
+     throw new Error(`TaxJar API error (${status} ${statusText}): ${errorMsg}`);
+   }
  },📝 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.
| async _makeRequest(opts = {}) { | |
| const { | |
| $ = this, | |
| path, | |
| headers, | |
| ...otherOpts | |
| } = opts; | |
| return axios($, { | |
| ...otherOpts, | |
| url: this._baseUrl() + path, | |
| headers: { | |
| Authorization: `Bearer ${this.$auth.api_key}`, | |
| ...headers, | |
| }, | |
| }); | |
| }, | |
| async _makeRequest(opts = {}) { | |
| const { | |
| $ = this, | |
| path, | |
| headers, | |
| ...otherOpts | |
| } = opts; | |
| try { | |
| return await axios($, { | |
| ...otherOpts, | |
| url: this._baseUrl() + path, | |
| headers: { | |
| Authorization: `Bearer ${this.$auth.api_key}`, | |
| ...headers, | |
| }, | |
| }); | |
| } catch (error) { | |
| const status = error.response?.status; | |
| const statusText = error.response?.statusText; | |
| const errorMsg = error.response?.data?.error || error.message; | |
| throw new Error(`TaxJar API error (${status} ${statusText}): ${errorMsg}`); | |
| } | |
| }, | 
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.
Hi @lcaresia, LGTM! Ready for QA!
WHY
Summary by CodeRabbit
New Features
Chores