@atzentis/booking-sdk 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -35,35 +35,48 @@ __export(index_exports, {
35
35
  BookingError: () => BookingError,
36
36
  BookingsService: () => BookingsService,
37
37
  CategoriesService: () => CategoriesService,
38
+ ConciergeService: () => ConciergeService,
38
39
  ConflictError: () => ConflictError,
39
40
  DEFAULT_MODULES: () => DEFAULT_MODULES,
40
41
  DiscountsService: () => DiscountsService,
41
42
  DistributionService: () => DistributionService,
42
43
  FinanceService: () => FinanceService,
44
+ FiscalService: () => FiscalService,
43
45
  ForbiddenError: () => ForbiddenError,
44
46
  GroupsService: () => GroupsService,
45
47
  GuestsService: () => GuestsService,
46
48
  HousekeepingService: () => HousekeepingService,
47
49
  HttpClient: () => HttpClient,
50
+ IdScanningService: () => IdScanningService,
51
+ IntelligenceService: () => IntelligenceService,
48
52
  NightAuditService: () => NightAuditService,
49
53
  NotFoundError: () => NotFoundError,
54
+ NotificationsService: () => NotificationsService,
50
55
  PROPERTY_MODULES: () => PROPERTY_MODULES,
51
56
  PaymentError: () => PaymentError,
52
57
  PaymentsService: () => PaymentsService,
58
+ PortfoliosService: () => PortfoliosService,
53
59
  PropertiesService: () => PropertiesService,
54
60
  RateLimitError: () => RateLimitError,
55
61
  RatePlansService: () => RatePlansService,
62
+ RevenueService: () => RevenueService,
56
63
  ReviewsService: () => ReviewsService,
57
64
  SPACE_STATUSES: () => SPACE_STATUSES,
58
65
  SPACE_TYPES: () => SPACE_TYPES,
66
+ SSEClient: () => SSEClient,
59
67
  ServerError: () => ServerError,
68
+ ServicesHelper: () => ServicesHelper,
69
+ SettingsService: () => SettingsService,
60
70
  SpacesService: () => SpacesService,
61
71
  StaffService: () => StaffService,
72
+ StaysHelper: () => StaysHelper,
62
73
  SupplyService: () => SupplyService,
74
+ TablesHelper: () => TablesHelper,
63
75
  TasksService: () => TasksService,
64
76
  TimeoutError: () => TimeoutError,
65
77
  VERSION: () => VERSION,
66
78
  ValidationError: () => ValidationError,
79
+ WebhooksService: () => WebhooksService,
67
80
  bookingClientConfigSchema: () => bookingClientConfigSchema,
68
81
  createErrorFromResponse: () => createErrorFromResponse,
69
82
  firstPage: () => firstPage,
@@ -1104,6 +1117,104 @@ var CategoriesService = class extends BaseService {
1104
1117
  }
1105
1118
  };
1106
1119
 
1120
+ // src/services/concierge.ts
1121
+ var ConciergeService = class extends BaseService {
1122
+ constructor() {
1123
+ super(...arguments);
1124
+ this.basePath = "/concierge/v1";
1125
+ }
1126
+ // ---------------------------------------------------------------------------
1127
+ // Conversations
1128
+ // ---------------------------------------------------------------------------
1129
+ /** Create a new guest conversation */
1130
+ createConversation(input) {
1131
+ return this._post(this._buildPath("conversations"), input);
1132
+ }
1133
+ /** Get a conversation by ID */
1134
+ getConversation(conversationId) {
1135
+ return this._get(this._buildPath("conversations", conversationId));
1136
+ }
1137
+ /** List conversations with optional filters */
1138
+ listConversations(params) {
1139
+ const query = {};
1140
+ query.propertyId = params.propertyId;
1141
+ if (params.guestId !== void 0) query.guestId = params.guestId;
1142
+ if (params.status !== void 0) query.status = params.status;
1143
+ if (params.channel !== void 0) query.channel = params.channel;
1144
+ if (params.from !== void 0) query.from = params.from;
1145
+ if (params.to !== void 0) query.to = params.to;
1146
+ if (params.sortBy !== void 0) query.sortBy = params.sortBy;
1147
+ if (params.sortOrder !== void 0) query.sortOrder = params.sortOrder;
1148
+ if (params.limit !== void 0) query.limit = params.limit;
1149
+ if (params.cursor !== void 0) query.cursor = params.cursor;
1150
+ return this._get(this._buildPath("conversations"), query);
1151
+ }
1152
+ // ---------------------------------------------------------------------------
1153
+ // Messages
1154
+ // ---------------------------------------------------------------------------
1155
+ /** Send a message in a conversation */
1156
+ sendMessage(conversationId, input) {
1157
+ return this._post(
1158
+ this._buildPath("conversations", conversationId, "messages"),
1159
+ input
1160
+ );
1161
+ }
1162
+ // ---------------------------------------------------------------------------
1163
+ // Context & Escalation
1164
+ // ---------------------------------------------------------------------------
1165
+ /** Get the full context for a conversation (property, guest, booking, FAQ) */
1166
+ getContext(conversationId) {
1167
+ return this._get(
1168
+ this._buildPath("conversations", conversationId, "context")
1169
+ );
1170
+ }
1171
+ /** Escalate a conversation to staff */
1172
+ escalate(conversationId, input) {
1173
+ return this._post(
1174
+ this._buildPath("conversations", conversationId, "escalate"),
1175
+ input ?? {}
1176
+ );
1177
+ }
1178
+ /** Resolve a conversation */
1179
+ resolve(conversationId, input) {
1180
+ return this._post(
1181
+ this._buildPath("conversations", conversationId, "resolve"),
1182
+ input ?? {}
1183
+ );
1184
+ }
1185
+ // ---------------------------------------------------------------------------
1186
+ // Templates
1187
+ // ---------------------------------------------------------------------------
1188
+ /** Create a response template */
1189
+ createTemplate(input) {
1190
+ return this._post(this._buildPath("templates"), input);
1191
+ }
1192
+ /** Get a template by ID */
1193
+ getTemplate(templateId) {
1194
+ return this._get(this._buildPath("templates", templateId));
1195
+ }
1196
+ /** List templates with optional filters */
1197
+ listTemplates(params) {
1198
+ const query = {};
1199
+ query.propertyId = params.propertyId;
1200
+ if (params.category !== void 0) query.category = params.category;
1201
+ if (params.language !== void 0) query.language = params.language;
1202
+ if (params.sortBy !== void 0) query.sortBy = params.sortBy;
1203
+ if (params.sortOrder !== void 0) query.sortOrder = params.sortOrder;
1204
+ if (params.limit !== void 0) query.limit = params.limit;
1205
+ if (params.cursor !== void 0) query.cursor = params.cursor;
1206
+ return this._get(this._buildPath("templates"), query);
1207
+ }
1208
+ /** Update a template */
1209
+ updateTemplate(templateId, input) {
1210
+ return this._patch(this._buildPath("templates", templateId), input);
1211
+ }
1212
+ /** Delete a template */
1213
+ deleteTemplate(templateId) {
1214
+ return this._delete(this._buildPath("templates", templateId));
1215
+ }
1216
+ };
1217
+
1107
1218
  // src/services/discounts.ts
1108
1219
  var DiscountsService = class extends BaseService {
1109
1220
  constructor() {
@@ -1429,6 +1540,77 @@ var FinanceService = class extends BaseService {
1429
1540
  }
1430
1541
  };
1431
1542
 
1543
+ // src/services/fiscal.ts
1544
+ var FiscalService = class extends BaseService {
1545
+ constructor() {
1546
+ super(...arguments);
1547
+ this.basePath = "/fiscal/v1";
1548
+ }
1549
+ // ---------------------------------------------------------------------------
1550
+ // myDATA (Greek fiscal compliance)
1551
+ // ---------------------------------------------------------------------------
1552
+ /** Get the current myDATA integration status */
1553
+ getMyDataStatus() {
1554
+ return this._get(this._buildPath("mydata", "status"));
1555
+ }
1556
+ /** Submit an invoice to the Greek AADE myDATA platform */
1557
+ submitMyData(input) {
1558
+ return this._post(this._buildPath("mydata", "submit"), input);
1559
+ }
1560
+ /** List myDATA submissions with optional filters */
1561
+ listMyDataSubmissions(params) {
1562
+ if (!params) {
1563
+ return this._get(this._buildPath("mydata", "submissions"));
1564
+ }
1565
+ const query = {};
1566
+ if (params.status !== void 0) query.status = params.status;
1567
+ if (params.from !== void 0) query.from = params.from;
1568
+ if (params.to !== void 0) query.to = params.to;
1569
+ if (params.limit !== void 0) query.limit = params.limit;
1570
+ if (params.cursor !== void 0) query.cursor = params.cursor;
1571
+ return this._get(this._buildPath("mydata", "submissions"), query);
1572
+ }
1573
+ /** Get a single myDATA submission by ID */
1574
+ getMyDataSubmission(submissionId) {
1575
+ return this._get(this._buildPath("mydata", "submissions", submissionId));
1576
+ }
1577
+ /** Generate a QR code for a myDATA transaction */
1578
+ getMyDataQr(transactionId) {
1579
+ return this._get(this._buildPath("mydata", "qr", transactionId));
1580
+ }
1581
+ // ---------------------------------------------------------------------------
1582
+ // TSE (German fiscal compliance)
1583
+ // ---------------------------------------------------------------------------
1584
+ /** Get the current TSE device status */
1585
+ getTseStatus() {
1586
+ return this._get(this._buildPath("tse", "status"));
1587
+ }
1588
+ /** List TSE transactions with optional filters */
1589
+ listTseTransactions(params) {
1590
+ if (!params) {
1591
+ return this._get(this._buildPath("tse", "transactions"));
1592
+ }
1593
+ const query = {};
1594
+ if (params.from !== void 0) query.from = params.from;
1595
+ if (params.to !== void 0) query.to = params.to;
1596
+ if (params.limit !== void 0) query.limit = params.limit;
1597
+ if (params.cursor !== void 0) query.cursor = params.cursor;
1598
+ return this._get(this._buildPath("tse", "transactions"), query);
1599
+ }
1600
+ /** Trigger a TSE day closure */
1601
+ tseDayClosure(input) {
1602
+ return this._post(this._buildPath("tse", "day-closure"), input ?? {});
1603
+ }
1604
+ /** Export DSFinV-K data for a date range */
1605
+ tseExportDsfinvk(params) {
1606
+ const query = {};
1607
+ query.from = params.from;
1608
+ query.to = params.to;
1609
+ if (params.format !== void 0) query.format = params.format;
1610
+ return this._get(this._buildPath("tse", "export", "dsfinvk"), query);
1611
+ }
1612
+ };
1613
+
1432
1614
  // src/services/groups.ts
1433
1615
  var GroupsService = class extends BaseService {
1434
1616
  constructor() {
@@ -1825,6 +2007,77 @@ var HousekeepingService = class extends BaseService {
1825
2007
  }
1826
2008
  };
1827
2009
 
2010
+ // src/services/id-scanning.ts
2011
+ var IdScanningService = class extends BaseService {
2012
+ constructor() {
2013
+ super(...arguments);
2014
+ this.basePath = "/guest/v1/id-scans";
2015
+ }
2016
+ /** Upload a document image for OCR processing */
2017
+ upload(input) {
2018
+ const formData = new FormData();
2019
+ formData.append("guestId", input.guestId);
2020
+ formData.append(
2021
+ "file",
2022
+ input.file instanceof ArrayBuffer ? new Blob([input.file]) : input.file
2023
+ );
2024
+ formData.append("type", input.type);
2025
+ return this._post(this.basePath, formData);
2026
+ }
2027
+ /** Get the OCR result for a scan by ID */
2028
+ getResult(scanId) {
2029
+ return this._get(this._buildPath(scanId));
2030
+ }
2031
+ /** List ID scans with optional filters */
2032
+ list(params) {
2033
+ const query = {};
2034
+ query.guestId = params.guestId;
2035
+ if (params.status !== void 0) query.status = params.status;
2036
+ if (params.limit !== void 0) query.limit = params.limit;
2037
+ if (params.cursor !== void 0) query.cursor = params.cursor;
2038
+ return this._get(this.basePath, query);
2039
+ }
2040
+ };
2041
+
2042
+ // src/services/intelligence.ts
2043
+ var IntelligenceService = class extends BaseService {
2044
+ constructor() {
2045
+ super(...arguments);
2046
+ this.basePath = "/guest/v1";
2047
+ }
2048
+ // ---------------------------------------------------------------------------
2049
+ // Profile
2050
+ // ---------------------------------------------------------------------------
2051
+ /** Get the intelligence profile for a guest */
2052
+ getProfile(guestId) {
2053
+ return this._get(this._buildPath("profiles", guestId, "intelligence"));
2054
+ }
2055
+ /** Trigger a refresh of the intelligence profile for a guest */
2056
+ refresh(guestId) {
2057
+ return this._post(
2058
+ this._buildPath("profiles", guestId, "intelligence", "refresh"),
2059
+ {}
2060
+ );
2061
+ }
2062
+ // ---------------------------------------------------------------------------
2063
+ // Events
2064
+ // ---------------------------------------------------------------------------
2065
+ /** Ingest a guest intelligence event for processing */
2066
+ ingestEvent(input) {
2067
+ return this._post(this._buildPath("intelligence", "events"), input);
2068
+ }
2069
+ /** List intelligence events for a guest with optional filters */
2070
+ listEvents(params) {
2071
+ const query = {};
2072
+ query.guestId = params.guestId;
2073
+ if (params.status !== void 0) query.status = params.status;
2074
+ if (params.type !== void 0) query.type = params.type;
2075
+ if (params.limit !== void 0) query.limit = params.limit;
2076
+ if (params.cursor !== void 0) query.cursor = params.cursor;
2077
+ return this._get(this._buildPath("intelligence", "events"), query);
2078
+ }
2079
+ };
2080
+
1828
2081
  // src/services/night-audit.ts
1829
2082
  var NightAuditService = class extends BaseService {
1830
2083
  constructor() {
@@ -1859,6 +2112,26 @@ var NightAuditService = class extends BaseService {
1859
2112
  }
1860
2113
  };
1861
2114
 
2115
+ // src/services/notifications.ts
2116
+ var NotificationsService = class extends BaseService {
2117
+ constructor() {
2118
+ super(...arguments);
2119
+ this.basePath = "/notifications/v1";
2120
+ }
2121
+ /** Get notification preferences for a guest */
2122
+ getPreferences(guestId) {
2123
+ return this._get(this._buildPath("preferences", guestId));
2124
+ }
2125
+ /** Update notification preferences for a guest */
2126
+ updatePreferences(guestId, input) {
2127
+ return this._patch(this._buildPath("preferences", guestId), input);
2128
+ }
2129
+ /** Opt a guest out of notifications (all channels or specific ones) */
2130
+ optOut(input) {
2131
+ return this._post(this._buildPath("opt-out"), input);
2132
+ }
2133
+ };
2134
+
1862
2135
  // src/services/payments.ts
1863
2136
  var PaymentsService = class extends BaseService {
1864
2137
  constructor() {
@@ -1954,6 +2227,77 @@ var PaymentsService = class extends BaseService {
1954
2227
  }
1955
2228
  };
1956
2229
 
2230
+ // src/services/portfolios.ts
2231
+ var PortfoliosService = class extends BaseService {
2232
+ constructor() {
2233
+ super(...arguments);
2234
+ this.basePath = "/operations/v1/portfolios";
2235
+ }
2236
+ // ---------------------------------------------------------------------------
2237
+ // CRUD
2238
+ // ---------------------------------------------------------------------------
2239
+ /** Create a new portfolio */
2240
+ create(input) {
2241
+ return this._post(this.basePath, input);
2242
+ }
2243
+ /** Get a portfolio by ID including its properties */
2244
+ get(portfolioId) {
2245
+ return this._get(this._buildPath(portfolioId));
2246
+ }
2247
+ /** List portfolios with optional filters */
2248
+ list(params) {
2249
+ if (!params) return this._get(this.basePath);
2250
+ const query = {};
2251
+ if (params.limit !== void 0) query.limit = params.limit;
2252
+ if (params.cursor !== void 0) query.cursor = params.cursor;
2253
+ if (params.search !== void 0) query.search = params.search;
2254
+ return this._get(this.basePath, query);
2255
+ }
2256
+ /** Update a portfolio */
2257
+ update(portfolioId, input) {
2258
+ return this._patch(this._buildPath(portfolioId), input);
2259
+ }
2260
+ /** Delete a portfolio */
2261
+ delete(portfolioId) {
2262
+ return this._delete(this._buildPath(portfolioId));
2263
+ }
2264
+ // ---------------------------------------------------------------------------
2265
+ // Membership
2266
+ // ---------------------------------------------------------------------------
2267
+ /** Add a property to a portfolio */
2268
+ addProperty(portfolioId, input) {
2269
+ return this._post(this._buildPath(portfolioId, "properties"), input);
2270
+ }
2271
+ /** Remove a property from a portfolio */
2272
+ removeProperty(portfolioId, propertyId) {
2273
+ return this._delete(this._buildPath(portfolioId, "properties", propertyId));
2274
+ }
2275
+ // ---------------------------------------------------------------------------
2276
+ // Dashboard
2277
+ // ---------------------------------------------------------------------------
2278
+ /** Get aggregated dashboard data for a portfolio */
2279
+ getDashboard(portfolioId, params) {
2280
+ const path = this._buildPath(portfolioId, "dashboard");
2281
+ if (!params) return this._get(path);
2282
+ const query = {};
2283
+ if (params.from !== void 0) query.from = params.from;
2284
+ if (params.to !== void 0) query.to = params.to;
2285
+ return this._get(path, query);
2286
+ }
2287
+ // ---------------------------------------------------------------------------
2288
+ // Search
2289
+ // ---------------------------------------------------------------------------
2290
+ /** Search for guests, bookings, or all records within a portfolio */
2291
+ search(portfolioId, params) {
2292
+ const query = {};
2293
+ query.query = params.query;
2294
+ if (params.type !== void 0) query.type = params.type;
2295
+ if (params.limit !== void 0) query.limit = params.limit;
2296
+ if (params.cursor !== void 0) query.cursor = params.cursor;
2297
+ return this._get(this._buildPath(portfolioId, "search"), query);
2298
+ }
2299
+ };
2300
+
1957
2301
  // src/services/properties.ts
1958
2302
  var PropertiesService = class extends BaseService {
1959
2303
  constructor() {
@@ -2121,6 +2465,152 @@ var RatePlansService = class extends BaseService {
2121
2465
  }
2122
2466
  };
2123
2467
 
2468
+ // src/services/revenue.ts
2469
+ var RevenueService = class extends BaseService {
2470
+ constructor() {
2471
+ super(...arguments);
2472
+ this.basePath = "/revenue/v1";
2473
+ }
2474
+ // ---------------------------------------------------------------------------
2475
+ // Dashboard
2476
+ // ---------------------------------------------------------------------------
2477
+ /** Get the revenue dashboard with KPIs, occupancy, and revenue breakdown */
2478
+ getDashboard(params) {
2479
+ const query = {};
2480
+ query.propertyId = params.propertyId;
2481
+ if (params.from !== void 0) query.from = params.from;
2482
+ if (params.to !== void 0) query.to = params.to;
2483
+ if (params.compareWith !== void 0) query.compareWith = params.compareWith;
2484
+ return this._get(this._buildPath("dashboard"), query);
2485
+ }
2486
+ /** Get individual KPI metrics with optional granularity breakdown */
2487
+ getKPIs(params) {
2488
+ const query = {};
2489
+ query.propertyId = params.propertyId;
2490
+ if (params.from !== void 0) query.from = params.from;
2491
+ if (params.to !== void 0) query.to = params.to;
2492
+ if (params.metrics !== void 0) query.metrics = params.metrics.join(",");
2493
+ if (params.granularity !== void 0) query.granularity = params.granularity;
2494
+ return this._get(this._buildPath("kpis"), query);
2495
+ }
2496
+ // ---------------------------------------------------------------------------
2497
+ // Rate suggestions
2498
+ // ---------------------------------------------------------------------------
2499
+ /** List AI-generated rate suggestions with optional filters */
2500
+ listSuggestions(params) {
2501
+ const query = {};
2502
+ query.propertyId = params.propertyId;
2503
+ if (params.status !== void 0) query.status = params.status;
2504
+ if (params.ratePlanId !== void 0) query.ratePlanId = params.ratePlanId;
2505
+ if (params.from !== void 0) query.from = params.from;
2506
+ if (params.to !== void 0) query.to = params.to;
2507
+ if (params.limit !== void 0) query.limit = params.limit;
2508
+ if (params.cursor !== void 0) query.cursor = params.cursor;
2509
+ return this._get(this._buildPath("suggestions"), query);
2510
+ }
2511
+ /** Apply a rate suggestion, updating the associated rate plan */
2512
+ applySuggestion(suggestionId) {
2513
+ return this._post(this._buildPath("suggestions", suggestionId, "apply"), {});
2514
+ }
2515
+ /** Dismiss a rate suggestion with an optional reason */
2516
+ dismissSuggestion(suggestionId, input) {
2517
+ return this._post(
2518
+ this._buildPath("suggestions", suggestionId, "dismiss"),
2519
+ input ?? {}
2520
+ );
2521
+ }
2522
+ // ---------------------------------------------------------------------------
2523
+ // Competitors
2524
+ // ---------------------------------------------------------------------------
2525
+ /** List competitors tracked for a property */
2526
+ listCompetitors(params) {
2527
+ const query = {};
2528
+ query.propertyId = params.propertyId;
2529
+ if (params.limit !== void 0) query.limit = params.limit;
2530
+ if (params.cursor !== void 0) query.cursor = params.cursor;
2531
+ return this._get(this._buildPath("competitors"), query);
2532
+ }
2533
+ /** Get rate data scraped for a competitor over a date range */
2534
+ getCompetitorRates(competitorId, params) {
2535
+ const query = {};
2536
+ if (params !== void 0) {
2537
+ if (params.from !== void 0) query.from = params.from;
2538
+ if (params.to !== void 0) query.to = params.to;
2539
+ if (params.source !== void 0) query.source = params.source;
2540
+ }
2541
+ return this._get(
2542
+ this._buildPath("competitors", competitorId, "rates"),
2543
+ query
2544
+ );
2545
+ }
2546
+ /** Add a competitor to track for a property */
2547
+ addCompetitor(input) {
2548
+ return this._post(this._buildPath("competitors"), input);
2549
+ }
2550
+ // ---------------------------------------------------------------------------
2551
+ // Reports
2552
+ // ---------------------------------------------------------------------------
2553
+ /** Get a detailed revenue report with optional comparison period */
2554
+ getRevenueReport(params) {
2555
+ const query = {};
2556
+ query.propertyId = params.propertyId;
2557
+ query.from = params.from;
2558
+ query.to = params.to;
2559
+ if (params.groupBy !== void 0) query.groupBy = params.groupBy;
2560
+ if (params.compareWith !== void 0) query.compareWith = params.compareWith;
2561
+ return this._get(this._buildPath("reports", "revenue"), query);
2562
+ }
2563
+ /** Get a revenue forecast for a future date range */
2564
+ getForecast(params) {
2565
+ const query = {};
2566
+ query.propertyId = params.propertyId;
2567
+ query.from = params.from;
2568
+ query.to = params.to;
2569
+ if (params.model !== void 0) query.model = params.model;
2570
+ return this._get(this._buildPath("reports", "forecast"), query);
2571
+ }
2572
+ /** Get a pace report comparing current bookings against a prior period */
2573
+ getPaceReport(params) {
2574
+ const query = {};
2575
+ query.propertyId = params.propertyId;
2576
+ query.from = params.from;
2577
+ query.to = params.to;
2578
+ if (params.compareWith !== void 0) query.compareWith = params.compareWith;
2579
+ if (params.granularity !== void 0) query.granularity = params.granularity;
2580
+ return this._get(this._buildPath("reports", "pace"), query);
2581
+ }
2582
+ // ---------------------------------------------------------------------------
2583
+ // Portfolio
2584
+ // ---------------------------------------------------------------------------
2585
+ /** Get a portfolio-level dashboard with aggregated KPIs */
2586
+ getPortfolioDashboard(params) {
2587
+ const query = {};
2588
+ query.portfolioId = params.portfolioId;
2589
+ if (params.from !== void 0) query.from = params.from;
2590
+ if (params.to !== void 0) query.to = params.to;
2591
+ return this._get(this._buildPath("portfolio", "dashboard"), query);
2592
+ }
2593
+ /** Get a per-property breakdown of revenue metrics across a portfolio */
2594
+ getPortfolioBreakdown(params) {
2595
+ const query = {};
2596
+ query.portfolioId = params.portfolioId;
2597
+ if (params.from !== void 0) query.from = params.from;
2598
+ if (params.to !== void 0) query.to = params.to;
2599
+ if (params.sortBy !== void 0) query.sortBy = params.sortBy;
2600
+ if (params.sortOrder !== void 0) query.sortOrder = params.sortOrder;
2601
+ return this._get(this._buildPath("portfolio", "breakdown"), query);
2602
+ }
2603
+ /** Get a revenue forecast for all properties in a portfolio */
2604
+ getPortfolioForecast(params) {
2605
+ const query = {};
2606
+ query.portfolioId = params.portfolioId;
2607
+ if (params.from !== void 0) query.from = params.from;
2608
+ if (params.to !== void 0) query.to = params.to;
2609
+ if (params.model !== void 0) query.model = params.model;
2610
+ return this._get(this._buildPath("portfolio", "forecast"), query);
2611
+ }
2612
+ };
2613
+
2124
2614
  // src/services/reviews.ts
2125
2615
  var ReviewsService = class extends BaseService {
2126
2616
  constructor() {
@@ -2206,6 +2696,195 @@ var ReviewsService = class extends BaseService {
2206
2696
  }
2207
2697
  };
2208
2698
 
2699
+ // src/services/services-helper.ts
2700
+ var ServicesHelper = class {
2701
+ constructor(client) {
2702
+ this.client = client;
2703
+ }
2704
+ /**
2705
+ * Book a service appointment in a single call.
2706
+ *
2707
+ * Orchestrates three steps:
2708
+ * 1. `client.availability.getServiceSlots()` — verify available slots for the date
2709
+ * 2. `client.guests.create()` — create the guest if inline data was provided
2710
+ * 3. `client.bookings.create()` — create and auto-confirm the appointment booking
2711
+ *
2712
+ * @throws {Error} if no appointment slots are available for the requested date
2713
+ */
2714
+ async bookAppointment(input) {
2715
+ const slots = await this.client.availability.getServiceSlots({
2716
+ propertyId: input.propertyId,
2717
+ date: input.date,
2718
+ providerId: input.providerId,
2719
+ categoryId: input.categoryId,
2720
+ duration: input.duration ?? 60
2721
+ });
2722
+ if (slots.length === 0) {
2723
+ throw new Error("No appointment slots available");
2724
+ }
2725
+ const guestId = typeof input.guest === "string" ? input.guest : (await this.client.guests.create(input.guest)).id;
2726
+ const duration = input.duration ?? 60;
2727
+ const checkIn = toISODateTime(input.date, input.time);
2728
+ const checkOut = toISODateTime(input.date, addMinutes(input.time, duration));
2729
+ const booking = await this.client.bookings.create({
2730
+ propertyId: input.propertyId,
2731
+ categoryId: input.categoryId,
2732
+ guestId,
2733
+ checkIn,
2734
+ checkOut,
2735
+ type: "service",
2736
+ notes: input.notes,
2737
+ autoConfirm: true
2738
+ });
2739
+ return { booking, guestId };
2740
+ }
2741
+ /**
2742
+ * Get available service appointment slots for a specific date.
2743
+ *
2744
+ * Delegates to `client.availability.getServiceSlots()`.
2745
+ */
2746
+ async getSlots(params) {
2747
+ return this.client.availability.getServiceSlots(params);
2748
+ }
2749
+ /**
2750
+ * Get the service menu for a property — all bookable service categories with
2751
+ * their base price and default duration.
2752
+ *
2753
+ * Calls `client.categories.list()` and maps each `SpaceCategory` to a
2754
+ * `ServiceMenuItem`. The `maxOccupancy` field on categories is used as the
2755
+ * default appointment duration for the Services vertical.
2756
+ */
2757
+ async getMenu(propertyId) {
2758
+ const result = await this.client.categories.list({ propertyId });
2759
+ return result.data.map((cat) => ({
2760
+ categoryId: cat.id,
2761
+ name: cat.name,
2762
+ description: cat.description ?? null,
2763
+ basePrice: cat.basePrice,
2764
+ // For the Services vertical, maxOccupancy stores the default duration
2765
+ duration: cat.maxOccupancy ?? null
2766
+ }));
2767
+ }
2768
+ /**
2769
+ * Get a provider's availability schedule across a date range.
2770
+ *
2771
+ * Calls `client.availability.getServiceSlots()` once per day from `from` to
2772
+ * `to` (exclusive), capped at 31 days. Each day is returned as a
2773
+ * `ProviderScheduleDay` with its individual time slots.
2774
+ *
2775
+ * @param params.from - Start date in YYYY-MM-DD format (inclusive)
2776
+ * @param params.to - End date in YYYY-MM-DD format (exclusive, max 31 days from `from`)
2777
+ */
2778
+ async getProviderSchedule(params) {
2779
+ const days = dateDiffDays2(params.from, params.to);
2780
+ const cappedDays = Math.min(days, 31);
2781
+ const schedule = [];
2782
+ for (let i = 0; i < cappedDays; i++) {
2783
+ const date = addDaysToDate(params.from, i);
2784
+ const slots = await this.client.availability.getServiceSlots({
2785
+ propertyId: params.propertyId,
2786
+ date,
2787
+ providerId: params.providerId
2788
+ });
2789
+ schedule.push({
2790
+ date,
2791
+ slots: slots.map((s) => ({
2792
+ startTime: s.startTime,
2793
+ endTime: s.endTime,
2794
+ available: s.available
2795
+ }))
2796
+ });
2797
+ }
2798
+ return schedule;
2799
+ }
2800
+ /**
2801
+ * Reschedule an existing appointment to a new date and time.
2802
+ *
2803
+ * Verifies slot availability for the new datetime via
2804
+ * `client.availability.getServiceSlots()`, then updates the booking via
2805
+ * `client.bookings.update()`.
2806
+ *
2807
+ * @throws {Error} if no slots are available for the new date/time
2808
+ */
2809
+ async reschedule(input) {
2810
+ const current = await this.client.bookings.get(input.bookingId);
2811
+ const duration = input.duration ?? 60;
2812
+ const slots = await this.client.availability.getServiceSlots({
2813
+ propertyId: current.propertyId,
2814
+ date: input.newDate,
2815
+ categoryId: current.categoryId ?? void 0,
2816
+ duration
2817
+ });
2818
+ if (slots.length === 0) {
2819
+ throw new Error("No slots available for new time");
2820
+ }
2821
+ const checkIn = toISODateTime(input.newDate, input.newTime);
2822
+ const checkOut = toISODateTime(input.newDate, addMinutes(input.newTime, duration));
2823
+ return this.client.bookings.update(input.bookingId, {
2824
+ checkIn,
2825
+ checkOut
2826
+ });
2827
+ }
2828
+ };
2829
+ function toDateString(date) {
2830
+ const y = date.getUTCFullYear();
2831
+ const m = String(date.getUTCMonth() + 1).padStart(2, "0");
2832
+ const d = String(date.getUTCDate()).padStart(2, "0");
2833
+ return `${y}-${m}-${d}`;
2834
+ }
2835
+ function toISODateTime(date, time) {
2836
+ return `${date}T${time}:00.000Z`;
2837
+ }
2838
+ function addMinutes(time, mins) {
2839
+ const [hourStr, minuteStr] = time.split(":");
2840
+ const totalMinutes = Number(hourStr) * 60 + Number(minuteStr) + mins;
2841
+ const h = Math.floor(totalMinutes / 60) % 24;
2842
+ const m = totalMinutes % 60;
2843
+ return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
2844
+ }
2845
+ function dateDiffDays2(start, end) {
2846
+ const parseDateStr2 = (s) => {
2847
+ const parts = s.split("-");
2848
+ return [Number(parts[0]), Number(parts[1]), Number(parts[2])];
2849
+ };
2850
+ const [sy, sm, sd] = parseDateStr2(start);
2851
+ const [ey, em, ed] = parseDateStr2(end);
2852
+ const startMs = Date.UTC(sy, sm - 1, sd);
2853
+ const endMs = Date.UTC(ey, em - 1, ed);
2854
+ return Math.max(0, Math.floor((endMs - startMs) / 864e5));
2855
+ }
2856
+ function addDaysToDate(dateStr, days) {
2857
+ const parts = dateStr.split("-");
2858
+ const year = Number(parts[0]);
2859
+ const month = Number(parts[1]);
2860
+ const day = Number(parts[2]);
2861
+ return toDateString(new Date(Date.UTC(year, month - 1, day + days)));
2862
+ }
2863
+
2864
+ // src/services/settings.ts
2865
+ var SettingsService = class extends BaseService {
2866
+ constructor() {
2867
+ super(...arguments);
2868
+ this.basePath = "/settings/v1";
2869
+ }
2870
+ /** Get property-level settings */
2871
+ getPropertySettings() {
2872
+ return this._get(this._buildPath("property"));
2873
+ }
2874
+ /** Update property-level settings */
2875
+ updatePropertySettings(input) {
2876
+ return this._patch(this._buildPath("property"), input);
2877
+ }
2878
+ /** Get fiscal compliance settings (myDATA and TSE) */
2879
+ getFiscalSettings() {
2880
+ return this._get(this._buildPath("fiscal"));
2881
+ }
2882
+ /** Update fiscal compliance settings (myDATA and TSE) */
2883
+ updateFiscalSettings(input) {
2884
+ return this._patch(this._buildPath("fiscal"), input);
2885
+ }
2886
+ };
2887
+
2209
2888
  // src/services/spaces.ts
2210
2889
  var SpacesService = class extends BaseService {
2211
2890
  constructor() {
@@ -2398,6 +3077,157 @@ var StaffService = class extends BaseService {
2398
3077
  }
2399
3078
  };
2400
3079
 
3080
+ // src/services/stays.ts
3081
+ var StaysHelper = class {
3082
+ constructor(client) {
3083
+ this.client = client;
3084
+ }
3085
+ /**
3086
+ * Book a stay in a single call.
3087
+ *
3088
+ * Orchestrates four steps:
3089
+ * 1. `client.availability.check()` — verify availability for the date range
3090
+ * 2. `client.guests.create()` — create the guest if inline data was provided
3091
+ * 3. `client.bookings.create()` — create the booking
3092
+ * 4. `client.bookings.confirm()` — confirm if `autoConfirm` is true
3093
+ *
3094
+ * @throws {Error} if no availability exists for the requested dates
3095
+ */
3096
+ async book(input) {
3097
+ const avail = await this.client.availability.check({
3098
+ propertyId: input.propertyId,
3099
+ categoryId: input.categoryId,
3100
+ checkIn: input.checkIn,
3101
+ checkOut: input.checkOut,
3102
+ guests: input.guests,
3103
+ spaceId: input.spaceId
3104
+ });
3105
+ if (!avail.available) {
3106
+ throw new Error("No availability for requested dates");
3107
+ }
3108
+ const guestId = typeof input.guest === "string" ? input.guest : (await this.client.guests.create(input.guest)).id;
3109
+ const booking = await this.client.bookings.create({
3110
+ propertyId: input.propertyId,
3111
+ categoryId: input.categoryId,
3112
+ guestId,
3113
+ checkIn: input.checkIn,
3114
+ checkOut: input.checkOut,
3115
+ type: "stay",
3116
+ guests: input.guests,
3117
+ spaceId: input.spaceId,
3118
+ notes: input.notes,
3119
+ source: input.source,
3120
+ rateId: input.rateId
3121
+ });
3122
+ let confirmed = false;
3123
+ if (input.autoConfirm) {
3124
+ await this.client.bookings.confirm(booking.id);
3125
+ confirmed = true;
3126
+ }
3127
+ return { booking, guestId, confirmed };
3128
+ }
3129
+ /**
3130
+ * Extend the checkout date of an existing stay.
3131
+ *
3132
+ * Verifies availability for the extension period (original checkout → new
3133
+ * checkout) via `client.availability.check()` before updating the booking
3134
+ * via `client.bookings.update()`.
3135
+ *
3136
+ * @throws {Error} if no availability exists for the extension period
3137
+ */
3138
+ async extend(input) {
3139
+ const current = await this.client.bookings.get(input.bookingId);
3140
+ const avail = await this.client.availability.check({
3141
+ propertyId: current.propertyId,
3142
+ checkIn: current.checkOut,
3143
+ checkOut: input.newCheckOut,
3144
+ categoryId: current.categoryId ?? void 0,
3145
+ spaceId: current.spaceId ?? void 0
3146
+ });
3147
+ if (!avail.available) {
3148
+ throw new Error("No availability for extension period");
3149
+ }
3150
+ return this.client.bookings.update(input.bookingId, {
3151
+ checkOut: input.newCheckOut
3152
+ });
3153
+ }
3154
+ /**
3155
+ * Check a guest out early.
3156
+ *
3157
+ * Updates the checkout date to today via `client.bookings.update()`, then
3158
+ * performs the check-out lifecycle transition via `client.bookings.checkOut()`.
3159
+ */
3160
+ async earlyCheckout(input) {
3161
+ const today = toDateString2(/* @__PURE__ */ new Date());
3162
+ await this.client.bookings.update(input.bookingId, { checkOut: today });
3163
+ return this.client.bookings.checkOut(input.bookingId, {
3164
+ actualDeparture: input.actualDeparture,
3165
+ notes: input.notes
3166
+ });
3167
+ }
3168
+ /**
3169
+ * Get all confirmed bookings arriving on a given date.
3170
+ *
3171
+ * Calls `client.bookings.list()` filtered by `status: "confirmed"`,
3172
+ * `type: "stay"`, and `checkInFrom/checkInTo` equal to the target date.
3173
+ *
3174
+ * @param params.date - Defaults to today if not provided
3175
+ */
3176
+ async getArrivals(params) {
3177
+ const date = params.date ?? toDateString2(/* @__PURE__ */ new Date());
3178
+ const result = await this.client.bookings.list({
3179
+ propertyId: params.propertyId,
3180
+ status: "confirmed",
3181
+ type: "stay",
3182
+ checkInFrom: date,
3183
+ checkInTo: date
3184
+ });
3185
+ return result.data;
3186
+ }
3187
+ /**
3188
+ * Get all checked-in bookings departing on a given date.
3189
+ *
3190
+ * Calls `client.bookings.list()` filtered by `status: "checked_in"`,
3191
+ * `type: "stay"`, and `checkOutFrom/checkOutTo` equal to the target date.
3192
+ *
3193
+ * @param params.date - Defaults to today if not provided
3194
+ */
3195
+ async getDepartures(params) {
3196
+ const date = params.date ?? toDateString2(/* @__PURE__ */ new Date());
3197
+ const result = await this.client.bookings.list({
3198
+ propertyId: params.propertyId,
3199
+ status: "checked_in",
3200
+ type: "stay",
3201
+ checkOutFrom: date,
3202
+ checkOutTo: date
3203
+ });
3204
+ return result.data;
3205
+ }
3206
+ /**
3207
+ * Get a composite summary for a booking — booking record plus its folio.
3208
+ *
3209
+ * Calls `client.bookings.get()` and `client.finance.listFolios()`. If the
3210
+ * finance service fails (e.g., folio not found), the folio is set to `null`
3211
+ * and no error is propagated.
3212
+ */
3213
+ async getSummary(bookingId) {
3214
+ const booking = await this.client.bookings.get(bookingId);
3215
+ let folio = null;
3216
+ try {
3217
+ const folios = await this.client.finance.listFolios({ bookingId });
3218
+ folio = folios.data[0] ?? null;
3219
+ } catch {
3220
+ }
3221
+ return { booking, folio };
3222
+ }
3223
+ };
3224
+ function toDateString2(date) {
3225
+ const y = date.getUTCFullYear();
3226
+ const m = String(date.getUTCMonth() + 1).padStart(2, "0");
3227
+ const d = String(date.getUTCDate()).padStart(2, "0");
3228
+ return `${y}-${m}-${d}`;
3229
+ }
3230
+
2401
3231
  // src/services/supply.ts
2402
3232
  var SupplyService = class extends BaseService {
2403
3233
  constructor() {
@@ -2488,6 +3318,169 @@ var SupplyService = class extends BaseService {
2488
3318
  }
2489
3319
  };
2490
3320
 
3321
+ // src/services/tables.ts
3322
+ var TablesHelper = class {
3323
+ constructor(client) {
3324
+ this.client = client;
3325
+ }
3326
+ /**
3327
+ * Reserve a table in a single call.
3328
+ *
3329
+ * Orchestrates three steps:
3330
+ * 1. `client.availability.getTableSlots()` — verify available slots for the date
3331
+ * 2. `client.guests.create()` — create the guest if inline data was provided
3332
+ * 3. `client.bookings.create()` — create and auto-confirm the booking
3333
+ *
3334
+ * @throws {Error} if no table slots are available for the requested date
3335
+ */
3336
+ async reserve(input) {
3337
+ const slots = await this.client.availability.getTableSlots({
3338
+ propertyId: input.propertyId,
3339
+ date: input.date,
3340
+ guests: input.guests,
3341
+ categoryId: input.categoryId,
3342
+ duration: input.duration ?? 90
3343
+ });
3344
+ if (slots.length === 0) {
3345
+ throw new Error("No table slots available");
3346
+ }
3347
+ const guestId = typeof input.guest === "string" ? input.guest : (await this.client.guests.create(input.guest)).id;
3348
+ const duration = input.duration ?? 90;
3349
+ const checkIn = toISODateTime2(input.date, input.time);
3350
+ const checkOut = toISODateTime2(input.date, addMinutes2(input.time, duration));
3351
+ const booking = await this.client.bookings.create({
3352
+ propertyId: input.propertyId,
3353
+ categoryId: input.categoryId ?? "default",
3354
+ guestId,
3355
+ checkIn,
3356
+ checkOut,
3357
+ type: "table",
3358
+ guests: input.guests,
3359
+ spaceId: input.spaceId,
3360
+ notes: input.notes,
3361
+ autoConfirm: true
3362
+ });
3363
+ return { booking, guestId };
3364
+ }
3365
+ /**
3366
+ * Get available table time slots for a specific date.
3367
+ *
3368
+ * Delegates to `client.availability.getTableSlots()`.
3369
+ */
3370
+ async getSlots(params) {
3371
+ return this.client.availability.getTableSlots(params);
3372
+ }
3373
+ /**
3374
+ * Build a floor plan showing every table and its current reservation status.
3375
+ *
3376
+ * Calls `client.spaces.list()` to retrieve all table spaces, then
3377
+ * `client.bookings.list()` to retrieve active bookings for the date,
3378
+ * and maps each space to a `FloorPlanTable` with its computed status.
3379
+ *
3380
+ * Status rules:
3381
+ * - `occupied` — booking with status `checked_in`
3382
+ * - `reserved` — booking with status `confirmed`
3383
+ * - `available` — no active booking found for the space
3384
+ */
3385
+ async getFloorPlan(params) {
3386
+ const spacesResult = await this.client.spaces.list({
3387
+ propertyId: params.propertyId,
3388
+ type: "table"
3389
+ });
3390
+ const date = params.date ?? toDateString3(/* @__PURE__ */ new Date());
3391
+ const bookingsResult = await this.client.bookings.list({
3392
+ propertyId: params.propertyId,
3393
+ type: "table",
3394
+ status: ["confirmed", "checked_in"],
3395
+ checkInFrom: date,
3396
+ checkInTo: date
3397
+ });
3398
+ const bookingBySpace = /* @__PURE__ */ new Map();
3399
+ for (const bk of bookingsResult.data) {
3400
+ if (bk.spaceId) {
3401
+ bookingBySpace.set(bk.spaceId, bk.id);
3402
+ }
3403
+ }
3404
+ return spacesResult.data.map((space) => {
3405
+ const bookingId = bookingBySpace.get(space.id) ?? null;
3406
+ let status = "available";
3407
+ if (bookingId) {
3408
+ const bk = bookingsResult.data.find((b) => b.id === bookingId);
3409
+ status = bk?.status === "checked_in" ? "occupied" : "reserved";
3410
+ }
3411
+ return {
3412
+ spaceId: space.id,
3413
+ name: space.name,
3414
+ capacity: space.capacity ?? 0,
3415
+ floor: space.floor ?? null,
3416
+ status,
3417
+ bookingId
3418
+ };
3419
+ });
3420
+ }
3421
+ /**
3422
+ * Get all waitlist bookings for a property, ordered FIFO (oldest first).
3423
+ *
3424
+ * Calls `client.bookings.list()` filtered by `status: "waitlist"` and
3425
+ * `type: "table"`, sorted by `createdAt` ascending.
3426
+ */
3427
+ async getWaitlist(propertyId) {
3428
+ const result = await this.client.bookings.list({
3429
+ propertyId,
3430
+ status: "waitlist",
3431
+ type: "table",
3432
+ sort: { field: "createdAt", direction: "asc" }
3433
+ });
3434
+ return result.data;
3435
+ }
3436
+ /**
3437
+ * Add a guest to the waitlist for a date and time.
3438
+ *
3439
+ * Resolves or creates the guest via `client.guests.create()` if inline data
3440
+ * is provided, then creates a booking via `client.bookings.create()` with
3441
+ * `metadata.waitlist: true`. The booking starts in `pending` status.
3442
+ */
3443
+ async addToWaitlist(input) {
3444
+ const guestId = typeof input.guest === "string" ? input.guest : (await this.client.guests.create(input.guest)).id;
3445
+ const checkIn = toISODateTime2(input.date, input.time);
3446
+ return this.client.bookings.create({
3447
+ propertyId: input.propertyId,
3448
+ categoryId: "default",
3449
+ guestId,
3450
+ checkIn,
3451
+ checkOut: checkIn,
3452
+ type: "table",
3453
+ guests: input.guests,
3454
+ notes: input.notes,
3455
+ metadata: { waitlist: true }
3456
+ });
3457
+ }
3458
+ /**
3459
+ * Remove a booking from the waitlist.
3460
+ *
3461
+ * Calls `client.bookings.delete()` on the given booking ID.
3462
+ */
3463
+ async removeFromWaitlist(bookingId) {
3464
+ await this.client.bookings.delete(bookingId);
3465
+ }
3466
+ };
3467
+ function toDateString3(date) {
3468
+ const y = date.getUTCFullYear();
3469
+ const m = String(date.getUTCMonth() + 1).padStart(2, "0");
3470
+ const d = String(date.getUTCDate()).padStart(2, "0");
3471
+ return `${y}-${m}-${d}`;
3472
+ }
3473
+ function toISODateTime2(date, time) {
3474
+ return `${date}T${time}:00.000Z`;
3475
+ }
3476
+ function addMinutes2(time, mins) {
3477
+ const [hourStr, minuteStr] = time.split(":");
3478
+ const totalMinutes = Number(hourStr) * 60 + Number(minuteStr) + mins;
3479
+ const h = Math.floor(totalMinutes / 60) % 24;
3480
+ const m = totalMinutes % 60;
3481
+ return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
3482
+ }
3483
+
2491
3484
  // src/services/tasks.ts
2492
3485
  var TasksService = class extends BaseService {
2493
3486
  constructor() {
@@ -2519,10 +3512,338 @@ var TasksService = class extends BaseService {
2519
3512
  }
2520
3513
  };
2521
3514
 
3515
+ // src/services/webhooks.ts
3516
+ var WebhooksService = class extends BaseService {
3517
+ constructor() {
3518
+ super(...arguments);
3519
+ this.basePath = "/webhooks/v1";
3520
+ }
3521
+ /** Create a new webhook subscription */
3522
+ createSubscription(input) {
3523
+ return this._post(this._buildPath("subscriptions"), input);
3524
+ }
3525
+ /** List webhook subscriptions with optional filters */
3526
+ listSubscriptions(params) {
3527
+ if (!params) {
3528
+ return this._get(this._buildPath("subscriptions"));
3529
+ }
3530
+ const query = {};
3531
+ if (params.active !== void 0) query.active = params.active;
3532
+ if (params.limit !== void 0) query.limit = params.limit;
3533
+ if (params.cursor !== void 0) query.cursor = params.cursor;
3534
+ return this._get(this._buildPath("subscriptions"), query);
3535
+ }
3536
+ /** Update a webhook subscription */
3537
+ updateSubscription(subscriptionId, input) {
3538
+ return this._patch(
3539
+ this._buildPath("subscriptions", subscriptionId),
3540
+ input
3541
+ );
3542
+ }
3543
+ /** List webhook delivery attempts with optional filters */
3544
+ listDeliveries(params) {
3545
+ if (!params) {
3546
+ return this._get(this._buildPath("deliveries"));
3547
+ }
3548
+ const query = {};
3549
+ if (params.subscriptionId !== void 0) query.subscriptionId = params.subscriptionId;
3550
+ if (params.status !== void 0) query.status = params.status;
3551
+ if (params.from !== void 0) query.from = params.from;
3552
+ if (params.to !== void 0) query.to = params.to;
3553
+ if (params.limit !== void 0) query.limit = params.limit;
3554
+ if (params.cursor !== void 0) query.cursor = params.cursor;
3555
+ return this._get(this._buildPath("deliveries"), query);
3556
+ }
3557
+ };
3558
+
3559
+ // src/sse.ts
3560
+ var SSEClient = class {
3561
+ /**
3562
+ * Create a new `SSEClient`.
3563
+ *
3564
+ * @param baseUrl - Base URL of the booking platform API (e.g., `"https://api.atzentis.io"`).
3565
+ * @param apiKey - API key used to authenticate the SSE stream request.
3566
+ * @param config - Optional client configuration for reconnect behaviour and custom `EventSource`.
3567
+ */
3568
+ constructor(baseUrl, apiKey, config) {
3569
+ // Connection state
3570
+ this.eventSource = null;
3571
+ this._state = "disconnected";
3572
+ this._connectedAt = null;
3573
+ this._lastEventAt = null;
3574
+ this._lastEventId = null;
3575
+ // Reconnect state
3576
+ this._reconnectAttempts = 0;
3577
+ this._reconnectTimer = null;
3578
+ this._isDisconnecting = false;
3579
+ /**
3580
+ * Internal handler registry.
3581
+ *
3582
+ * Keys are event type strings (including wildcards). The value type is
3583
+ * intentionally `SSEEventHandler<any>` here because the Map must hold
3584
+ * handlers for many different event types — the public API enforces correct
3585
+ * typing through the overloaded `on()` and `off()` signatures.
3586
+ */
3587
+ // biome-ignore lint/suspicious/noExplicitAny: registry holds mixed handler types
3588
+ this.handlers = /* @__PURE__ */ new Map();
3589
+ this.baseUrl = baseUrl;
3590
+ this.apiKey = apiKey;
3591
+ this.config = {
3592
+ initialReconnectDelay: config?.initialReconnectDelay ?? 1e3,
3593
+ maxReconnectDelay: config?.maxReconnectDelay ?? 3e4,
3594
+ maxReconnectAttempts: config?.maxReconnectAttempts ?? Number.POSITIVE_INFINITY
3595
+ };
3596
+ this.EventSourceImpl = config?.EventSource ?? globalThis.EventSource;
3597
+ }
3598
+ // -------------------------------------------------------------------------
3599
+ // Public API
3600
+ // -------------------------------------------------------------------------
3601
+ /**
3602
+ * Open the SSE connection to the platform stream.
3603
+ *
3604
+ * If a connection is already active it is closed and a new one is opened
3605
+ * with the supplied options. The `lastEventId` tracking from a previous
3606
+ * session is preserved for automatic replay unless explicitly overridden in
3607
+ * `options.lastEventId`.
3608
+ *
3609
+ * @param options - Optional filters for channels, property, and replay cursor.
3610
+ */
3611
+ connect(options) {
3612
+ if (this.eventSource) {
3613
+ this._closeEventSource();
3614
+ }
3615
+ this._isDisconnecting = false;
3616
+ this._connectOptions = options;
3617
+ this._state = "connecting";
3618
+ const url = this._buildUrl(options);
3619
+ this.eventSource = new this.EventSourceImpl(url);
3620
+ this.eventSource.onopen = () => {
3621
+ this._state = "connected";
3622
+ this._connectedAt = (/* @__PURE__ */ new Date()).toISOString();
3623
+ this._reconnectAttempts = 0;
3624
+ this._emit("connection.opened", {
3625
+ type: "connection.opened",
3626
+ id: this._generateId("conn"),
3627
+ timestamp: this._connectedAt,
3628
+ propertyId: options?.propertyId ?? "",
3629
+ data: { connectedAt: this._connectedAt }
3630
+ });
3631
+ };
3632
+ this.eventSource.onerror = () => {
3633
+ if (this._isDisconnecting) return;
3634
+ this._emit("connection.error", {
3635
+ type: "connection.error",
3636
+ id: this._generateId("err"),
3637
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3638
+ propertyId: this._connectOptions?.propertyId ?? "",
3639
+ data: { error: "Connection lost", recoverable: true }
3640
+ });
3641
+ this._scheduleReconnect();
3642
+ };
3643
+ this.eventSource.onmessage = (event) => {
3644
+ this._handleMessage(event);
3645
+ };
3646
+ }
3647
+ /**
3648
+ * Close the SSE connection and cancel any pending reconnect timer.
3649
+ *
3650
+ * Emits a `connection.closed` lifecycle event with `wasClean: true` if the
3651
+ * client was connected or connecting at the time of the call.
3652
+ */
3653
+ disconnect() {
3654
+ this._isDisconnecting = true;
3655
+ this._clearReconnectTimer();
3656
+ this._closeEventSource();
3657
+ const wasConnected = this._state !== "disconnected";
3658
+ this._state = "disconnected";
3659
+ this._reconnectAttempts = 0;
3660
+ if (wasConnected) {
3661
+ this._emit("connection.closed", {
3662
+ type: "connection.closed",
3663
+ id: this._generateId("close"),
3664
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3665
+ propertyId: this._connectOptions?.propertyId ?? "",
3666
+ data: { reason: "Client disconnected", wasClean: true }
3667
+ });
3668
+ }
3669
+ }
3670
+ on(eventType, handler) {
3671
+ if (!this.handlers.has(eventType)) {
3672
+ this.handlers.set(eventType, /* @__PURE__ */ new Set());
3673
+ }
3674
+ this.handlers.get(eventType)?.add(handler);
3675
+ }
3676
+ off(eventType, handler) {
3677
+ const set = this.handlers.get(eventType);
3678
+ if (set) {
3679
+ set.delete(handler);
3680
+ if (set.size === 0) this.handlers.delete(eventType);
3681
+ }
3682
+ }
3683
+ /**
3684
+ * Return a snapshot of the current connection status.
3685
+ *
3686
+ * This is a pure read — calling it has no side effects.
3687
+ */
3688
+ getStatus() {
3689
+ return {
3690
+ state: this._state,
3691
+ reconnectAttempts: this._reconnectAttempts,
3692
+ connectedAt: this._connectedAt,
3693
+ lastEventAt: this._lastEventAt,
3694
+ lastEventId: this._lastEventId
3695
+ };
3696
+ }
3697
+ // -------------------------------------------------------------------------
3698
+ // Internal methods
3699
+ // -------------------------------------------------------------------------
3700
+ /**
3701
+ * Build the full SSE stream URL including query parameters.
3702
+ *
3703
+ * The API key is always appended. Optional filters for channels, property ID,
3704
+ * and last-event-id for replay are appended when present.
3705
+ */
3706
+ _buildUrl(options) {
3707
+ const url = new URL("/sse/v1/stream", this.baseUrl);
3708
+ url.searchParams.set("apiKey", this.apiKey);
3709
+ if (options?.channels && options.channels.length > 0) {
3710
+ url.searchParams.set("channels", options.channels.join(","));
3711
+ }
3712
+ if (options?.propertyId) {
3713
+ url.searchParams.set("propertyId", options.propertyId);
3714
+ }
3715
+ const lastEventId = options?.lastEventId ?? this._lastEventId;
3716
+ if (lastEventId) {
3717
+ url.searchParams.set("lastEventId", lastEventId);
3718
+ }
3719
+ return url.toString();
3720
+ }
3721
+ /**
3722
+ * Parse and dispatch an incoming `MessageEvent` from the `EventSource`.
3723
+ *
3724
+ * Malformed JSON is silently ignored to keep the connection stable.
3725
+ */
3726
+ _handleMessage(event) {
3727
+ try {
3728
+ const parsed = JSON.parse(event.data);
3729
+ this._lastEventAt = (/* @__PURE__ */ new Date()).toISOString();
3730
+ if (parsed.id) this._lastEventId = parsed.id;
3731
+ this._emit(parsed.type, parsed);
3732
+ } catch {
3733
+ }
3734
+ }
3735
+ /**
3736
+ * Dispatch an event to all matching handlers in the registry.
3737
+ *
3738
+ * Dispatch order:
3739
+ * 1. Handlers registered for the exact event type string.
3740
+ * 2. Handlers registered for the channel wildcard (e.g., `"booking.*"`).
3741
+ * 3. Handlers registered for the global wildcard (`"*"`).
3742
+ */
3743
+ _emit(eventType, event) {
3744
+ const specific = this.handlers.get(eventType);
3745
+ if (specific) {
3746
+ for (const handler of specific) handler(event);
3747
+ }
3748
+ const channel = eventType.split(".")[0];
3749
+ const channelWildcard = this.handlers.get(`${channel}.*`);
3750
+ if (channelWildcard && eventType !== `${channel}.*`) {
3751
+ for (const handler of channelWildcard) handler(event);
3752
+ }
3753
+ const global = this.handlers.get("*");
3754
+ if (global && eventType !== "*") {
3755
+ for (const handler of global) handler(event);
3756
+ }
3757
+ }
3758
+ /**
3759
+ * Schedule a reconnect attempt using exponential backoff with jitter.
3760
+ *
3761
+ * Closes the current `EventSource`, increments the attempt counter, emits
3762
+ * a `connection.reconnecting` lifecycle event, then calls `connect()` after
3763
+ * the computed delay.
3764
+ *
3765
+ * If `maxReconnectAttempts` is exceeded the client enters `disconnected`
3766
+ * state and emits a final `connection.closed` lifecycle event.
3767
+ */
3768
+ _scheduleReconnect() {
3769
+ this._closeEventSource();
3770
+ if (this._isDisconnecting) return;
3771
+ if (this._reconnectAttempts >= this.config.maxReconnectAttempts) {
3772
+ this._state = "disconnected";
3773
+ this._emit("connection.closed", {
3774
+ type: "connection.closed",
3775
+ id: this._generateId("close"),
3776
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3777
+ propertyId: this._connectOptions?.propertyId ?? "",
3778
+ data: { reason: "Max reconnect attempts exceeded", wasClean: false }
3779
+ });
3780
+ return;
3781
+ }
3782
+ this._state = "reconnecting";
3783
+ this._reconnectAttempts++;
3784
+ const base = Math.min(
3785
+ this.config.initialReconnectDelay * 2 ** (this._reconnectAttempts - 1),
3786
+ this.config.maxReconnectDelay
3787
+ );
3788
+ const delay = base + Math.random() * 1e3;
3789
+ this._emit("connection.reconnecting", {
3790
+ type: "connection.reconnecting",
3791
+ id: this._generateId("reconn"),
3792
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3793
+ propertyId: this._connectOptions?.propertyId ?? "",
3794
+ data: { attempt: this._reconnectAttempts, delay: Math.round(delay) }
3795
+ });
3796
+ this._reconnectTimer = setTimeout(() => {
3797
+ if (!this._isDisconnecting) {
3798
+ this.connect(this._connectOptions);
3799
+ }
3800
+ }, delay);
3801
+ }
3802
+ /**
3803
+ * Detach all event listeners and close the underlying `EventSource`.
3804
+ *
3805
+ * Listeners are removed before calling `close()` to prevent the `onerror`
3806
+ * callback from firing during a deliberate teardown.
3807
+ */
3808
+ _closeEventSource() {
3809
+ if (this.eventSource) {
3810
+ this.eventSource.onopen = null;
3811
+ this.eventSource.onerror = null;
3812
+ this.eventSource.onmessage = null;
3813
+ this.eventSource.close();
3814
+ this.eventSource = null;
3815
+ }
3816
+ }
3817
+ /**
3818
+ * Cancel the pending reconnect timer if one is scheduled.
3819
+ */
3820
+ _clearReconnectTimer() {
3821
+ if (this._reconnectTimer !== null) {
3822
+ clearTimeout(this._reconnectTimer);
3823
+ this._reconnectTimer = null;
3824
+ }
3825
+ }
3826
+ /**
3827
+ * Generate a lightweight unique ID for synthetic lifecycle events.
3828
+ *
3829
+ * Uses `crypto.randomUUID()` when available (browsers, Node 19+, Bun).
3830
+ * Falls back to a timestamp-based string in older environments.
3831
+ *
3832
+ * @param prefix - Short label for readability (e.g., `"conn"`, `"err"`).
3833
+ */
3834
+ _generateId(prefix) {
3835
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3836
+ return crypto.randomUUID();
3837
+ }
3838
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
3839
+ }
3840
+ };
3841
+
2522
3842
  // src/client.ts
2523
3843
  var BookingClient = class {
2524
3844
  constructor(config) {
2525
3845
  const validated = bookingClientConfigSchema.parse(config);
3846
+ this._config = validated;
2526
3847
  this.httpClient = new HttpClient({
2527
3848
  baseUrl: validated.baseUrl,
2528
3849
  apiKey: validated.apiKey,
@@ -2546,6 +3867,11 @@ var BookingClient = class {
2546
3867
  this._bookings ?? (this._bookings = new BookingsService(this.httpClient));
2547
3868
  return this._bookings;
2548
3869
  }
3870
+ /** Concierge service — lazy-initialized on first access */
3871
+ get concierge() {
3872
+ this._concierge ?? (this._concierge = new ConciergeService(this.httpClient));
3873
+ return this._concierge;
3874
+ }
2549
3875
  /** Distribution service — lazy-initialized on first access */
2550
3876
  get distribution() {
2551
3877
  this._distribution ?? (this._distribution = new DistributionService(this.httpClient));
@@ -2556,6 +3882,11 @@ var BookingClient = class {
2556
3882
  this._finance ?? (this._finance = new FinanceService(this.httpClient));
2557
3883
  return this._finance;
2558
3884
  }
3885
+ /** Fiscal service — lazy-initialized on first access */
3886
+ get fiscal() {
3887
+ this._fiscal ?? (this._fiscal = new FiscalService(this.httpClient));
3888
+ return this._fiscal;
3889
+ }
2559
3890
  /** Groups service — lazy-initialized on first access */
2560
3891
  get groups() {
2561
3892
  this._groups ?? (this._groups = new GroupsService(this.httpClient));
@@ -2571,16 +3902,36 @@ var BookingClient = class {
2571
3902
  this._housekeeping ?? (this._housekeeping = new HousekeepingService(this.httpClient));
2572
3903
  return this._housekeeping;
2573
3904
  }
3905
+ /** ID scanning service — lazy-initialized on first access */
3906
+ get idScanning() {
3907
+ this._idScanning ?? (this._idScanning = new IdScanningService(this.httpClient));
3908
+ return this._idScanning;
3909
+ }
3910
+ /** Intelligence service — lazy-initialized on first access */
3911
+ get intelligence() {
3912
+ this._intelligence ?? (this._intelligence = new IntelligenceService(this.httpClient));
3913
+ return this._intelligence;
3914
+ }
2574
3915
  /** Night audit service — lazy-initialized on first access */
2575
3916
  get nightAudit() {
2576
3917
  this._nightAudit ?? (this._nightAudit = new NightAuditService(this.httpClient));
2577
3918
  return this._nightAudit;
2578
3919
  }
3920
+ /** Notifications service — lazy-initialized on first access */
3921
+ get notifications() {
3922
+ this._notifications ?? (this._notifications = new NotificationsService(this.httpClient));
3923
+ return this._notifications;
3924
+ }
2579
3925
  /** Payments service — lazy-initialized on first access */
2580
3926
  get payments() {
2581
3927
  this._payments ?? (this._payments = new PaymentsService(this.httpClient));
2582
3928
  return this._payments;
2583
3929
  }
3930
+ /** Portfolios service — lazy-initialized on first access */
3931
+ get portfolios() {
3932
+ this._portfolios ?? (this._portfolios = new PortfoliosService(this.httpClient));
3933
+ return this._portfolios;
3934
+ }
2584
3935
  /** Properties service — lazy-initialized on first access */
2585
3936
  get properties() {
2586
3937
  this._properties ?? (this._properties = new PropertiesService(this.httpClient));
@@ -2591,6 +3942,11 @@ var BookingClient = class {
2591
3942
  this._ratePlans ?? (this._ratePlans = new RatePlansService(this.httpClient));
2592
3943
  return this._ratePlans;
2593
3944
  }
3945
+ /** Revenue service — lazy-initialized on first access */
3946
+ get revenue() {
3947
+ this._revenue ?? (this._revenue = new RevenueService(this.httpClient));
3948
+ return this._revenue;
3949
+ }
2594
3950
  /** Categories service — lazy-initialized on first access */
2595
3951
  get categories() {
2596
3952
  this._categories ?? (this._categories = new CategoriesService(this.httpClient));
@@ -2606,6 +3962,11 @@ var BookingClient = class {
2606
3962
  this._reviews ?? (this._reviews = new ReviewsService(this.httpClient));
2607
3963
  return this._reviews;
2608
3964
  }
3965
+ /** Settings service — lazy-initialized on first access */
3966
+ get settings() {
3967
+ this._settings ?? (this._settings = new SettingsService(this.httpClient));
3968
+ return this._settings;
3969
+ }
2609
3970
  /** Spaces service — lazy-initialized on first access */
2610
3971
  get spaces() {
2611
3972
  this._spaces ?? (this._spaces = new SpacesService(this.httpClient));
@@ -2626,6 +3987,31 @@ var BookingClient = class {
2626
3987
  this._tasks ?? (this._tasks = new TasksService(this.httpClient));
2627
3988
  return this._tasks;
2628
3989
  }
3990
+ /** Webhooks service — lazy-initialized on first access */
3991
+ get webhooks() {
3992
+ this._webhooks ?? (this._webhooks = new WebhooksService(this.httpClient));
3993
+ return this._webhooks;
3994
+ }
3995
+ /** Stays vertical helper — lazy-initialized on first access */
3996
+ get stays() {
3997
+ this._stays ?? (this._stays = new StaysHelper(this));
3998
+ return this._stays;
3999
+ }
4000
+ /** Tables vertical helper — lazy-initialized on first access */
4001
+ get tables() {
4002
+ this._tables ?? (this._tables = new TablesHelper(this));
4003
+ return this._tables;
4004
+ }
4005
+ /** Services vertical helper — lazy-initialized on first access */
4006
+ get services() {
4007
+ this._services ?? (this._services = new ServicesHelper(this));
4008
+ return this._services;
4009
+ }
4010
+ /** SSE client — lazy-initialized on first access */
4011
+ get sse() {
4012
+ this._sse ?? (this._sse = new SSEClient(this._config.baseUrl, this._config.apiKey));
4013
+ return this._sse;
4014
+ }
2629
4015
  setApiKey(key) {
2630
4016
  if (!key || key.trim().length === 0) {
2631
4017
  throw new Error("apiKey must be a non-empty string");
@@ -2742,35 +4128,48 @@ var VERSION = "0.1.0";
2742
4128
  BookingError,
2743
4129
  BookingsService,
2744
4130
  CategoriesService,
4131
+ ConciergeService,
2745
4132
  ConflictError,
2746
4133
  DEFAULT_MODULES,
2747
4134
  DiscountsService,
2748
4135
  DistributionService,
2749
4136
  FinanceService,
4137
+ FiscalService,
2750
4138
  ForbiddenError,
2751
4139
  GroupsService,
2752
4140
  GuestsService,
2753
4141
  HousekeepingService,
2754
4142
  HttpClient,
4143
+ IdScanningService,
4144
+ IntelligenceService,
2755
4145
  NightAuditService,
2756
4146
  NotFoundError,
4147
+ NotificationsService,
2757
4148
  PROPERTY_MODULES,
2758
4149
  PaymentError,
2759
4150
  PaymentsService,
4151
+ PortfoliosService,
2760
4152
  PropertiesService,
2761
4153
  RateLimitError,
2762
4154
  RatePlansService,
4155
+ RevenueService,
2763
4156
  ReviewsService,
2764
4157
  SPACE_STATUSES,
2765
4158
  SPACE_TYPES,
4159
+ SSEClient,
2766
4160
  ServerError,
4161
+ ServicesHelper,
4162
+ SettingsService,
2767
4163
  SpacesService,
2768
4164
  StaffService,
4165
+ StaysHelper,
2769
4166
  SupplyService,
4167
+ TablesHelper,
2770
4168
  TasksService,
2771
4169
  TimeoutError,
2772
4170
  VERSION,
2773
4171
  ValidationError,
4172
+ WebhooksService,
2774
4173
  bookingClientConfigSchema,
2775
4174
  createErrorFromResponse,
2776
4175
  firstPage,