From ffb4497b17a653133d7e2b0c5d24085785671a6b Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Tue, 15 Jul 2025 11:45:29 -0400 Subject: [PATCH 1/3] new components --- .../create-return-order.mjs | 147 +++++++++ .../list-return-orders/list-return-orders.mjs | 63 ++++ .../list-sales-orders/list-sales-orders.mjs | 32 ++ .../update-return-order-status.mjs | 36 +++ components/returnless/common/utils.mjs | 27 ++ components/returnless/package.json | 7 +- components/returnless/returnless.app.mjs | 305 +++++++++++++++++- components/returnless/sources/common/base.mjs | 72 +++++ .../new-return-created/new-return-created.mjs | 22 ++ .../return-notes-added/return-notes-added.mjs | 22 ++ .../return-product-marked-received.mjs | 22 ++ .../return-status-changed.mjs | 22 ++ 12 files changed, 770 insertions(+), 7 deletions(-) create mode 100644 components/returnless/actions/create-return-order/create-return-order.mjs create mode 100644 components/returnless/actions/list-return-orders/list-return-orders.mjs create mode 100644 components/returnless/actions/list-sales-orders/list-sales-orders.mjs create mode 100644 components/returnless/actions/update-return-order-status/update-return-order-status.mjs create mode 100644 components/returnless/common/utils.mjs create mode 100644 components/returnless/sources/common/base.mjs create mode 100644 components/returnless/sources/new-return-created/new-return-created.mjs create mode 100644 components/returnless/sources/return-notes-added/return-notes-added.mjs create mode 100644 components/returnless/sources/return-product-marked-received/return-product-marked-received.mjs create mode 100644 components/returnless/sources/return-status-changed/return-status-changed.mjs diff --git a/components/returnless/actions/create-return-order/create-return-order.mjs b/components/returnless/actions/create-return-order/create-return-order.mjs new file mode 100644 index 0000000000000..f4464b850c151 --- /dev/null +++ b/components/returnless/actions/create-return-order/create-return-order.mjs @@ -0,0 +1,147 @@ +import returnless from "../../returnless.app.mjs"; +import { parseObject } from "../../common/utils.mjs"; + +export default { + key: "returnless-create-return-order", + name: "Create Return Order", + description: "Create a return order. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/1fce50b07484b-creates-a-return-order-from-a-return-order-intent)", + version: "0.0.1", + type: "action", + props: { + returnless, + formId: { + propDefinition: [ + returnless, + "formId", + ], + }, + locale: { + type: "string", + label: "Locale", + description: "The locale of the form to create the return-order intent for", + }, + input: { + type: "string", + label: "Input", + description: "The input for the order. This could be an email address or postalcode or something else.", + }, + orderId: { + propDefinition: [ + returnless, + "orderId", + ], + }, + customerHouseNumber: { + type: "string", + label: "Customer House Number", + description: "The house number of the customer", + }, + customerStreet: { + type: "string", + label: "Customer Street", + description: "The street of the customer", + }, + customerPostalCode: { + type: "string", + label: "Customer Postal Code", + description: "The postal code of the customer", + }, + customerCity: { + type: "string", + label: "Customer City", + description: "The city of the customer", + }, + customerCountryId: { + propDefinition: [ + returnless, + "countryId", + ], + }, + itemIds: { + propDefinition: [ + returnless, + "itemIds", + (c) => ({ + orderId: c.orderId, + }), + ], + reloadProps: true, + }, + metadata: { + type: "object", + label: "Metadata", + description: "Metadata key/value pairs to add to the return order", + optional: true, + }, + }, + async additionalProps() { + const props = {}; + if (!this.itemIds) { + return props; + } + const { data: items } = await this.returnless.listSalesOrderItems({ + orderId: this.orderId, + }); + for (const item of items) { + props[`item${item.id}Quantity`] = { + type: "string", + label: `Item ${item.id} Quantity`, + description: `The quantity of item ${item.id} to return`, + }; + props[`item${item.id}ReturnReasonId`] = { + type: "string", + label: `Item ${item.id} Return Reason ID`, + description: `The return reason for item ${item.id}`, + options: async () => { + const { data: returnReasons } = await this.returnless.listReturnReasons(); + return returnReasons.map(({ + id, label, + }) => ({ + value: id, + label, + })); + }, + }; + } + return props; + }, + async run({ $ }) { + const { data: order } = await this.returnless.getOrder({ + $, + orderId: this.orderId, + }); + + const { data: intent } = await this.returnless.createReturnOrderIntent({ + $, + data: { + form_id: this.formId, + locale: this.locale, + input: this.input, + order_number: order.order_number, + }, + }); + + const { data: returnOrder } = await this.returnless.createReturnOrder({ + $, + data: { + return_order_intent_id: intent.id, + customer: { + house_number: this.customerHouseNumber, + street: this.customerStreet, + postal_code: this.customerPostalCode, + city: this.customerCity, + country_id: this.customerCountryId, + }, + items: this.itemIds.map((itemId) => ({ + id: itemId, + quantity: this[`item${itemId}Quantity`], + return_reason_id: this[`item${itemId}ReturnReasonId`], + })), + metadata: parseObject(this.metadata), + }, + }); + + $.export("$summary", `Return order created: ${returnOrder.id}`); + return returnOrder; + }, +}; diff --git a/components/returnless/actions/list-return-orders/list-return-orders.mjs b/components/returnless/actions/list-return-orders/list-return-orders.mjs new file mode 100644 index 0000000000000..51c81a8667994 --- /dev/null +++ b/components/returnless/actions/list-return-orders/list-return-orders.mjs @@ -0,0 +1,63 @@ +import returnless from "../../returnless.app.mjs"; + +export default { + key: "returnless-list-return-orders", + name: "List Return Orders", + description: "Retrieve a list of return orders. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/0640e3c064cdc-list-all-return-orders)", + version: "0.0.1", + type: "action", + props: { + returnless, + returnType: { + type: "string", + label: "Return Type", + description: "The type of return orders to retrieve", + options: [ + "request", + "return", + ], + }, + createdAfter: { + type: "string", + label: "Created After", + description: "Only return return-orders that were created after the given date", + optional: true, + }, + createdBefore: { + type: "string", + label: "Created Before", + description: "Only return return-orders that were created before the given date", + optional: true, + }, + maxResults: { + propDefinition: [ + returnless, + "maxResults", + ], + }, + }, + async run({ $ }) { + const returnOrders = await this.returnless.getPaginatedResources({ + fn: this.returnless.listReturnOrders, + args: { + $, + params: { + filter: { + return_type: this.returnType, + created_at: { + gt: this.createdAfter, + lt: this.createdBefore, + }, + }, + sort: "-created_at", + }, + }, + max: this.maxResults, + }); + + $.export("$summary", `Found ${returnOrders.length} return order${returnOrders.length === 1 + ? "" + : "s"}`); + return returnOrders; + }, +}; diff --git a/components/returnless/actions/list-sales-orders/list-sales-orders.mjs b/components/returnless/actions/list-sales-orders/list-sales-orders.mjs new file mode 100644 index 0000000000000..46a6b2b247656 --- /dev/null +++ b/components/returnless/actions/list-sales-orders/list-sales-orders.mjs @@ -0,0 +1,32 @@ +import returnless from "../../returnless.app.mjs"; + +export default { + key: "returnless-list-sales-orders", + name: "List Sales Orders", + description: "Retrieve a list of sales orders sorted by creation date, with the most recent sales orders appearing first. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/ce6a0e3d66378-list-all-sales-orders)", + version: "0.0.1", + type: "action", + props: { + returnless, + maxResults: { + propDefinition: [ + returnless, + "maxResults", + ], + }, + }, + async run({ $ }) { + const salesOrders = await this.returnless.getPaginatedResources({ + fn: this.returnless.listSalesOrders, + args: { + $, + }, + max: this.maxResults, + }); + + $.export("$summary", `Found ${salesOrders.length} sales order${salesOrders.length === 1 + ? "" + : "s"}`); + return salesOrders; + }, +}; diff --git a/components/returnless/actions/update-return-order-status/update-return-order-status.mjs b/components/returnless/actions/update-return-order-status/update-return-order-status.mjs new file mode 100644 index 0000000000000..1fa0a33d9753a --- /dev/null +++ b/components/returnless/actions/update-return-order-status/update-return-order-status.mjs @@ -0,0 +1,36 @@ +import returnless from "../../returnless.app.mjs"; + +export default { + key: "returnless-update-return-order-status", + name: "Update Return Order Status", + description: "Update the status of a return order. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/1d07e272437a4-update-a-return-order-status)", + version: "0.0.1", + type: "action", + props: { + returnless, + returnOrderId: { + propDefinition: [ + returnless, + "returnOrderId", + ], + }, + returnStatusId: { + propDefinition: [ + returnless, + "returnStatusId", + ], + }, + }, + async run({ $ }) { + const { data } = await this.returnless.updateReturnOrderStatus({ + $, + returnOrderId: this.returnOrderId, + data: { + status_id: this.returnStatusId, + }, + }); + + $.export("$summary", `Return Order Status Updated: ${data.id}`); + return data; + }, +}; diff --git a/components/returnless/common/utils.mjs b/components/returnless/common/utils.mjs new file mode 100644 index 0000000000000..4dab12cb93153 --- /dev/null +++ b/components/returnless/common/utils.mjs @@ -0,0 +1,27 @@ +export const parseObject = (obj) => { + if (!obj) { + return undefined; + } + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + if (Array.isArray(obj)) { + return obj.map(parseObject); + } + if (typeof obj === "object") { + return Object.fromEntries( + Object.entries(obj).map(([ + key, + value, + ]) => [ + key, + parseObject(value), + ]), + ); + } + return obj; +}; diff --git a/components/returnless/package.json b/components/returnless/package.json index b7c4bc783f0cc..1a004790bb789 100644 --- a/components/returnless/package.json +++ b/components/returnless/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/returnless", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Returnless Components", "main": "returnless.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0" } -} \ No newline at end of file +} diff --git a/components/returnless/returnless.app.mjs b/components/returnless/returnless.app.mjs index 0b1c640130083..742cada04e62a 100644 --- a/components/returnless/returnless.app.mjs +++ b/components/returnless/returnless.app.mjs @@ -1,11 +1,306 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "returnless", - propDefinitions: {}, + propDefinitions: { + returnOrderId: { + type: "string", + label: "Return Order ID", + description: "The ID of the return order to update", + async options({ prevContext }) { + const { + data, meta, + } = await this.listReturnOrders({ + params: { + cursor: prevContext?.cursor, + }, + }); + return { + options: data.map(({ + id: value, return_number: number, + }) => ({ + value, + label: `Return Number: ${number}`, + })) || [], + context: { + cursor: meta.next_cursor, + }, + }; + }, + }, + formId: { + type: "string", + label: "Form ID", + description: "The ID of the form to use for the return order", + async options({ prevContext }) { + const { + data, meta, + } = await this.listForms({ + params: { + cursor: prevContext?.cursor, + }, + }); + return { + options: data.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || [], + context: { + cursor: meta.next_cursor, + }, + }; + }, + }, + orderId: { + type: "string", + label: "Order ID", + description: "The ID of the sales order to use for the return order", + async options({ prevContext }) { + const { + data, meta, + } = await this.listSalesOrders({ + params: { + cursor: prevContext?.cursor, + }, + }); + return { + options: data.map(({ + id: value, order_number: number, + }) => ({ + value, + label: `Order Number: ${number}`, + })) || [], + context: { + cursor: meta.next_cursor, + }, + }; + }, + }, + countryId: { + type: "string", + label: "Country ID", + description: "The ID of the country to use for the return order", + async options({ prevContext }) { + const { + data, meta, + } = await this.listCountries({ + params: { + cursor: prevContext?.cursor, + }, + }); + return { + options: data.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || [], + context: { + cursor: meta.next_cursor, + }, + }; + }, + }, + itemIds: { + type: "string[]", + label: "Item IDs", + description: "The IDs of the items in the sales order to return", + async options({ + prevContext, orderId, + }) { + const { + data, meta, + } = await this.listSalesOrderItems({ + orderId, + params: { + cursor: prevContext?.cursor, + }, + }); + return { + options: data.map(({ id }) => id) || [], + context: { + cursor: meta.next_cursor, + }, + }; + }, + }, + returnStatusId: { + type: "string", + label: "Return Status ID", + description: "The ID of the return status to use for the return order", + async options({ prevContext }) { + const { + data, meta, + } = await this.listReturnStatuses({ + params: { + cursor: prevContext?.cursor, + }, + }); + return { + options: data.map(({ + id: value, label, + }) => ({ + value, + label, + })) || [], + context: { + cursor: meta.next_cursor, + }, + }; + }, + }, + maxResults: { + type: "integer", + label: "Max Results", + description: "The maximum number of results to return", + default: 100, + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api-v2.returnless.com/2025-01"; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: { + "Authorization": `Bearer ${this.$auth.api_key}`, + "Content-Type": "application/json", + }, + ...opts, + }); + }, + createWebhook(opts = {}) { + return this._makeRequest({ + path: "/webhook-subscriptions", + method: "POST", + ...opts, + }); + }, + deleteWebhook({ + hookId, ...opts + }) { + return this._makeRequest({ + path: `/webhook-subscriptions/${hookId}`, + method: "DELETE", + ...opts, + }); + }, + getOrder({ + orderId, ...opts + }) { + return this._makeRequest({ + path: `/sales-orders/${orderId}`, + ...opts, + }); + }, + listCountries(opts = {}) { + return this._makeRequest({ + path: "/countries", + ...opts, + }); + }, + listForms(opts = {}) { + return this._makeRequest({ + path: "/forms", + ...opts, + }); + }, + listReturnOrders(opts = {}) { + return this._makeRequest({ + path: "/return-orders", + ...opts, + }); + }, + listSalesOrders(opts = {}) { + return this._makeRequest({ + path: "/sales-orders", + ...opts, + }); + }, + listSalesOrderItems({ + orderId, ...opts + }) { + return this._makeRequest({ + path: `/sales-orders/${orderId}/items`, + ...opts, + }); + }, + listReturnStatuses(opts = {}) { + return this._makeRequest({ + path: "/return-statuses", + ...opts, + }); + }, + listReturnReasons(opts = {}) { + return this._makeRequest({ + path: "/return-reasons", + ...opts, + }); + }, + createReturnOrderIntent(opts = {}) { + return this._makeRequest({ + path: "/return-order-intents", + method: "POST", + ...opts, + }); + }, + createReturnOrder(opts = {}) { + return this._makeRequest({ + path: "/return-orders", + method: "POST", + ...opts, + }); + }, + updateReturnOrderStatus({ + returnOrderId, ...opts + }) { + return this._makeRequest({ + path: `/return-orders/${returnOrderId}/status`, + method: "PATCH", + ...opts, + }); + }, + async *paginate({ + fn, args, max, + }) { + args = { + ...args, + params: { + ...args?.params, + per_page: 100, + }, + }; + let cursor, count = 0; + do { + const { + data, meta, + } = await fn(args); + if (!data?.length) { + return; + } + for (const item of data) { + yield item; + if (max && ++count >= max) { + return; + } + } + cursor = meta.next_cursor; + args.params.cursor = cursor; + } while (cursor); + }, + async getPaginatedResources(opts) { + const resources = []; + for await (const resource of this.paginate(opts)) { + resources.push(resource); + } + return resources; }, }, -}; \ No newline at end of file +}; diff --git a/components/returnless/sources/common/base.mjs b/components/returnless/sources/common/base.mjs new file mode 100644 index 0000000000000..fbc9dfb0af8d9 --- /dev/null +++ b/components/returnless/sources/common/base.mjs @@ -0,0 +1,72 @@ +import returnless from "../../returnless.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + props: { + returnless, + db: "$.service.db", + http: { + type: "$.interface.http", + customResponse: true, + }, + description: { + type: "string", + label: "Description", + description: "The description of the webhook", + }, + }, + hooks: { + async activate() { + const { data: { id } } = await this.returnless.createWebhook({ + data: { + endpoint: this.http.endpoint, + description: this.description, + is_enabled: true, + events: this.getEvents(), + }, + }); + this._setHookId(id); + }, + async deactivate() { + const hookId = this._getHookId(); + if (hookId) { + await this.returnless.deleteWebhook({ + hookId, + }); + } + }, + }, + methods: { + _getHookId() { + return this.db.get("hookId"); + }, + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + generateMeta(data) { + return { + id: data.id, + summary: this.getSummary(data), + ts: Date.now(), + }; + }, + getEvents() { + throw new ConfigurationError("getEvents is not implemented"); + }, + getSummary() { + throw new ConfigurationError("getSummary is not implemented"); + }, + }, + async run({ body }) { + this.http.respond({ + status: 200, + }); + + if (!body?.data) { + return; + } + + const meta = this.generateMeta(body.data); + this.$emit(body.data, meta); + }, +}; diff --git a/components/returnless/sources/new-return-created/new-return-created.mjs b/components/returnless/sources/new-return-created/new-return-created.mjs new file mode 100644 index 0000000000000..a54aaa1ed0367 --- /dev/null +++ b/components/returnless/sources/new-return-created/new-return-created.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "returnless-new-return-created", + name: "New Return Created (Instant)", + description: "Emit new event when a return is created. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/fd4ad9c27648b-creates-a-webhook-subscriptions)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "return.created", + ]; + }, + getSummary(data) { + return `New Return Created: ${data.id}`; + }, + }, +}; diff --git a/components/returnless/sources/return-notes-added/return-notes-added.mjs b/components/returnless/sources/return-notes-added/return-notes-added.mjs new file mode 100644 index 0000000000000..21c7c3d680ffc --- /dev/null +++ b/components/returnless/sources/return-notes-added/return-notes-added.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "returnless-return-notes-added", + name: "Return Notes Added (Instant)", + description: "Emit new event when a return note is added. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/fd4ad9c27648b-creates-a-webhook-subscriptions)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "return.notes.added", + ]; + }, + getSummary(data) { + return `Return Notes Added to Return: ${data.id}`; + }, + }, +}; diff --git a/components/returnless/sources/return-product-marked-received/return-product-marked-received.mjs b/components/returnless/sources/return-product-marked-received/return-product-marked-received.mjs new file mode 100644 index 0000000000000..edc71205b1f19 --- /dev/null +++ b/components/returnless/sources/return-product-marked-received/return-product-marked-received.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "returnless-return-product-marked-received", + name: "Return Product Marked Received (Instant)", + description: "Emit new event when a return product is marked as received. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/fd4ad9c27648b-creates-a-webhook-subscriptions)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "return.product.marked_as_received", + ]; + }, + getSummary(data) { + return `Product Marked as Received in Return: ${data.id}`; + }, + }, +}; diff --git a/components/returnless/sources/return-status-changed/return-status-changed.mjs b/components/returnless/sources/return-status-changed/return-status-changed.mjs new file mode 100644 index 0000000000000..229893f484a93 --- /dev/null +++ b/components/returnless/sources/return-status-changed/return-status-changed.mjs @@ -0,0 +1,22 @@ +import common from "../common/base.mjs"; + +export default { + ...common, + key: "returnless-return-status-changed", + name: "Return Status Changed (Instant)", + description: "Emit new event when a return status is changed. [See the documentation](https://docs.returnless.com/docs/api-rest-reference/fd4ad9c27648b-creates-a-webhook-subscriptions)", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEvents() { + return [ + "return.status_changed", + ]; + }, + getSummary(data) { + return `Status Changed for Return: ${data.id}`; + }, + }, +}; From 662e77561b4cde639aad3e83e5909f7a9b9c47ae Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Tue, 15 Jul 2025 11:46:04 -0400 Subject: [PATCH 2/3] pnpm-lock.yaml --- pnpm-lock.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5db50fe9d680..982469a0b5df7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1868,8 +1868,7 @@ importers: specifier: ^3.0.0 version: 3.0.3 - components/bright_data: - specifiers: {} + components/bright_data: {} components/brilliant_directories: dependencies: @@ -11386,7 +11385,11 @@ importers: specifier: ^1.5.1 version: 1.6.6 - components/returnless: {} + components/returnless: + dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 components/returnly: dependencies: From 470a8210180b92df561da186d866e539ebb7d35e Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Wed, 16 Jul 2025 14:23:44 -0400 Subject: [PATCH 3/3] updates --- .../create-return-order.mjs | 18 ++++++-- components/returnless/returnless.app.mjs | 46 +++++++++++-------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/components/returnless/actions/create-return-order/create-return-order.mjs b/components/returnless/actions/create-return-order/create-return-order.mjs index f4464b850c151..2804a126567a6 100644 --- a/components/returnless/actions/create-return-order/create-return-order.mjs +++ b/components/returnless/actions/create-return-order/create-return-order.mjs @@ -1,5 +1,6 @@ import returnless from "../../returnless.app.mjs"; import { parseObject } from "../../common/utils.mjs"; +import { ConfigurationError } from "@pipedream/platform"; export default { key: "returnless-create-return-order", @@ -16,9 +17,13 @@ export default { ], }, locale: { - type: "string", - label: "Locale", - description: "The locale of the form to create the return-order intent for", + propDefinition: [ + returnless, + "locale", + (c) => ({ + formId: c.formId, + }), + ], }, input: { type: "string", @@ -84,7 +89,7 @@ export default { }); for (const item of items) { props[`item${item.id}Quantity`] = { - type: "string", + type: "integer", label: `Item ${item.id} Quantity`, description: `The quantity of item ${item.id} to return`, }; @@ -120,6 +125,9 @@ export default { order_number: order.order_number, }, }); + if (intent.status === "failed") { + throw new ConfigurationError(intent.status_message); + } const { data: returnOrder } = await this.returnless.createReturnOrder({ $, @@ -128,7 +136,7 @@ export default { customer: { house_number: this.customerHouseNumber, street: this.customerStreet, - postal_code: this.customerPostalCode, + postcode: this.customerPostalCode, city: this.customerCity, country_id: this.customerCountryId, }, diff --git a/components/returnless/returnless.app.mjs b/components/returnless/returnless.app.mjs index 742cada04e62a..c7eabda076dcd 100644 --- a/components/returnless/returnless.app.mjs +++ b/components/returnless/returnless.app.mjs @@ -83,25 +83,14 @@ export default { type: "string", label: "Country ID", description: "The ID of the country to use for the return order", - async options({ prevContext }) { - const { - data, meta, - } = await this.listCountries({ - params: { - cursor: prevContext?.cursor, - }, - }); - return { - options: data.map(({ - id: value, name: label, - }) => ({ - value, - label, - })) || [], - context: { - cursor: meta.next_cursor, - }, - }; + async options() { + const { data } = await this.listCountries(); + return data.map(({ + id: value, name: label, + }) => ({ + value, + label, + })) || []; }, }, itemIds: { @@ -152,6 +141,17 @@ export default { }; }, }, + locale: { + type: "string", + label: "Locale", + description: "The locale of the form to use for the return order", + async options({ formId }) { + const { data } = await this.getForm({ + formId, + }); + return data.locales.map(({ locale }) => locale); + }, + }, maxResults: { type: "integer", label: "Max Results", @@ -200,6 +200,14 @@ export default { ...opts, }); }, + getForm({ + formId, ...opts + }) { + return this._makeRequest({ + path: `/forms/${formId}`, + ...opts, + }); + }, listCountries(opts = {}) { return this._makeRequest({ path: "/countries",