-
Notifications
You must be signed in to change notification settings - Fork 5.5k
[Components] finerworks #10976 #18830
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
Changes from 2 commits
08b3ac4
045c9ed
ca7b96b
24f7e5c
4bf481a
7dd11b2
927c805
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import app from "../../finerworks.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "finerworks-get-prices", | ||
| name: "Get Prices", | ||
| description: "Get the price of a product. [See the documentation](https://v2.api.finerworks.com/Help/Api/POST-v3-get_prices)", | ||
| version: "0.0.1", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: true, | ||
| }, | ||
| type: "action", | ||
| props: { | ||
| app, | ||
| productSku: { | ||
| propDefinition: [ | ||
| app, | ||
| "productSku", | ||
| ], | ||
| }, | ||
| productQty: { | ||
| propDefinition: [ | ||
| app, | ||
| "productQty", | ||
| ], | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.app.getPrices({ | ||
| $, | ||
| data: [ | ||
| { | ||
| product_qty: this.productQty, | ||
| product_sku: this.productSku, | ||
| }, | ||
| ], | ||
| }); | ||
| $.export("$summary", "Successfully sent the request"); | ||
| return response; | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import app from "../../finerworks.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "finerworks-get-product-details", | ||
| name: "Get Product Details", | ||
| description: "Get details of a product. [See the documentation](https://v2.api.finerworks.com/Help/Api/POST-v3-get_product_details)", | ||
| version: "0.0.1", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: true, | ||
| }, | ||
| type: "action", | ||
| props: { | ||
| app, | ||
| productSku: { | ||
| propDefinition: [ | ||
| app, | ||
| "productSku", | ||
| ], | ||
| }, | ||
| productQty: { | ||
| propDefinition: [ | ||
| app, | ||
| "productQty", | ||
| ], | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.app.getProductDetails({ | ||
| $, | ||
| data: { | ||
| products: [ | ||
| { | ||
| product_sku: this.productSku, | ||
| product_qty: this.productQty, | ||
| }, | ||
| ], | ||
| }, | ||
| }); | ||
| $.export("$summary", "Successfully sent the request to get details of the specified product"); | ||
lcaresia marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return response; | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,105 @@ | ||||||
| import app from "../../finerworks.app.mjs"; | ||||||
|
|
||||||
| export default { | ||||||
| key: "finerworks-validate-address", | ||||||
| name: "Validate Address", | ||||||
| description: "Validate an address. [See the documentation](https://v2.api.finerworks.com/Help/Api/POST-v3-validate_recipient_address)", | ||||||
| version: "0.0.1", | ||||||
| annotations: { | ||||||
| destructiveHint: false, | ||||||
| openWorldHint: true, | ||||||
| readOnlyHint: true, | ||||||
| }, | ||||||
| type: "action", | ||||||
| props: { | ||||||
| app, | ||||||
| firstName: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "firstName", | ||||||
| ], | ||||||
| }, | ||||||
| lastName: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "lastName", | ||||||
| ], | ||||||
| }, | ||||||
| companyName: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "companyName", | ||||||
| ], | ||||||
| }, | ||||||
| address: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "address", | ||||||
| ], | ||||||
| }, | ||||||
| city: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "city", | ||||||
| ], | ||||||
| }, | ||||||
| stateCode: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "stateCode", | ||||||
| ], | ||||||
| }, | ||||||
| province: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "province", | ||||||
| ], | ||||||
| }, | ||||||
| zipPostalCode: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "zipPostalCode", | ||||||
| ], | ||||||
| }, | ||||||
| countryCode: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "countryCode", | ||||||
| ], | ||||||
| }, | ||||||
| phone: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "phone", | ||||||
| ], | ||||||
| }, | ||||||
| email: { | ||||||
| propDefinition: [ | ||||||
| app, | ||||||
| "email", | ||||||
| ], | ||||||
| }, | ||||||
| }, | ||||||
| async run({ $ }) { | ||||||
| const response = await this.app.validateAddress({ | ||||||
| $, | ||||||
| data: { | ||||||
| recipient: { | ||||||
| first_name: this.firstName, | ||||||
| last_name: this.lastName, | ||||||
| company_name: this.companyName, | ||||||
| address_1: this.address, | ||||||
| city: this.city, | ||||||
| state_code: this.stateCode, | ||||||
| province: this.province, | ||||||
| zip_postal_code: this.zipPostalCode, | ||||||
| country_code: this.countryCode, | ||||||
| phone: this.phone, | ||||||
| email: this.email, | ||||||
| }, | ||||||
| }, | ||||||
| }); | ||||||
| $.export("$summary", "Successfully sent the request. Validation success: " + response.status.success); | ||||||
|
||||||
| $.export("$summary", "Successfully sent the request. Validation success: " + response.status.success); | |
| $.export("$summary", `Successfully sent the request. Validation success: ${response.status?.success ?? 'unknown'}`); |
🤖 Prompt for AI Agents
In components/finerworks/actions/validate-address/validate-address.mjs around
line 102, the summary concatenates response.status.success directly which can be
undefined and produce misleading text or throw; update the expression to use
optional chaining and a safe fallback (e.g., response?.status?.success ?? false
or convert to a string like String(response?.status?.success ?? 'unknown')) so
the summary always displays a deterministic value and won’t throw when response
or status is missing.
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.
Same for this summary (also worth checking CodeRabbit's comment)
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the summary messages in the other action files
cat components/finerworks/actions/get-prices/get-prices.mjs | grep -A 2 -B 2 '\$\.export.*\$summary'
echo "---"
cat components/finerworks/actions/get-product-details/get-product-details.mjs | grep -A 2 -B 2 '\$\.export.*\$summary'
Length of output: 247
@GTFalcao, I checked all the summary messages in this PR. The good news is that get-prices.mjs and get-product-details.mjs are already using safe static strings for their summaries, so they don't have the same issue.
Only validate-address.mjs has the unsafe property access problem that CodeRabbit flagged. You should apply the fix here using optional chaining and a template literal:
$.export("$summary", `Successfully sent the request. Validation success: ${response.status?.success ?? 'unknown'}`);Alternatively, if you want to make it more robust and user-friendly, you could use:
$.export("$summary", `Address validation ${response.status?.success ? 'succeeded' : 'failed'}`);This would give a clearer message about whether the validation actually passed or not.
🧠 Learnings used
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`.
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,140 @@ | ||||||||||||||||
| import { axios } from "@pipedream/platform"; | ||||||||||||||||
|
|
||||||||||||||||
| export default { | ||||||||||||||||
| type: "app", | ||||||||||||||||
| app: "finerworks", | ||||||||||||||||
| propDefinitions: {}, | ||||||||||||||||
| propDefinitions: { | ||||||||||||||||
| firstName: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "First Name", | ||||||||||||||||
| description: "Recipient first name", | ||||||||||||||||
| }, | ||||||||||||||||
| lastName: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Last Name", | ||||||||||||||||
| description: "Recipient last name", | ||||||||||||||||
| }, | ||||||||||||||||
| companyName: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Company Name", | ||||||||||||||||
| description: "Recipient company name", | ||||||||||||||||
| optional: true, | ||||||||||||||||
| }, | ||||||||||||||||
| address: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Address", | ||||||||||||||||
| description: "Street address for the recipient", | ||||||||||||||||
| }, | ||||||||||||||||
| city: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "City", | ||||||||||||||||
| description: "Recipient city", | ||||||||||||||||
| optional: true, | ||||||||||||||||
| }, | ||||||||||||||||
| stateCode: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "State Code", | ||||||||||||||||
| description: "Required if in U.S. A valid USPS recognized 2 digit state code, i.e.: `CA`", | ||||||||||||||||
| optional: true, | ||||||||||||||||
| }, | ||||||||||||||||
| province: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Province", | ||||||||||||||||
| description: "Province or region name", | ||||||||||||||||
| optional: true, | ||||||||||||||||
| }, | ||||||||||||||||
| zipPostalCode: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "ZIP or Postal Code", | ||||||||||||||||
| description: "ZIP or postal code of the recipient", | ||||||||||||||||
| }, | ||||||||||||||||
| countryCode: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Country Code", | ||||||||||||||||
| description: "Two-letter ISO country code, e.g.: `US`, `CA`, `GB`", | ||||||||||||||||
| }, | ||||||||||||||||
| phone: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Phone", | ||||||||||||||||
| description: "Recipient phone number", | ||||||||||||||||
| optional: true, | ||||||||||||||||
| }, | ||||||||||||||||
| email: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Email", | ||||||||||||||||
| description: "Recipient email address", | ||||||||||||||||
| optional: true, | ||||||||||||||||
| }, | ||||||||||||||||
| productQty: { | ||||||||||||||||
| type: "integer", | ||||||||||||||||
| label: "Product Quantity", | ||||||||||||||||
| description: "Quantity of the product", | ||||||||||||||||
| }, | ||||||||||||||||
| productSku: { | ||||||||||||||||
| type: "string", | ||||||||||||||||
| label: "Product SKU", | ||||||||||||||||
| description: "SKU identifier of the product", | ||||||||||||||||
| async options() { | ||||||||||||||||
| const response = await this.getProducts(); | ||||||||||||||||
| const products = response.products; | ||||||||||||||||
| return products.map(({ | ||||||||||||||||
| sku, name, | ||||||||||||||||
| }) => ({ | ||||||||||||||||
| label: name, | ||||||||||||||||
| value: sku, | ||||||||||||||||
| })); | ||||||||||||||||
| }, | ||||||||||||||||
| }, | ||||||||||||||||
| }, | ||||||||||||||||
| methods: { | ||||||||||||||||
| // this.$auth contains connected account data | ||||||||||||||||
| authKeys() { | ||||||||||||||||
| console.log(Object.keys(this.$auth)); | ||||||||||||||||
| _baseUrl() { | ||||||||||||||||
| return "https://v2.api.finerworks.com/v3"; | ||||||||||||||||
| }, | ||||||||||||||||
| async _makeRequest(opts = {}) { | ||||||||||||||||
| const { | ||||||||||||||||
| $ = this, | ||||||||||||||||
| path, | ||||||||||||||||
| headers, | ||||||||||||||||
| ...otherOpts | ||||||||||||||||
| } = opts; | ||||||||||||||||
| return axios($, { | ||||||||||||||||
| ...otherOpts, | ||||||||||||||||
| url: this._baseUrl() + path, | ||||||||||||||||
| headers: { | ||||||||||||||||
| "web_api_key": `${this.$auth.web_api_key}`, | ||||||||||||||||
| "app_key": `${this.$auth.app_key}`, | ||||||||||||||||
|
Comment on lines
+113
to
+114
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Remove unnecessary template literals. The authentication keys are already strings and don't need template literal wrapping. This simplifies the code without changing behavior. Apply this diff: headers: {
- "web_api_key": `${this.$auth.web_api_key}`,
- "app_key": `${this.$auth.app_key}`,
+ "web_api_key": this.$auth.web_api_key,
+ "app_key": this.$auth.app_key,
...headers,
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| ...headers, | ||||||||||||||||
| }, | ||||||||||||||||
| }); | ||||||||||||||||
| }, | ||||||||||||||||
| async validateAddress(args = {}) { | ||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||
| path: "/validate_recipient_address", | ||||||||||||||||
| method: "post", | ||||||||||||||||
| ...args, | ||||||||||||||||
| }); | ||||||||||||||||
| }, | ||||||||||||||||
| async getPrices(args = {}) { | ||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||
| path: "/get_prices", | ||||||||||||||||
| method: "post", | ||||||||||||||||
| ...args, | ||||||||||||||||
| }); | ||||||||||||||||
| }, | ||||||||||||||||
| async getProductDetails(args = {}) { | ||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||
| path: "/get_product_details", | ||||||||||||||||
| method: "post", | ||||||||||||||||
| ...args, | ||||||||||||||||
| }); | ||||||||||||||||
| }, | ||||||||||||||||
| async getProducts(args = {}) { | ||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||
| path: "/list_virtual_inventory", | ||||||||||||||||
| method: "post", | ||||||||||||||||
| data: {}, | ||||||||||||||||
| ...args, | ||||||||||||||||
| }); | ||||||||||||||||
| }, | ||||||||||||||||
| }, | ||||||||||||||||
| }; | ||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.