- 
                Notifications
    
You must be signed in to change notification settings  - Fork 5.5k
 
New Components - booking_experts #18223
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
Conversation
| 
           The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
  | 
    
          
WalkthroughAdds a Booking Experts app client with axios-based requests and x-api-key auth, multiple actions (list/create/search/add-guest/get-complex-prices), a reusable polling base and three polling sources, dynamic propDefinitions, package bump/dependency, and a trivial newline formatting change in the Afosto app file. Changes
 Sequence Diagram(s)sequenceDiagram
  autonumber
  actor User
  participant Action as Pipedream Action
  participant App as BookingExperts App Client
  participant API as Booking Experts API
  User->>Action: Provide props
  Action->>App: call method (e.g., createAgendaPeriod / addGuestToReservation / listBookings)
  App->>App: _makeRequest (build URL, headers with x-api-key)
  App->>API: HTTP request
  API-->>App: HTTP response (data)
  App-->>Action: data
  Action-->>User: summary + data
    sequenceDiagram
  autonumber
  participant Source as Source (extends Base)
  participant Base as Base Polling
  participant App as BookingExperts App Client
  participant API as Booking Experts API
  participant DB as Source DB
  participant Sink as Event Emitter
  rect rgb(245,248,255)
  note right of Source: Deploy (initial sync)
  Source->>Base: deploy()
  Base->>DB: _getLastTs()
  loop pages (limit)
    Base->>App: getResourceFn(args with sort & page)
    App->>API: GET with pagination
    API-->>App: data[]
    App-->>Base: data[]
    Base->>Sink: emit item + meta (filtered by ts)
  end
  Base->>DB: _setLastTs(newTs)
  end
  rect rgb(245,255,245)
  note right of Source: Run (interval)
  Source->>Base: run()
  Base->>DB: _getLastTs()
  loop while new pages
    Base->>App: getResourceFn(next page)
    App->>API: GET
    API-->>App: data[]
    App-->>Base: data[]
    Base->>Sink: emit item + meta
  end
  Base->>DB: _setLastTs(newTs)
  end
    Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Assessment against linked issues
 Out-of-scope changes
 Poem
 📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration: 
 You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
 🚧 Files skipped from review as they are similar to previous changes (1)
 ⏰ 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)
 ✨ 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/Issue comments)Type  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: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️  Outside diff range comments (1)
components/afosto/afosto.app.mjs (1)
7-9: Remove logging of auth keys.
LeakingObject.keys(this.$auth)to logs can expose sensitive metadata. Remove or guard behind a debug flag.Apply this diff:
methods: { // this.$auth contains connected account data authKeys() { - console.log(Object.keys(this.$auth)); + if (process.env.DEBUG === "true") { + console.debug("Afosto auth keys present"); + } }, },
🧹 Nitpick comments (6)
components/booking_experts/actions/get-complex-prices/get-complex-prices.mjs (1)
3-7: Double-check endpoint shape and pagination meta.
If the endpoint returns JSON:APIlinks/meta, consider exposing them for callers that need pagination beyondpage[size]/page[number].components/booking_experts/sources/new-inventory-object-created/new-inventory-object-created.mjs (1)
33-39: Harden ts parsing and improve summaryGuard against invalid/missing dates and include a friendlier summary when a name/label exists.
- generateMeta(inventoryObject) { - return { - id: inventoryObject.id, - summary: `New inventory object created: ${inventoryObject.id}`, - ts: Date.parse(inventoryObject.attributes.created_at), - }; - }, + generateMeta(inventoryObject) { + const attrs = inventoryObject?.attributes ?? {}; + const ts = Date.parse(attrs.created_at) || Date.now(); + const title = attrs.name || attrs.label || inventoryObject.id; + return { + id: inventoryObject.id, + summary: `New inventory object created: ${title}`, + ts, + }; + },components/booking_experts/sources/booking-updated/booking-updated.mjs (1)
36-41: Harden ts parsing and make summary more helpfulProtect against missing/invalid updated_at and show human-friendly identifier if available.
- generateMeta(booking) { - return { - id: booking.id, - summary: `Booking updated: ${booking.id}`, - ts: Date.parse(booking.attributes.updated_at), - }; - }, + generateMeta(booking) { + const attrs = booking?.attributes ?? {}; + const ts = Date.parse(attrs.updated_at) || Date.now(); + const title = attrs.reference || attrs.code || booking.id; + return { + id: booking.id, + summary: `Booking updated: ${title}`, + ts, + }; + },components/booking_experts/sources/inventory-object-updated/inventory-object-updated.mjs (1)
36-41: Harden ts parsing and improve summaryGuard date parsing and prefer a readable label/name when present.
- generateMeta(inventoryObject) { - return { - id: inventoryObject.id, - summary: `Inventory object updated: ${inventoryObject.id}`, - ts: Date.parse(inventoryObject.attributes.updated_at), - }; - }, + generateMeta(inventoryObject) { + const attrs = inventoryObject?.attributes ?? {}; + const ts = Date.parse(attrs.updated_at) || Date.now(); + const title = attrs.name || attrs.label || inventoryObject.id; + return { + id: inventoryObject.id, + summary: `Inventory object updated: ${title}`, + ts, + }; + },components/booking_experts/actions/add-guest-to-reservation/add-guest-to-reservation.mjs (2)
6-6: Fix double period in descriptionMinor grammar nit.
- description: "Add a guest to a reservation.. [See the documentation](https://developers.bookingexperts.com/reference/administration-reservation-guests-create)", + description: "Add a guest to a reservation. [See the documentation](https://developers.bookingexperts.com/reference/administration-reservation-guests-create)",
93-94: Make summary more informativeInclude reservation and guest in the summary for easier run visibility.
- $.export("$summary", "Guest added to reservation"); - return data; + $.export("$summary", `Added guest ${this.firstName} ${this.lastName} to reservation ${this.reservationId}`); + return data;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
 - Jira integration is disabled by default for public repositories
 - Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (14)
components/afosto/afosto.app.mjs(1 hunks)components/booking_experts/actions/add-guest-to-reservation/add-guest-to-reservation.mjs(1 hunks)components/booking_experts/actions/create-agenda-period/create-agenda-period.mjs(1 hunks)components/booking_experts/actions/get-complex-prices/get-complex-prices.mjs(1 hunks)components/booking_experts/actions/list-bookings/list-bookings.mjs(1 hunks)components/booking_experts/actions/list-inventory-objects/list-inventory-objects.mjs(1 hunks)components/booking_experts/actions/search-contacts/search-contacts.mjs(1 hunks)components/booking_experts/booking_experts.app.mjs(1 hunks)components/booking_experts/package.json(2 hunks)components/booking_experts/sources/booking-updated/booking-updated.mjs(1 hunks)components/booking_experts/sources/common/base-polling.mjs(1 hunks)components/booking_experts/sources/inventory-object-updated/inventory-object-updated.mjs(1 hunks)components/booking_experts/sources/new-booking-created/new-booking-created.mjs(1 hunks)components/booking_experts/sources/new-inventory-object-created/new-inventory-object-created.mjs(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 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/booking_experts/package.json
⏰ 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: Verify TypeScript components
 - GitHub Check: Publish TypeScript components
 - GitHub Check: pnpm publish
 - GitHub Check: Lint Code Base
 
🔇 Additional comments (18)
components/afosto/afosto.app.mjs (1)
11-11: Trailing newline only — OK.
No functional changes.components/booking_experts/package.json (2)
3-3: Version bump to 0.1.0 — OK.
Matches the new surface area added in this PR.
15-17: Verify @pipedream/platform v3.1.0 API availability
Confirm that the specific exports your code relies on—such asaxiosimports andConfigurationError—are present in @pipedream/platform version 3.1.0 (e.g. by reviewing the v3.1.0 source or changelog).components/booking_experts/booking_experts.app.mjs (1)
186-254: Unable to verify nested endpoints due to missing credentials. The script returned only anerrorsarray (nodata) becauseBOOKING_EXPERTS_API_KEYand/orADMIN_IDweren’t set. Provide valid values or consult the Booking Experts API docs to confirm whether these/administrations/{id}/…routes are correct.components/booking_experts/actions/search-contacts/search-contacts.mjs (1)
1-9: Provide the official parameter list for /contacts/search/first
Share the Booking Experts API docs snippet that lists all supported query parameters (with exact names and casing) for the/contacts/search/firstendpoint so we can confirm whetherphone, andnameare valid.components/booking_experts/actions/list-inventory-objects/list-inventory-objects.mjs (1)
43-55: Include$for request context and avoid sendingundefinedquery paramsPass
$to the app method for logging/observability, and buildparamswithout undefined values to prevent sending"undefined"strings.
[ suggest_essential_refactor ]- const { data } = await this.bookingExperts.listInventoryObjects({ - administrationId: this.administrationId, - params: { - "filter[name]": this.name, - "filter[labels]": this.labels - ? this.labels.join(",") - : undefined, - "page[number]": this.page, - "page[size]": this.perPage, - }, - }); + const params = { + ...(this.name && { "filter[name]": this.name }), + ...(this.labels?.length && { "filter[labels]": this.labels.join(",") }), + ...(this.page && { "page[number]": this.page }), + ...(this.perPage && { "page[size]": this.perPage }), + }; + const { data } = await this.bookingExperts.listInventoryObjects({ + $, + administrationId: this.administrationId, + params, + });components/booking_experts/actions/create-agenda-period/create-agenda-period.mjs (3)
50-59: MakerentableIdoptional and validate that at least one relation is providedAPI commonly requires either an inventory object or a rentable. Mark
rentableIdoptional and enforce a guard inrun.
[ suggest_essential_refactor ]- rentableId: { + rentableId: { propDefinition: [ bookingExperts, "rentableId", (c) => ({ administrationId: c.administrationId, inventoryObjectId: c.inventoryObjectId, }), ], + optional: true, + description: "Rentable to associate. Provide either this or an Inventory Object.", },
61-95: Add input validation (date order, required relationships) and build relationships conditionallyPrevent invalid requests and clearer errors.
[ suggest_essential_refactor ]async run({ $ }) { - const { data } = await this.bookingExperts.createAgendaPeriod({ + const start = Date.parse(this.startDate); + const end = Date.parse(this.endDate); + if (Number.isNaN(start) || Number.isNaN(end) || start > end) { + throw new Error("Invalid dates: ensure Start Date and End Date are valid and start <= end."); + } + if (!this.rentableId && !this.inventoryObjectId) { + throw new Error("Provide either `rentableId` or `inventoryObjectId`."); + } + + const relationships = {}; + if (this.inventoryObjectId) { + relationships.inventory_object = { data: { type: "inventory_object", id: this.inventoryObjectId } }; + } + if (this.rentableId) { + relationships.rentable = { data: { type: "rentable", id: this.rentableId } }; + } + + const { data } = await this.bookingExperts.createAgendaPeriod({ $, administrationId: this.administrationId, type: this.type, data: { data: { type: "agenda_period", attributes: { label: this.label, start_date: this.startDate, end_date: this.endDate, }, - relationships: { - inventory_object: this.inventoryObjectId - ? { - data: { - type: "inventory_object", - id: this.inventoryObjectId, - }, - } - : undefined, - rentable: { - data: { - type: "rentable", - id: this.rentableId, - }, - }, - }, + relationships, }, }, });
6-6: Confirm JSON:APItypevalueEnsure the payload’s resource
"type": "agenda_period"matches Booking Experts’ expected resource type for the selected endpoint (e.g., maintenance vs external blocked).
[ request_verification ]
Would you like me to cross-check the docs and adjust thetypeaccordingly?components/booking_experts/actions/list-bookings/list-bookings.mjs (2)
61-73: Bug: references to undefinedcreatedAt/updatedAtprops; filter keys may sendundefinedEither add these props or remove the filters and omit undefined values. Also pass
$and mark optional filters as optional.
[ raise_critical_issue ]props: { bookingExperts, administrationId: { propDefinition: [ bookingExperts, "administrationId", ], }, ownerId: { propDefinition: [ bookingExperts, "ownerId", (c) => ({ administrationId: c.administrationId, }), ], - description: "Filter by owner", + description: "Filter by owner", + optional: true, }, channelId: { propDefinition: [ bookingExperts, "channelId", (c) => ({ administrationId: c.administrationId, }), ], - description: "Filter by channel", + description: "Filter by channel", + optional: true, }, @@ reservationId: { @@ optional: true, }, + createdAt: { + type: "string", + label: "Created At", + description: "Filter by created_at (e.g. `2025-08-01..2025-08-31` or exact ISO timestamp), if supported by the API.", + optional: true, + }, + updatedAt: { + type: "string", + label: "Updated At", + description: "Filter by updated_at (range or exact), if supported by the API.", + optional: true, + },async run({ $ }) { - const { data } = await this.bookingExperts.listBookings({ - $, - administrationId: this.administrationId, - params: { - "filter[owner]": this.ownerId, - "filter[channel]": this.channelId, - "filter[reservations]": this.reservationId, - "filter[created_at]": this.createdAt, - "filter[updated_at]": this.updatedAt, - "page[number]": this.page, - "page[size]": this.perPage, - }, - }); + const params = { + ...(this.ownerId && { "filter[owner]": this.ownerId }), + ...(this.channelId && { "filter[channel]": this.channelId }), + ...(this.reservationId && { "filter[reservations]": this.reservationId }), + ...(this.createdAt && { "filter[created_at]": this.createdAt }), + ...(this.updatedAt && { "filter[updated_at]": this.updatedAt }), + ...(this.page && { "page[number]": this.page }), + ...(this.perPage && { "page[size]": this.perPage }), + }; + const { data } = await this.bookingExperts.listBookings({ + $, + administrationId: this.administrationId, + params, + });
66-70: Verify filter param names against the APIDouble-check whether the API expects singular vs plural keys (e.g.,
filter[reservation]vsfilter[reservations]) and accepted date filter formats.
[ request_verification ]
I can adjust the params once confirmed.components/booking_experts/sources/common/base-polling.mjs (2)
36-67: Pagination stops after first page; uninitializedhasMoreand potential event loss on equal timestampsInitialize
hasMore, bind the resource fn, default-sort by timestamp if absent, and use>=to avoid skipping events sharing the same timestamp (dedupe will handle duplicates).
[ raise_critical_issue ]- const items = []; - let total, hasMore, count = 0; + const items = []; + let total, hasMore = true, count = 0; - args = { + args = { ...args, params: { ...args?.params, + // default to newest-first by timestamp if not provided + sort: args?.params?.sort ?? `-${tsField}`, "page[number]": 1, "page[size]": 100, }, }; do { - const { data } = await resourceFn(args); + const boundResource = this.getResourceFn().bind(this.bookingExperts); + const { data } = await boundResource(args); total = data?.length; if (!total) { break; } - for (const item of data) { + hasMore = true; + for (const item of data) { const ts = Date.parse(item.attributes[tsField]); - if (ts > lastTs) { + if (ts >= lastTs) { items.push(item); if (limit && ++count >= limit) { hasMore = false; break; } } else { hasMore = false; break; } } - args.params["page[number]"]++; - } while (hasMore && total === args.params["page[size]"]); + if (hasMore && total === args.params["page[size]"]) { + args.params["page[number]"]++; + } else { + hasMore = false; + } + } while (hasMore);
72-77: AnchorlastTscorrectly to avoid dropping itemsKeeping
lastTsat the newest ts is fine with>=filtering plus unique dedupe. Consider persisting the newest ts across the page, not only the first item.
[ suggest_optional_refactor ]- this._setLastTs(Date.parse(items[0].attributes[tsField])); + const newestTs = Math.max(...items.map((i) => Date.parse(i.attributes[tsField]))); + this._setLastTs(newestTs);components/booking_experts/sources/new-booking-created/new-booking-created.mjs (2)
22-24: Bind the app method to preservethiscontextReturning an unbound method will lose its
thisand likely throw at runtime. Bind to the app instance.
[ raise_critical_issue ]- getResourceFn() { - return this.bookingExperts.listBookings; - }, + getResourceFn() { + return this.bookingExperts.listBookings.bind(this.bookingExperts); + },
26-32: Pass sort by created_at explicitly (already done) and consider adding$if your app wrapper uses itIf the app method benefits from
$, updatebase-pollingto pass it or wrap here.
[ request_verification ]
Do you want me to extend the base to pass$through to the app calls?components/booking_experts/sources/booking-updated/booking-updated.mjs (1)
25-35: Confirmed base-polling uses getTsField() for checkpointing and the API consistently applies sort: "-updated_at"; no changes required.components/booking_experts/actions/add-guest-to-reservation/add-guest-to-reservation.mjs (2)
79-80: Confirm JSON:API type value
The Booking Experts docs list this resource’s type as “reservation_guests” for the create‐guest endpoint; please double-check that using “guest” here is correct.
1-25: Verified: reservationId propDefinition and addGuestToReservation method are present
ThereservationIdprop is defined with async options scoped byadministrationId, and theaddGuestToReservationclient method exists in the app.
        
          
                components/booking_experts/actions/add-guest-to-reservation/add-guest-to-reservation.mjs
          
            Show resolved
            Hide resolved
        
              
          
                components/booking_experts/actions/get-complex-prices/get-complex-prices.mjs
          
            Show resolved
            Hide resolved
        
              
          
                components/booking_experts/actions/search-contacts/search-contacts.mjs
              
                Outdated
          
            Show resolved
            Hide resolved
        
              
          
                components/booking_experts/sources/inventory-object-updated/inventory-object-updated.mjs
          
            Show resolved
            Hide resolved
        
              
          
                ...onents/booking_experts/sources/new-inventory-object-created/new-inventory-object-created.mjs
          
            Show resolved
            Hide resolved
        
      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 @michelle0927, LGTM! Ready for QA!
Resolves #18055
Summary by CodeRabbit
New Features
Chores
Style