Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions components/xola/actions/add-event-guide/add-event-guide.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import app from "../../xola.app.mjs";

export default {
key: "xola-add-event-guide",
name: "Add Event Guide",
description: "Adds a guide to an event. [See the documentation](https://developers.xola.com/reference/assign-a-guide-to-a-trip)",
version: "0.0.1",
type: "action",
annotations: {
destructiveHint: true,
openWorldHint: true,
readOnlyHint: false,
},
props: {
app,
eventId: {
propDefinition: [
app,
"eventId",
],
},
guideId: {
propDefinition: [
app,
"guideId",
],
},
forceConfirm: {
type: "boolean",
label: "Force Confirm",
description: "Force assignment even if guide has conflicts",
optional: true,
},
},
async run({ $ }) {
const {
app,
eventId,
guideId,
forceConfirm,
} = this;

const response = await app.addEventGuide({
$,
eventId,
data: {
guide: {
id: guideId,
forceConfirm,
},
},
});
Comment on lines +43 to +52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the payload structure matches the API contract.

The data structure wraps the guide parameters in a nested data.guide object, which differs from the simpler structure used in the related remove-event-guide action (which passes eventId and guideId directly). Please confirm this nested structure matches the Xola API specification for assigning guides.


🏁 Script executed:

#!/bin/bash
# Description: Check how addEventGuide is implemented in xola.app.mjs to understand the expected payload structure

# Find the addEventGuide method implementation
rg -A 10 'addEventGuide' components/xola/xola.app.mjs

Length of output: 217





🏁 Script executed:

#!/bin/bash
# Check removeEventGuide implementation and compare with addEventGuide
rg -A 5 'removeEventGuide' components/xola/xola.app.mjs

# Also check the post() method to understand how it handles the data parameter
rg -A 15 'post\s*\(\s*\{' components/xola/xola.app.mjs | head -40

Length of output: 1048


🏁 Script executed:

#!/bin/bash
# Check how remove-event-guide action calls removeEventGuide for comparison
cat components/xola/actions/remove-event-guide/remove-event-guide.mjs | grep -A 10 'removeEventGuide'

Length of output: 509



---

🏁 Script executed:

```shell
#!/bin/bash
# Look for any documentation links or comments about Xola API structure
rg -i 'xola.*api|addEventGuide' components/xola/actions/add-event-guide/add-event-guide.mjs

# Check for test files that might show expected payload
fd -type f -name '*.test.*' -o -name '*.spec.*' | xargs rg 'addEventGuide' 2>/dev/null || echo "No test files found with addEventGuide"

# Look at other POST actions in xola to see if nested data structures are common
rg -B 5 'this\.post\(' components/xola/xola.app.mjs | head -60

Length of output: 676



$.export("$summary", `Successfully added guide to event with ID \`${response.id}\``);
return response;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import app from "../../xola.app.mjs";

export default {
key: "xola-create-experience-schedule",
name: "Create Experience Schedule",
description: "Creates a new schedule for an experience. [See the documentation](https://developers.xola.com/reference/create-an-experience)",
version: "0.0.1",
type: "action",
props: {
app,
experienceId: {
propDefinition: [
app,
"experienceId",
],
},
name: {
type: "string",
label: "Name",
description: "Name for this schedule",
},
type: {
type: "string",
label: "Type",
description: "Can be for an open (`available`) schedule or a `blackout` schedule",
options: [
"available",
"blackout",
],
},
days: {
type: "string[]",
label: "Days",
description: "Days of week",
optional: true,
options: [
{
label: "Sunday",
value: "0",
},
{
label: "Monday",
value: "1",
},
{
label: "Tuesday",
value: "2",
},
{
label: "Wednesday",
value: "3",
},
{
label: "Thursday",
value: "4",
},
{
label: "Friday",
value: "5",
},
{
label: "Saturday",
value: "6",
},
],
},
Comment on lines +31 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Critical: Inconsistent days representation across schedule actions.

The days prop uses string[] with values "0" (Sunday) through "6" (Saturday), but the update action at components/xola/actions/update-experience-schedule/update-experience-schedule.mjs (lines 50-54) uses integer[] with values 1 (Monday) through 7 (Sunday).

This inconsistency will break workflows where users create a schedule and then attempt to update it, as the day numbering systems are incompatible.

Choose one consistent convention:

  • Option 1: Use the create action's Sunday=0 convention (JavaScript Date.getDay() standard)
  • Option 2: Use the update action's Monday=1 convention (ISO 8601 standard)

Then update both actions to match.

🤖 Prompt for AI Agents
In
components/xola/actions/create-experience-schedule/create-experience-schedule.mjs
(lines 31-66) and
components/xola/actions/update-experience-schedule/update-experience-schedule.mjs
(around lines 50-54), the days representations are inconsistent: create uses
string[] "0"–"6" (Sunday=0) while update uses integer[] 1–7 (Monday=1). Pick one
convention (recommend Option 1: Sunday=0 as string[] to match JS Date.getDay()
or Option 2: Monday=1 as integer[] for ISO), then make both files use the exact
same type and numeric mapping: update the create action to use the chosen
numeric range and type (or update the update action to match create), adjust the
options array values and types accordingly, and ensure any input
parsing/validation and downstream code expecting days is updated to accept the
unified format.

departure: {
type: "string",
label: "Departure",
description: "Whether departure time is fixed or varies",
options: [
"fixed",
"varies",
],
optional: true,
},
times: {
type: "string[]",
label: "Times",
description: "Start times in HHMM format (e.g., `900` = 9:00 AM, `1400` = 2:00 PM, `1800` = 6:00 PM).",
options: [
{
label: "9:00 AM",
value: "900",
},
{
label: "2:00 PM",
value: "1400",
},
{
label: "6:00 PM",
value: "1800",
},
],
optional: true,
},
priceDelta: {
type: "string",
label: "Price Delta",
description: "Price adjustment for this schedule (can be positive or negative). Only available when **Type** is `available`",
optional: true,
},
repeat: {
type: "string",
label: "Repeat",
description: "When and how the schedule should repeat. Options are `weekly` (repeat the same schedule every week until **End**, if specified), or custom, which can be used in conjunction with **Dates** to specify individual days for the schedule to run",
optional: true,
options: [
"weekly",
"custom",
],
},
start: {
type: "string",
label: "Start",
description: "Start date of the schedule in ISO 8601 format. Example: `2024-01-01T00:00:00Z`",
optional: true,
},
end: {
type: "string",
label: "End",
description: "End date of the schedule in ISO 8601 format. Example: `2024-12-31T23:59:59Z`",
optional: true,
},
dates: {
type: "string[]",
label: "Dates",
description: "Specific dates when this schedule applies. Only available when **Repeat** is `custom`. Format is `YYYY-MM-DD`. Cannot be combined with **End**.",
optional: true,
},
},
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
async run({ $ }) {
const {
app,
experienceId,
name,
type,
days,
times,
departure,
priceDelta,
repeat,
start,
end,
dates,
} = this;

const response = await app.createExperienceSchedule({
$,
experienceId,
data: {
start,
end,
dates,
type,
name,
repeat,
days,
times,
departure,
priceDelta,
},
});

$.export("$summary", `Successfully created schedule for experience with ID \`${response.id}\``);
return response;
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import app from "../../xola.app.mjs";

export default {
key: "xola-delete-experience-schedule",
name: "Delete Experience Schedule",
description: "Deletes a schedule from an experience. [See the documentation](https://xola.github.io/xola-docs/#tag/schedules/operation/deleteExperienceSchedule)",
version: "0.0.1",
type: "action",
props: {
app,
experienceId: {
propDefinition: [
app,
"experienceId",
],
},
scheduleId: {
propDefinition: [
app,
"scheduleId",
],
},
},
annotations: {
destructiveHint: true,
openWorldHint: true,
readOnlyHint: false,
},
async run({ $ }) {
const {
app,
experienceId,
scheduleId,
} = this;

const response = await app.deleteExperienceSchedule({
$,
experienceId,
scheduleId,
});

$.export("$summary", `Successfully deleted schedule ${scheduleId}`);
return response;
},
};
89 changes: 89 additions & 0 deletions components/xola/actions/patch-event/patch-event.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import app from "../../xola.app.mjs";

export default {
key: "xola-patch-event",
name: "Patch Event",
description: "Updates specific fields of an event. [See the documentation](https://xola.github.io/xola-docs/#tag/events/operation/patchEvent)",
version: "0.0.1",
type: "action",
props: {
app,
eventId: {
propDefinition: [
app,
"eventId",
],
},
name: {
type: "string",
label: "Name",
description: "The name of the event",
optional: true,
},
description: {
type: "string",
label: "Description",
description: "The description of the event",
optional: true,
},
start: {
type: "string",
label: "Start Date/Time",
description: "Start date and time in ISO 8601 format. Example: `2024-01-01T09:00:00Z`",
optional: true,
},
end: {
type: "string",
label: "End Date/Time",
description: "End date and time in ISO 8601 format. Example: `2024-01-01T17:00:00Z`",
optional: true,
},
capacity: {
type: "integer",
label: "Capacity",
description: "The maximum number of participants for the event",
optional: true,
},
},
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
async run({ $ }) {
const {
app,
eventId,
name,
description,
start,
end,
capacity,
} = this;

const response = await app.patchEvent({
$,
eventId,
data: {
...name && {
name,
},
...description && {
description,
},
...start && {
start,
},
...end && {
end,
},
...capacity && {
capacity,
},
},
});

$.export("$summary", `Successfully patched event ${eventId}`);
return response;
},
};
Loading
Loading