-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[Components] Mews #17998
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] Mews #17998
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 3 Skipped Deployments
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (17)
WalkthroughAdds a full Mews integration: an API client app, pagination helper, actions for create/update/cancel/fetch resources, a recursive JSON parse utility, a polling base, and multiple polling sources for reservations, order items, and product service orders. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Action
participant MewsApp
participant MewsAPI
User->>Action: Trigger action (create/update/cancel/fetch)
Action->>MewsApp: Call method (e.g., reservationsCreate/reservationsUpdate/reservationsCancel/reservationsGetAll)
MewsApp->>MewsAPI: POST /api/connector/v1/... (with auth merged)
MewsAPI-->>MewsApp: API response
MewsApp-->>Action: Return response
Action-->>User: Output summary and data
sequenceDiagram
participant PollingSource
participant MewsApp
participant MewsAPI
participant EventBus
PollingSource->>MewsApp: paginate(requester=reservationsGetAll/orderItemsGetAll/...)
MewsApp->>MewsAPI: POST /api/connector/v1/.../getAll (with Cursor, Count)
MewsAPI-->>MewsApp: Paged response (resultKey)
MewsApp-->>PollingSource: Return aggregated items
PollingSource->>EventBus: Emit items with generated meta
PollingSource-->>MewsApp: Update last poll timestamp
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Assessment against linked issues
Poem
Tip You can validate your CodeRabbit configuration file in your editor.If your editor has YAML language server, you can enable auto-completion and validation by adding ✨ Finishing Touches
🧪 Generate unit tests
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:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
1e2ebe1
to
7d11b65
Compare
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: 12
♻️ Duplicate comments (2)
components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
2-2
: Import path inherits the “uilts” typoEvery action imports
../../common/uilts.mjs
. If the utility file is renamed, remember to update these paths to avoid runtime failures.components/mews/actions/fetch-products/fetch-products.mjs (1)
2-2
: Import path inherits the “uilts” typoSame observation as in
fetch-reservations.mjs
.
🧹 Nitpick comments (25)
components/mews/common/uilts.mjs (2)
1-1
: File name typo will confuse future maintainers
uilts.mjs
looks like a misspelling of “utils”. Every import must now repeat the typo, making the mistake contagious across the codebase. Consider renaming the file (and fixing all imports) before this spreads further.
15-16
: Cycle-detection reset on nested JSON parseCalling
parseJson(JSON.parse(value), …)
re-creates a freshWeakSet
, so objects produced by parsing nested JSON strings won’t be tracked for cycles seen earlier. Re-enter with the sameseen
set (e.g. callparse(...)
instead) to keep cycle detection consistent.components/mews/package.json (1)
3-3
: Version bump without changelogJumping to
0.7.0
is fine, but please document breaking / new features inCHANGELOG.md
to keep consumers informed.components/mews/actions/fetch-reservations/fetch-reservations.mjs (2)
25-33
: Guard against emptyadditionalFields
When the prop is left blank it will be
undefined
, which the Mews API might reject. Safer to default to{}
:- data: utils.parseJson(additionalFields), + data: utils.parseJson(additionalFields) || {},
34-35
: Minor wording tweak in summary
Successfully fetched … reservations
is good, but follow the repo learning: use retrieved instead of fetched for consistency with other components.components/mews/actions/fetch-products/fetch-products.mjs (2)
25-32
: DefaultadditionalFields
to empty objectSame defensive default recommended for reservations action.
33-33
: Align summary wordingConsider “Successfully retrieved … products” for consistency.
components/mews/actions/cancel-reservation/cancel-reservation.mjs (2)
4-4
: Action name implies single cancel but accepts manySince the input is an array, rename to “Cancel Reservations” or update the description to clarify that multiple IDs are supported.
28-28
: Summary wording consistencyUse “Cancelled ${n} reservations” (plural) to match earlier naming suggestion.
components/mews/actions/create-reservation/create-reservation.mjs (2)
29-29
: Align summary message with component guidelinesUse the “Successfully …” phrasing for consistency with prior learnings.
- $.export("summary", `Created ${reservations.length} reservation(s)`); + $.export("summary", `Successfully created ${reservations.length} reservation(s)`);
5-5
: Add API docs link for quicker discoverabilityIncluding the Mews docs link helps users format payloads correctly.
- description: "Create a reservation in Mews.", + description: "Create a reservation in Mews. See API docs: https://mews-systems.gitbook.io/connector-api/operations/reservations#create-reservation",components/mews/sources/order-item-created/order-item-created.mjs (1)
6-6
: Include API docs link in descriptionSpeeds up configuration and troubleshooting.
- description: "Emit new order items as they are created (polling)", + description: "Emit new order items as they are created (polling). Docs: https://mews-systems.gitbook.io/connector-api/operations/order-items#get-all-order-items",components/mews/actions/update-reservation/update-reservation.mjs (2)
29-29
: Align summary message with prior guideline- $.export("summary", `Updated ${reservations.length} reservation(s)`); + $.export("summary", `Successfully updated ${reservations.length} reservation(s)`);
5-5
: Add API docs link to the description- description: "Update an existing reservation in Mews.", + description: "Update an existing reservation in Mews. See API docs: https://mews-systems.gitbook.io/connector-api/operations/reservations#update-reservation",components/mews/actions/fetch-customers/fetch-customers.mjs (2)
21-23
: Avoid shadowing the importedapp
symbol for clarityUse a different local name (e.g.,
mews
) to avoid confusion with the top-level import and to match patterns in sibling actions.- const { - app, - additionalFields, - } = this; + const { + app: mews, + additionalFields, + } = this; - const items = await app.paginate({ - requester: app.customersGetAll, + const items = await mews.paginate({ + requester: mews.customersGetAll, requesterArgs: { $, - data: utils.parseJson(additionalFields), + data: utils.parseJson(additionalFields), }, resultKey: "Customers", });Also applies to: 25-33
33-33
: Minor: align summary wording with prior conventions“Retrieved” is the phrasing used in prior learnings. Optional.
- $.export("summary", `Successfully fetched ${items.length} customers`); + $.export("summary", `Successfully retrieved ${items.length} customers`);components/mews/sources/product-service-order-created/product-service-order-created.mjs (1)
6-6
: Add API docs link in descriptionHelps users understand filters and payload shape.
- description: "Emit new product service orders as they are created (polling)", + description: "Emit new product service orders as they are created (polling). Docs: https://mews-systems.gitbook.io/connector-api/operations/product-service-orders#get-all-product-service-orders",components/mews/sources/reservation-updated/reservation-updated.mjs (1)
6-7
: Clarify description (avoid “new” for updates).Recommend: “Emit an event when a reservation is updated (polling)”.
- description: "Emit new reservations as they are updated (polling)", + description: "Emit an event when a reservation is updated (polling)",components/mews/sources/order-item-updated/order-item-updated.mjs (1)
6-7
: Tighten description (avoid “new”).Recommend: “Emit an event when an order item is updated (polling)”.
- description: "Emit new order items as they are updated (polling)", + description: "Emit an event when an order item is updated (polling)",components/mews/sources/reservation-cancelled/reservation-cancelled.mjs (1)
5-7
: Align spelling and phrasing; avoid “new” for cancellations.To match the API fields (CanceledUtc, “Canceled”), and for consistency/searchability, consider US spelling and clearer description.
- name: "Reservation Cancelled", - description: "Emit new reservations as they are cancelled (polling)", - key: "mews-reservation-cancelled", + name: "Reservation Canceled", + description: "Emit an event when a reservation is canceled (polling)", + key: "mews-reservation-canceled",If this source is already public, renaming the key is breaking. If not yet released, this improves consistency.
components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
10-18
: Optional: expose maxRequests or query props for large datasets.To give users control over API volume / rate limits, consider adding an optional
maxRequests
prop passed topaginate
, mirroring any limit prop patterns used elsewhere.props: { app, additionalFields: { propDefinition: [ app, "additionalFields", ], }, + maxRequests: { + type: "integer", + label: "Max Requests", + description: "Limit the number of paginated API calls (helps manage rate limits and execution time).", + optional: true, + default: 0, // 0 or undefined => no explicit cap, defer to app default + }, }, async run({ $ }) { const { app, additionalFields, + maxRequests, } = this; const items = await app.paginate({ requester: app.orderItemsGetAll, requesterArgs: { $, data: utils.parseJson(additionalFields), }, resultKey: "OrderItems", + ...(maxRequests ? { maxRequests } : {}), });components/mews/sources/common/polling.mjs (2)
120-122
: Prefer numeric timestamp comparison for clarity and robustnessComparing ISO strings works if formats are uniform, but numeric comparisons avoid subtle issues. Parse once and compare numbers.
- const tsStr = resource?.[getDateField()] || new Date().toISOString(); - - if (tsStr > maxTs) { - maxTs = tsStr; - } + const tsStr = resource?.[getDateField()] || new Date().toISOString(); + if (Date.parse(tsStr) > Date.parse(maxTs)) { + maxTs = tsStr; + }
58-63
: Make pagination depth configurable (default of 3 is likely too low)A default of 3 pages can be insufficient during initial deploys or bursts of activity. Expose this as a prop or raise the default to reduce the chance of truncation.
- getMaxRequests() { - return 3; - }, + getMaxRequests() { + return 10; // consider making this configurable via a prop + },components/mews/mews.app.mjs (2)
46-51
: Set JSON Content-Type header by defaultMews endpoints expect JSON POST bodies. Being explicit improves interoperability and edge case handling.
return axios($, { method: "POST", url: this.getUrl(path), data: this.getAuthData(data), + headers: { + "content-type": "application/json", + }, ...args, });
101-139
: Consider exposing pagination metadata (cursor) to callersCurrently
paginate
only returns an array of items. For sources that need to avoid event loss under truncation, it helps to know whether pagination was exhausted. Consider an optional mode returning{ items, nextCursor }
or a generator.Example (non-breaking, optional flag):
- async paginate({ + async paginate({ requester, requesterArgs = {}, resultKey, count = 100, maxRequests = 3, - } = {}) { + returnCursor = false, + } = {}) { const items = []; let next; let requestCount = 0; while (true) { if (requestCount >= maxRequests) { break; } - const response = await requester({ + const response = await requester.call(this, { ...requesterArgs, data: { ...requesterArgs?.data, Limitation: { Cursor: next, Count: count, }, }, }); items.push(...(response?.[resultKey] || [])); next = response?.Limitation?.Cursor ?? null; requestCount += 1; if (!next) { break; } } - return items; + return returnCursor ? { items, nextCursor: next } : items; },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
components/mews/actions/cancel-reservation/cancel-reservation.mjs
(1 hunks)components/mews/actions/create-reservation/create-reservation.mjs
(1 hunks)components/mews/actions/fetch-customers/fetch-customers.mjs
(1 hunks)components/mews/actions/fetch-order-items/fetch-order-items.mjs
(1 hunks)components/mews/actions/fetch-products/fetch-products.mjs
(1 hunks)components/mews/actions/fetch-reservations/fetch-reservations.mjs
(1 hunks)components/mews/actions/update-reservation/update-reservation.mjs
(1 hunks)components/mews/common/uilts.mjs
(1 hunks)components/mews/mews.app.mjs
(1 hunks)components/mews/package.json
(2 hunks)components/mews/sources/common/polling.mjs
(1 hunks)components/mews/sources/order-item-created/order-item-created.mjs
(1 hunks)components/mews/sources/order-item-updated/order-item-updated.mjs
(1 hunks)components/mews/sources/product-service-order-created/product-service-order-created.mjs
(1 hunks)components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
(1 hunks)components/mews/sources/reservation-created/reservation-created.mjs
(1 hunks)components/mews/sources/reservation-updated/reservation-updated.mjs
(1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2024-12-12T19:23:09.039Z
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14935
File: components/sailpoint/package.json:15-18
Timestamp: 2024-12-12T19:23:09.039Z
Learning: When developing Pipedream components, do not add built-in Node.js modules like `fs` to `package.json` dependencies, as they are native modules provided by the Node.js runtime.
Applied to files:
components/mews/package.json
📚 Learning: 2024-10-30T15:24:39.294Z
Learnt from: jcortes
PR: PipedreamHQ/pipedream#14467
File: components/gainsight_px/actions/create-account/create-account.mjs:4-6
Timestamp: 2024-10-30T15:24:39.294Z
Learning: In `components/gainsight_px/actions/create-account/create-account.mjs`, the action name should be "Create Account" instead of "Create Memory".
Applied to files:
components/mews/actions/fetch-reservations/fetch-reservations.mjs
components/mews/actions/fetch-products/fetch-products.mjs
components/mews/actions/create-reservation/create-reservation.mjs
components/mews/actions/fetch-customers/fetch-customers.mjs
components/mews/actions/update-reservation/update-reservation.mjs
📚 Learning: 2024-10-08T15:33:38.240Z
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`.
Applied to files:
components/mews/actions/fetch-reservations/fetch-reservations.mjs
components/mews/actions/fetch-products/fetch-products.mjs
components/mews/actions/create-reservation/create-reservation.mjs
components/mews/actions/fetch-customers/fetch-customers.mjs
components/mews/actions/update-reservation/update-reservation.mjs
📚 Learning: 2025-01-23T03:55:15.166Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#15376
File: components/monday/sources/name-updated/name-updated.mjs:6-6
Timestamp: 2025-01-23T03:55:15.166Z
Learning: Source names in Monday.com components don't need to start with "New" if they emit events for updated items (e.g., "Name Updated", "Column Value Updated") rather than new items. This follows the component guidelines exception where the "New" prefix is only required when emits are limited to new items.
Applied to files:
components/mews/sources/product-service-order-created/product-service-order-created.mjs
components/mews/sources/order-item-updated/order-item-updated.mjs
components/mews/sources/reservation-created/reservation-created.mjs
components/mews/sources/reservation-updated/reservation-updated.mjs
components/mews/sources/order-item-created/order-item-created.mjs
components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
📚 Learning: 2024-10-10T19:18:27.998Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#14265
File: components/the_magic_drip/sources/common.mjs:35-43
Timestamp: 2024-10-10T19:18:27.998Z
Learning: In `components/the_magic_drip/sources/common.mjs`, when processing items in `getAndProcessData`, `savedIds` is intentionally updated with IDs of both emitted and non-emitted items to avoid emitting retroactive events upon first deployment and ensure only new events are emitted as they occur.
Applied to files:
components/mews/sources/product-service-order-created/product-service-order-created.mjs
components/mews/sources/order-item-updated/order-item-updated.mjs
components/mews/sources/reservation-created/reservation-created.mjs
components/mews/sources/reservation-updated/reservation-updated.mjs
components/mews/sources/order-item-created/order-item-created.mjs
components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
components/mews/sources/common/polling.mjs
📚 Learning: 2024-10-08T15:33:38.240Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common-webhook-methods.mjs:1-71
Timestamp: 2024-10-08T15:33:38.240Z
Learning: The `common-webhook-methods.mjs` object is designed to be extended, similar to an abstract class, and intentionally does not implement certain methods like `generateWebhookMeta` and `getEventType` to enforce implementation in subclasses.
Applied to files:
components/mews/sources/product-service-order-created/product-service-order-created.mjs
components/mews/sources/order-item-updated/order-item-updated.mjs
components/mews/sources/reservation-created/reservation-created.mjs
components/mews/sources/reservation-updated/reservation-updated.mjs
components/mews/mews.app.mjs
components/mews/sources/order-item-created/order-item-created.mjs
components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
components/mews/sources/common/polling.mjs
📚 Learning: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.
Applied to files:
components/mews/mews.app.mjs
📚 Learning: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: The Salesloft API list endpoints (listPeople, listCadences, listUsers, listAccounts) return arrays directly in the response body, not wrapped in a metadata object with a nested data property. The _makeRequest method correctly returns response.data which contains the arrays that can be mapped over directly in propDefinitions.
Applied to files:
components/mews/mews.app.mjs
📚 Learning: 2024-07-24T02:05:59.531Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#12697
File: components/salesforce_rest_api/sources/common.mjs:97-98
Timestamp: 2024-07-24T02:05:59.531Z
Learning: The `processTimerEvent` method in the `components/salesforce_rest_api/sources/common.mjs` file is intentionally left unimplemented to enforce that subclasses must implement this method, similar to an abstract class in object-oriented programming.
Applied to files:
components/mews/sources/order-item-created/order-item-created.mjs
components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
components/mews/sources/common/polling.mjs
🧬 Code Graph Analysis (8)
components/mews/actions/fetch-reservations/fetch-reservations.mjs (4)
components/mews/actions/fetch-customers/fetch-customers.mjs (1)
items
(25-32)components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
items
(25-32)components/mews/actions/fetch-products/fetch-products.mjs (1)
items
(25-32)components/mews/sources/common/polling.mjs (1)
items
(97-109)
components/mews/actions/fetch-products/fetch-products.mjs (4)
components/mews/actions/fetch-customers/fetch-customers.mjs (1)
items
(25-32)components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
items
(25-32)components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
items
(25-32)components/mews/sources/common/polling.mjs (1)
items
(97-109)
components/mews/actions/create-reservation/create-reservation.mjs (3)
components/mews/actions/cancel-reservation/cancel-reservation.mjs (3)
mews
(18-20)data
(21-23)response
(24-27)components/mews/actions/update-reservation/update-reservation.mjs (4)
mews
(18-18)reservations
(19-21)data
(22-24)response
(25-28)components/mews/mews.app.mjs (1)
response
(117-126)
components/mews/actions/fetch-order-items/fetch-order-items.mjs (4)
components/mews/actions/fetch-customers/fetch-customers.mjs (1)
items
(25-32)components/mews/actions/fetch-products/fetch-products.mjs (1)
items
(25-32)components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
items
(25-32)components/mews/sources/common/polling.mjs (1)
items
(97-109)
components/mews/actions/cancel-reservation/cancel-reservation.mjs (2)
components/mews/actions/create-reservation/create-reservation.mjs (3)
mews
(18-18)data
(22-24)response
(25-28)components/mews/actions/update-reservation/update-reservation.mjs (3)
mews
(18-18)data
(22-24)response
(25-28)
components/mews/actions/fetch-customers/fetch-customers.mjs (4)
components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
items
(25-32)components/mews/actions/fetch-products/fetch-products.mjs (1)
items
(25-32)components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
items
(25-32)components/mews/sources/common/polling.mjs (1)
items
(97-109)
components/mews/mews.app.mjs (8)
components/mews/actions/cancel-reservation/cancel-reservation.mjs (2)
data
(21-23)response
(24-27)components/mews/actions/create-reservation/create-reservation.mjs (2)
data
(22-24)response
(25-28)components/mews/actions/update-reservation/update-reservation.mjs (2)
data
(22-24)response
(25-28)components/mews/actions/fetch-customers/fetch-customers.mjs (1)
items
(25-32)components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
items
(25-32)components/mews/actions/fetch-products/fetch-products.mjs (1)
items
(25-32)components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
items
(25-32)components/mews/sources/common/polling.mjs (1)
items
(97-109)
components/mews/sources/common/polling.mjs (1)
components/mews/mews.app.mjs (1)
items
(108-108)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
- GitHub Check: Lint Code Base
🔇 Additional comments (8)
components/mews/package.json (1)
16-16
: Confirm platform peer-compatibility
@pipedream/platform
^3.1.0
introduces breaking auth-prop changes. Verify all Mews components still compile against the new types before publishing.components/mews/sources/order-item-created/order-item-created.mjs (1)
3-31
: LGTM: Correct requester, result key, ID extraction, and date fieldsSource cleanly extends the base polling with the right endpoint, keys, and CreatedUtc for filtering.
components/mews/sources/product-service-order-created/product-service-order-created.mjs (1)
3-31
: LGTM: Correct base overrides and keysRequester, result key, ID extraction, and CreatedUtc fields look correct.
components/mews/sources/reservation-cancelled/reservation-cancelled.mjs (1)
24-35
: Sanity-check CanceledUtc + States filter.Using CanceledUtc as the date filter plus States: ["Canceled"] looks correct and should prevent false positives. LGTM.
Confirm the Mews API consistently uses "CanceledUtc" (single “l”) and the state literal "Canceled"; adjust if the API actually returns “Cancelled”.
components/mews/sources/reservation-created/reservation-created.mjs (2)
5-7
: LGTM on name and description for “created” source.Clear and consistent with guidelines for “New …” sources.
24-29
: Correct date fields for creation polling.Using CreatedUtc for both the date field and filter is appropriate here.
components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
25-32
: Good use of shared paginate + resultKey.The pagination pattern matches other actions and the resultKey aligns with the API. LGTM.
components/mews/sources/common/polling.mjs (1)
115-127
: Confirm Mews API ordering or adjust pagination logicThe current implementation advances
lastDateAt
to the maximum timestamp of the processed items on every run. If you ever hit thegetMaxRequests()
limit before consuming all pages—and if the API doesn’t guarantee ascending order by your date field—you risk skipping older items in the next execution.Please verify in the Mews Public API docs whether the following endpoints return results sorted in ascending order by your chosen date field (e.g.
CreatedAt
or whichevergetDateField()
resolves to):
- Reservations
- OrderItems
- ProductServiceOrders
If no such ordering guarantee exists, consider one of these safer approaches:
- Only call
setLastDateAt(maxTs)
after all pages have been fetched (i.e. when you know pagination is exhausted); otherwise, persist the pagination cursor (e.g. offset ornextCursor
) between runs and resume where you left off.- Make
getMaxRequests()
configurable so it can be set high enough to cover full pagination in typical use cases.- Extend
app.paginate
to return{ items, nextCursor }
, storenextCursor
in your key‐value store, and only advancelastDateAt
whennextCursor
is null.File: components/mews/sources/common/polling.mjs
Lines: 115–127
components/mews/actions/cancel-reservation/cancel-reservation.mjs
Outdated
Show resolved
Hide resolved
components/mews/actions/create-reservation/create-reservation.mjs
Outdated
Show resolved
Hide resolved
components/mews/actions/fetch-order-items/fetch-order-items.mjs
Outdated
Show resolved
Hide resolved
components/mews/actions/update-reservation/update-reservation.mjs
Outdated
Show resolved
Hide resolved
7d11b65
to
9fe177c
Compare
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: 4
♻️ Duplicate comments (3)
components/mews/mews.app.mjs (2)
176-176
: Fix incorrect endpoint path for reservationsThe endpoint includes an unintended date suffix "/2023-06-06" that should be removed to prevent 404 errors.
- path: "/reservations/getAll/2023-06-06", + path: "/reservations/getAll",
274-283
: Fix method binding issue in paginate functionThe requester function is called without binding its context, causing loss of
this
inside the method and breaking internal calls to_makeRequest
,getUrl
, andgetAuthData
.- const response = await requester({ + const response = await requester.call(this, { ...requesterArgs, data: { ...requesterArgs?.data, Limitation: { Cursor: next, Count: count, }, }, });components/mews/sources/reservation-updated/reservation-updated.mjs (1)
24-29
: Filter out newly-created reservations to prevent duplicatesUsing UpdatedUtc alone will include items where CreatedUtc === UpdatedUtc (newly-created reservations), potentially causing duplicates if both reservation-created and reservation-updated sources are used.
Consider adding filtering logic in the common polling base to support a
shouldInclude(resource)
method, then override it here to exclude newly-created items:+ shouldInclude(resource) { + const created = resource?.CreatedUtc && Date.parse(resource.CreatedUtc); + const updated = resource?.UpdatedUtc && Date.parse(resource.UpdatedUtc); + if (!updated) return false; + if (created && created === updated) return false; + return true; + },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
components/mews/actions/cancel-reservation/cancel-reservation.mjs
(1 hunks)components/mews/actions/create-reservation/create-reservation.mjs
(1 hunks)components/mews/actions/fetch-customers/fetch-customers.mjs
(1 hunks)components/mews/actions/fetch-order-items/fetch-order-items.mjs
(1 hunks)components/mews/actions/fetch-products/fetch-products.mjs
(1 hunks)components/mews/actions/fetch-reservations/fetch-reservations.mjs
(1 hunks)components/mews/actions/update-reservation/update-reservation.mjs
(1 hunks)components/mews/common/uilts.mjs
(1 hunks)components/mews/mews.app.mjs
(1 hunks)components/mews/package.json
(2 hunks)components/mews/sources/common/polling.mjs
(1 hunks)components/mews/sources/order-item-created/order-item-created.mjs
(1 hunks)components/mews/sources/order-item-updated/order-item-updated.mjs
(1 hunks)components/mews/sources/product-service-order-created/product-service-order-created.mjs
(1 hunks)components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
(1 hunks)components/mews/sources/reservation-created/reservation-created.mjs
(1 hunks)components/mews/sources/reservation-updated/reservation-updated.mjs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
- components/mews/common/uilts.mjs
- components/mews/sources/reservation-cancelled/reservation-cancelled.mjs
- components/mews/actions/fetch-products/fetch-products.mjs
- components/mews/sources/product-service-order-created/product-service-order-created.mjs
- components/mews/sources/reservation-created/reservation-created.mjs
- components/mews/actions/fetch-order-items/fetch-order-items.mjs
- components/mews/sources/order-item-updated/order-item-updated.mjs
- components/mews/package.json
- components/mews/actions/fetch-customers/fetch-customers.mjs
- components/mews/sources/common/polling.mjs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-04T17:52:05.780Z
Learnt from: GTFalcao
PR: PipedreamHQ/pipedream#16954
File: components/salesloft/salesloft.app.mjs:14-23
Timestamp: 2025-06-04T17:52:05.780Z
Learning: In the Salesloft API integration (components/salesloft/salesloft.app.mjs), the _makeRequest method returns response.data which directly contains arrays for list endpoints like listPeople, listCadences, listUsers, and listAccounts. The propDefinitions correctly call .map() directly on these responses without needing to destructure a nested data property.
Applied to files:
components/mews/mews.app.mjs
🧬 Code Graph Analysis (5)
components/mews/actions/cancel-reservation/cancel-reservation.mjs (3)
components/mews/actions/create-reservation/create-reservation.mjs (1)
response
(118-157)components/mews/actions/update-reservation/update-reservation.mjs (1)
response
(113-153)components/mews/mews.app.mjs (1)
response
(274-283)
components/mews/mews.app.mjs (8)
components/mews/actions/fetch-customers/fetch-customers.mjs (1)
items
(25-32)components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
items
(25-32)components/mews/actions/fetch-products/fetch-products.mjs (1)
items
(25-32)components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
items
(25-32)components/mews/sources/common/polling.mjs (1)
items
(97-109)components/mews/actions/cancel-reservation/cancel-reservation.mjs (1)
response
(23-30)components/mews/actions/create-reservation/create-reservation.mjs (1)
response
(118-157)components/mews/actions/update-reservation/update-reservation.mjs (1)
response
(113-153)
components/mews/actions/create-reservation/create-reservation.mjs (3)
components/mews/actions/cancel-reservation/cancel-reservation.mjs (1)
response
(23-30)components/mews/actions/update-reservation/update-reservation.mjs (1)
response
(113-153)components/mews/mews.app.mjs (1)
response
(274-283)
components/mews/actions/update-reservation/update-reservation.mjs (3)
components/mews/actions/cancel-reservation/cancel-reservation.mjs (1)
response
(23-30)components/mews/actions/create-reservation/create-reservation.mjs (1)
response
(118-157)components/mews/mews.app.mjs (1)
response
(274-283)
components/mews/actions/fetch-reservations/fetch-reservations.mjs (5)
components/mews/actions/fetch-customers/fetch-customers.mjs (1)
items
(25-32)components/mews/actions/fetch-order-items/fetch-order-items.mjs (1)
items
(25-32)components/mews/actions/fetch-products/fetch-products.mjs (1)
items
(25-32)components/mews/mews.app.mjs (1)
items
(265-265)components/mews/sources/common/polling.mjs (1)
items
(97-109)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Lint Code Base
- GitHub Check: pnpm publish
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
🔇 Additional comments (5)
components/mews/actions/fetch-reservations/fetch-reservations.mjs (1)
1-37
: LGTM! Well-structured fetch actionThe action follows consistent patterns and properly uses the app's paginate method. The implementation is clean and handles the flow correctly.
components/mews/actions/cancel-reservation/cancel-reservation.mjs (1)
1-34
: LGTM! Simple and effective cancellation actionThe action correctly handles single reservation cancellation by wrapping the ID in an array as expected by the API. The implementation is clean and follows the established patterns.
components/mews/sources/order-item-created/order-item-created.mjs (1)
1-31
: LGTM! Consistent polling source implementationThe source correctly extends the common polling base and implements all required methods. The use of "CreatedUtc" for both date field and filter field is appropriate for detecting new order items.
components/mews/actions/update-reservation/update-reservation.mjs (1)
96-156
: LGTM! Well-structured update actionThe action properly handles conditional field updates and follows consistent patterns. The use of conditional spreads for optional fields is appropriate.
components/mews/actions/create-reservation/create-reservation.mjs (1)
100-160
: LGTM! Comprehensive reservation creation actionThe action properly handles required and optional fields, uses appropriate conditional spreads, and follows established patterns. The structure is clean and well-organized.
BusinessSegmentId: businessSegmentId, | ||
}), | ||
...(additionalFields && { | ||
...utils.parseJson(additionalFields), |
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.
💡 Verification agent
🧩 Analysis chain
Verify utils.parseJson handles errors properly
Same concern as in the update action - if utils.parseJson fails silently, invalid data could be sent to the API.
🏁 Script executed:
#!/bin/bash
# Check how parseJson is used across actions
echo "Searching for parseJson usage patterns..."
rg -A 3 -B 1 "parseJson" components/mews/actions/ --type js
Length of output: 152
Let’s broaden the search to include all file types (not just “.js”) so we can locate both the definition and every usage of parseJson
:
🏁 Script executed:
#!/bin/bash
# Find definition and all references to parseJson across the entire repo
echo "Searching for parseJson occurrences in all files..."
rg -n "parseJson" .
Length of output: 15746
Let’s inspect the parseJson
implementation in components/mews/common/uilts.mjs
to see how it handles invalid JSON:
🏁 Script executed:
#!/bin/bash
# Show the parseJson implementation in the mews common utils
sed -n '1,200p' components/mews/common/uilts.mjs
Length of output: 1164
Ensure JSON parse failures aren’t silently swallowed
The parseJson
function in components/mews/common/uilts.mjs
wraps JSON.parse
in a try/catch and simply returns the raw string on failure. In your action:
- components/mews/actions/create-reservation/create-reservation.mjs:151
...utils.parseJson(additionalFields),
an invalid JSON string will be passed straight through (and even spread into the payload as individual character properties), leading to malformed API requests.
Please add explicit error handling or a safe default around this call (for example, guard against non-object returns or default to {}
), or update parseJson
so it surfaces errors instead of swallowing them silently.
Targets for your fix:
- components/mews/actions/create-reservation/create-reservation.mjs:151
- components/mews/actions/update-reservation/update-reservation.mjs:149
🤖 Prompt for AI Agents
In components/mews/actions/create-reservation/create-reservation.mjs around line
151 and components/mews/actions/update-reservation/update-reservation.mjs around
line 149, the spread of utils.parseJson(additionalFields) can silently spread a
raw string (or other non-object) when parseJson fails; update the call to
validate the parse result and guard against non-object returns by using a safe
default (e.g., const parsed = utils.parseJson(additionalFields); const safeObj =
(parsed && typeof parsed === "object" && !Array.isArray(parsed)) ? parsed : {};
then spread safeObj) or change parseJson to throw on invalid JSON and catch it
here to default to {} before spreading so malformed JSON cannot produce
character properties in the payload.
...(businessSegmentId && { | ||
BusinessSegmentId: businessSegmentId, | ||
}), | ||
...utils.parseJson(additionalFields), |
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.
💡 Verification agent
🧩 Analysis chain
Verify utils.parseJson handles errors properly
The utils.parseJson function is used without error handling. If it fails silently like suggested in past comments, invalid data could be sent to the API.
🏁 Script executed:
#!/bin/bash
# Check the implementation of parseJson utility
echo "Checking parseJson implementation..."
cat components/mews/common/uilts.mjs
Length of output: 1237
Ensure JSON parsing failures are surfaced or handled explicitly
The parseJson
utility currently swallows all JSON parse errors and returns the original value, which means malformed JSON in additionalFields
would be spread as a string (or even spread into character keys) instead of alerting or failing fast. This can lead to unintentional invalid payloads being sent to the API.
Please address this by either logging or re-throwing parse errors in the utility, or by validating the result at the call site:
– In components/mews/common/uilts.mjs (parseJson):
• Locate the catch block around JSON.parse
• Add a warning or throw to surface invalid JSON, for example:
try {
- return parseJson(JSON.parse(value), maxDepth - 1);
+ return parseJson(JSON.parse(value), maxDepth - 1);
} catch (e) {
- return value;
+ console.warn('parseJson: invalid JSON, returning original value', e);
+ // Or: throw new Error(`parseJson failed: ${e.message}`);
+ return value;
}
– In components/mews/actions/update-reservation/update-reservation.mjs (around line 149):
• Wrap the spread of utils.parseJson(additionalFields)
to verify you got an object, e.g.:
- ...utils.parseJson(additionalFields),
+ ...(() => {
+ const parsed = utils.parseJson(additionalFields);
+ if (typeof parsed !== 'object' || parsed === null) {
+ throw new Error('Invalid additionalFields payload');
+ }
+ return parsed;
+ })(),
This ensures malformed additionalFields
JSON is detected early, preventing unexpected API payloads.
📝 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.
...utils.parseJson(additionalFields), | |
// Validate that parseJson returned an object before spreading | |
...(() => { | |
const parsed = utils.parseJson(additionalFields); | |
if (typeof parsed !== 'object' || parsed === null) { | |
throw new Error('Invalid additionalFields payload'); | |
} | |
return parsed; | |
})(), |
🤖 Prompt for AI Agents
In components/mews/actions/update-reservation/update-reservation.mjs around line
149 and components/mews/common/uilts.mjs, the current parseJson swallows JSON
errors causing malformed additionalFields to be spread as strings; update
parseJson so its catch block either logs the error and re-throws (or returns
null) so failures are surfaced, and then in update-reservation replace the
direct spread of utils.parseJson(additionalFields) with a guarded flow: call
parseJson, verify the result is a plain object (throw or return a clear error if
not), and only spread when it is an object (otherwise omit or handle the invalid
payload); ensure errors include context (which field and raw value) to aid
debugging.
async options() { | ||
const reservations = await this.reservationsGetAll(); | ||
return reservations.map((reservation) => ({ | ||
label: reservation.Id, | ||
value: reservation.Id, | ||
})); | ||
}, |
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.
💡 Verification agent
🧩 Analysis chain
Verify reservations endpoint returns expected data structure
The async options function expects reservations
to be an array with Id
properties, but needs verification that the API endpoint returns data in this format.
🏁 Script executed:
#!/bin/bash
# Check if the reservationsGetAll endpoint returns the expected data structure
echo "Searching for usage patterns of reservationsGetAll response structure..."
rg -A 10 "reservationsGetAll.*response" --type js
rg -A 5 "\.map.*reservation.*Id" --type js
Length of output: 251
🏁 Script executed:
#!/bin/bash
# Locate all occurrences of reservationsGetAll (definition & usage) across the repo
echo "Searching for reservationsGetAll references..."
rg "reservationsGetAll" -n
echo "Showing context around each occurrence..."
rg -C 5 "reservationsGetAll"
Length of output: 6072
Extract the Reservations array before mapping in options
The reservationsGetAll()
call returns an object keyed by "Reservations"
, not a raw array. As written,
const reservations = await this.reservationsGetAll();
return reservations.map(r => ({ label: r.Id, value: r.Id }));
will throw because reservations
isn’t an array. Please update components/mews/mews.app.mjs
(around lines 17–23) to something like:
- const reservations = await this.reservationsGetAll();
- return reservations.map((reservation) => ({
- label: reservation.Id,
- value: reservation.Id,
- }));
+ const { Reservations } = await this.reservationsGetAll();
+ return Reservations.map((reservation) => ({
+ label: reservation.Id,
+ value: reservation.Id,
+ }));
Alternatively, you can use the paginate
helper with resultKey: "Reservations"
to flatten the list before mapping.
🤖 Prompt for AI Agents
In components/mews/mews.app.mjs around lines 17 to 23, the code assigns the
result of reservationsGetAll() to reservations then calls .map, but
reservationsGetAll() returns an object with a "Reservations" array; extract that
array first (e.g., const { Reservations } = await this.reservationsGetAll(); and
map over Reservations) or use the paginate helper with resultKey: "Reservations"
to flatten the list before mapping so you map an actual array of reservation
objects and return { label: reservation.Id, value: reservation.Id } for each
item.
async paginate({ | ||
requester, | ||
requesterArgs = {}, | ||
resultKey, | ||
count = 100, | ||
maxRequests = 3, | ||
} = {}) { | ||
const items = []; | ||
let next; | ||
let requestCount = 0; | ||
|
||
while (true) { | ||
if (requestCount >= maxRequests) { | ||
break; | ||
} | ||
|
||
const response = await requester({ | ||
...requesterArgs, | ||
data: { | ||
...requesterArgs?.data, | ||
Limitation: { | ||
Cursor: next, | ||
Count: count, | ||
}, | ||
}, | ||
}); | ||
|
||
items.push(...(response?.[resultKey] || [])); | ||
|
||
next = response?.Limitation?.Cursor ?? null; | ||
requestCount += 1; | ||
|
||
if (!next) { | ||
break; | ||
} | ||
} | ||
|
||
return items; | ||
}, |
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
Add error handling and input validation to paginate method
The paginate method lacks error handling for API failures and input validation for required parameters.
async paginate({
requester,
requesterArgs = {},
resultKey,
count = 100,
maxRequests = 3,
} = {}) {
+ if (!requester || typeof requester !== 'function') {
+ throw new Error('requester must be a function');
+ }
+ if (!resultKey || typeof resultKey !== 'string') {
+ throw new Error('resultKey must be a non-empty string');
+ }
+ if (count <= 0 || maxRequests <= 0) {
+ throw new Error('count and maxRequests must be positive integers');
+ }
+
const items = [];
let next;
let requestCount = 0;
while (true) {
if (requestCount >= maxRequests) {
break;
}
+ try {
const response = await requester.call(this, {
...requesterArgs,
data: {
...requesterArgs?.data,
Limitation: {
Cursor: next,
Count: count,
},
},
});
+ } catch (error) {
+ throw new Error(`Pagination request failed: ${error.message}`);
+ }
items.push(...(response?.[resultKey] || []));
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In components/mews/mews.app.mjs around lines 258 to 296, the paginate method
needs input validation and error handling: first validate that requester is a
function and resultKey is provided (throw a clear TypeError if not),
coerce/validate count and maxRequests to positive integers (set defaults if
invalid), and ensure requesterArgs is an object; then wrap the await
requester(...) call in a try/catch, and on error include contextual information
(requesterArgs, current Cursor, requestCount) in the logged/propagated error and
rethrow or return a rejected promise so callers can handle it; finally ensure
the loop terminates on repeated failures (increment requestCount on failure or
break) to avoid infinite loops.
9fe177c
to
2ff8179
Compare
WHY
Resolves #17448
Summary by CodeRabbit