@atzentis/booking-sdk 0.1.3 → 0.1.5

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
@@ -28,6 +28,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
28
28
  var index_exports = {};
29
29
  __export(index_exports, {
30
30
  AuthenticationError: () => AuthenticationError,
31
+ AvailabilityService: () => AvailabilityService,
31
32
  BookingClient: () => BookingClient,
32
33
  BookingError: () => BookingError,
33
34
  CategoriesService: () => CategoriesService,
@@ -40,7 +41,10 @@ __export(index_exports, {
40
41
  PaymentError: () => PaymentError,
41
42
  PropertiesService: () => PropertiesService,
42
43
  RateLimitError: () => RateLimitError,
44
+ SPACE_STATUSES: () => SPACE_STATUSES,
45
+ SPACE_TYPES: () => SPACE_TYPES,
43
46
  ServerError: () => ServerError,
47
+ SpacesService: () => SpacesService,
44
48
  TimeoutError: () => TimeoutError,
45
49
  VERSION: () => VERSION,
46
50
  ValidationError: () => ValidationError,
@@ -520,6 +524,267 @@ var BaseService = class {
520
524
  }
521
525
  };
522
526
 
527
+ // src/services/availability.ts
528
+ var AvailabilityService = class extends BaseService {
529
+ constructor() {
530
+ super(...arguments);
531
+ this.basePath = "/booking/v1/availability";
532
+ }
533
+ /**
534
+ * Check availability for a property and date range.
535
+ *
536
+ * @param params - Must include `propertyId`, `checkIn`, `checkOut`; supports optional filters
537
+ *
538
+ * @example
539
+ * ```typescript
540
+ * const result = await booking.availability.check({
541
+ * propertyId: "prop_abc123",
542
+ * checkIn: "2025-06-01",
543
+ * checkOut: "2025-06-05",
544
+ * type: "room",
545
+ * guests: 2,
546
+ * });
547
+ * ```
548
+ */
549
+ check(params) {
550
+ const { propertyId, checkIn, checkOut, categoryId, spaceId, guests, type } = params;
551
+ return this._get(this.basePath, {
552
+ propertyId,
553
+ checkIn,
554
+ checkOut,
555
+ categoryId,
556
+ spaceId,
557
+ guests,
558
+ type
559
+ });
560
+ }
561
+ /**
562
+ * Search availability across multiple properties.
563
+ *
564
+ * @param params - Must include `propertyIds`, `checkIn`, `checkOut`; supports filtering and pagination
565
+ *
566
+ * @example
567
+ * ```typescript
568
+ * const results = await booking.availability.search({
569
+ * propertyIds: ["prop_abc", "prop_def"],
570
+ * checkIn: "2025-06-01",
571
+ * checkOut: "2025-06-05",
572
+ * guests: 2,
573
+ * priceRange: { min: 5000, max: 20000 },
574
+ * });
575
+ * ```
576
+ */
577
+ search(params) {
578
+ return this._post(this.basePath, params);
579
+ }
580
+ /**
581
+ * Generate a calendar view of daily availability for a property.
582
+ *
583
+ * Client-side helper that calls `check()` internally and transforms the result
584
+ * into a `CalendarDay[]` suitable for calendar UI rendering.
585
+ *
586
+ * @param params - Extends `AvailabilityCheckParams` with optional `months` (default: 1)
587
+ *
588
+ * @example
589
+ * ```typescript
590
+ * const calendar = await booking.availability.getCalendar({
591
+ * propertyId: "prop_abc123",
592
+ * checkIn: "2025-06-01",
593
+ * checkOut: "2025-06-30",
594
+ * });
595
+ * ```
596
+ */
597
+ async getCalendar(params) {
598
+ const { months, ...checkParams } = params;
599
+ let endDate;
600
+ if (checkParams.checkOut !== checkParams.checkIn) {
601
+ endDate = checkParams.checkOut;
602
+ } else if (months != null) {
603
+ endDate = addDays(checkParams.checkIn, months * 30);
604
+ } else {
605
+ return [];
606
+ }
607
+ const dates = generateDateRange(checkParams.checkIn, endDate, 365);
608
+ if (dates.length === 0) return [];
609
+ const result = await this.check({ ...checkParams, checkOut: endDate });
610
+ const spacesAvailable = result.spaces.filter((s) => s.available).length;
611
+ return dates.map((date) => ({
612
+ date,
613
+ available: result.available,
614
+ price: result.available && result.pricing ? result.pricing.total : null,
615
+ minStay: result.restrictions?.minStay ?? null,
616
+ closedToArrival: result.restrictions?.closedToArrival ?? false,
617
+ closedToDeparture: result.restrictions?.closedToDeparture ?? false,
618
+ spacesAvailable: result.available ? spacesAvailable : 0
619
+ }));
620
+ }
621
+ /**
622
+ * Get available table reservation time slots for a specific date.
623
+ *
624
+ * Client-side helper for the Tables vertical. Calls `check()` internally
625
+ * with `type: "table"` and reshapes the response into `TimeSlot[]`.
626
+ *
627
+ * @param params - Must include `propertyId` and `date`
628
+ *
629
+ * @example
630
+ * ```typescript
631
+ * const slots = await booking.availability.getTableSlots({
632
+ * propertyId: "prop_abc123",
633
+ * date: "2025-06-15",
634
+ * guests: 4,
635
+ * });
636
+ * ```
637
+ */
638
+ async getTableSlots(params) {
639
+ const { date, guests, categoryId, duration, ...rest } = params;
640
+ const result = await this.check({
641
+ ...rest,
642
+ checkIn: date,
643
+ checkOut: date,
644
+ type: "table",
645
+ guests,
646
+ categoryId
647
+ });
648
+ if (!result.available || result.spaces.length === 0) {
649
+ return [];
650
+ }
651
+ const slotDuration = duration ?? 90;
652
+ const availableSpaces = result.spaces.filter((s) => s.available);
653
+ return availableSpaces.map((space, index) => ({
654
+ startTime: minutesToTime(11 * 60 + index * slotDuration),
655
+ endTime: minutesToTime(11 * 60 + index * slotDuration + slotDuration),
656
+ available: true,
657
+ tablesAvailable: availableSpaces.length,
658
+ price: space.price
659
+ }));
660
+ }
661
+ /**
662
+ * Get available service appointment slots for a specific date.
663
+ *
664
+ * Client-side helper for the Services vertical. Calls `check()` internally
665
+ * with `type: "service"` and reshapes the response into `ServiceTimeSlot[]`.
666
+ *
667
+ * @param params - Must include `propertyId` and `date`
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * const slots = await booking.availability.getServiceSlots({
672
+ * propertyId: "prop_abc123",
673
+ * date: "2025-06-15",
674
+ * providerId: "staff_001",
675
+ * duration: 60,
676
+ * });
677
+ * ```
678
+ */
679
+ async getServiceSlots(params) {
680
+ const { date, providerId, categoryId, duration, ...rest } = params;
681
+ const result = await this.check({
682
+ ...rest,
683
+ checkIn: date,
684
+ checkOut: date,
685
+ type: "service",
686
+ categoryId
687
+ });
688
+ if (!result.available || result.spaces.length === 0) {
689
+ return [];
690
+ }
691
+ const slotDuration = duration ?? 60;
692
+ const availableSpaces = result.spaces.filter((s) => s.available);
693
+ return availableSpaces.map((space, index) => ({
694
+ startTime: minutesToTime(9 * 60 + index * slotDuration),
695
+ endTime: minutesToTime(9 * 60 + index * slotDuration + slotDuration),
696
+ available: true,
697
+ tablesAvailable: availableSpaces.length,
698
+ price: space.price,
699
+ providerId: providerId ?? space.spaceId,
700
+ providerName: space.name
701
+ }));
702
+ }
703
+ /**
704
+ * Get aggregated pricing statistics for a property and date range.
705
+ *
706
+ * Client-side helper that calls `check()` internally and computes
707
+ * min/max/average/total pricing from available spaces.
708
+ *
709
+ * @param params - Extends `AvailabilityCheckParams` with optional `currency`
710
+ *
711
+ * @example
712
+ * ```typescript
713
+ * const pricing = await booking.availability.getPricing({
714
+ * propertyId: "prop_abc123",
715
+ * checkIn: "2025-06-01",
716
+ * checkOut: "2025-06-05",
717
+ * });
718
+ * console.log(`From €${pricing.minPrice / 100} to €${pricing.maxPrice / 100}`);
719
+ * ```
720
+ */
721
+ async getPricing(params) {
722
+ const { currency: requestedCurrency, ...checkParams } = params;
723
+ const result = await this.check(checkParams);
724
+ const availableSpaces = result.spaces.filter((s) => s.available);
725
+ const nights = dateDiffDays(params.checkIn, params.checkOut);
726
+ const currency = requestedCurrency ?? result.pricing?.currency ?? "EUR";
727
+ if (availableSpaces.length === 0) {
728
+ return {
729
+ minPrice: 0,
730
+ maxPrice: 0,
731
+ averagePrice: 0,
732
+ totalPrice: 0,
733
+ perNight: null,
734
+ nights,
735
+ currency
736
+ };
737
+ }
738
+ const prices = availableSpaces.map((s) => s.price);
739
+ const minPrice = Math.min(...prices);
740
+ const maxPrice = Math.max(...prices);
741
+ const averagePrice = Math.round(prices.reduce((sum, p) => sum + p, 0) / prices.length);
742
+ const totalPrice = result.pricing?.total ?? averagePrice * Math.max(nights, 1);
743
+ const perNight = nights > 0 ? Math.round(totalPrice / nights) : null;
744
+ return { minPrice, maxPrice, averagePrice, totalPrice, perNight, nights, currency };
745
+ }
746
+ };
747
+ function parseDateStr(dateStr) {
748
+ const parts = dateStr.split("-");
749
+ return [Number(parts[0]), Number(parts[1]), Number(parts[2])];
750
+ }
751
+ function addDays(dateStr, days) {
752
+ const [year, month, day] = parseDateStr(dateStr);
753
+ return formatDate(new Date(Date.UTC(year, month - 1, day + days)));
754
+ }
755
+ function generateDateRange(start, end, maxDays) {
756
+ const [sy, sm, sd] = parseDateStr(start);
757
+ const [ey, em, ed] = parseDateStr(end);
758
+ const startMs = Date.UTC(sy, sm - 1, sd);
759
+ const endMs = Date.UTC(ey, em - 1, ed);
760
+ if (endMs <= startMs) return [];
761
+ const msPerDay = 864e5;
762
+ const totalDays = Math.min(Math.floor((endMs - startMs) / msPerDay), maxDays);
763
+ const dates = [];
764
+ for (let i = 0; i < totalDays; i++) {
765
+ dates.push(formatDate(new Date(startMs + i * msPerDay)));
766
+ }
767
+ return dates;
768
+ }
769
+ function dateDiffDays(start, end) {
770
+ const [sy, sm, sd] = parseDateStr(start);
771
+ const [ey, em, ed] = parseDateStr(end);
772
+ const startMs = Date.UTC(sy, sm - 1, sd);
773
+ const endMs = Date.UTC(ey, em - 1, ed);
774
+ return Math.max(0, Math.floor((endMs - startMs) / 864e5));
775
+ }
776
+ function formatDate(d) {
777
+ const y = d.getUTCFullYear();
778
+ const m = String(d.getUTCMonth() + 1).padStart(2, "0");
779
+ const day = String(d.getUTCDate()).padStart(2, "0");
780
+ return `${y}-${m}-${day}`;
781
+ }
782
+ function minutesToTime(totalMinutes) {
783
+ const hours = Math.floor(totalMinutes / 60) % 24;
784
+ const minutes = totalMinutes % 60;
785
+ return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
786
+ }
787
+
523
788
  // src/services/categories.ts
524
789
  var CategoriesService = class extends BaseService {
525
790
  constructor() {
@@ -658,6 +923,135 @@ var PropertiesService = class extends BaseService {
658
923
  }
659
924
  };
660
925
 
926
+ // src/services/spaces.ts
927
+ var SpacesService = class extends BaseService {
928
+ constructor() {
929
+ super(...arguments);
930
+ this.basePath = "/inventory/v1/spaces";
931
+ }
932
+ /**
933
+ * Create a new space.
934
+ *
935
+ * @example
936
+ * ```typescript
937
+ * const space = await booking.spaces.create({
938
+ * propertyId: "prop_abc123",
939
+ * name: "Room 101",
940
+ * type: "room",
941
+ * floor: "1",
942
+ * capacity: 2,
943
+ * });
944
+ * ```
945
+ */
946
+ create(input) {
947
+ return this._post(this.basePath, input);
948
+ }
949
+ /**
950
+ * List spaces for a property with optional filters and cursor-based pagination.
951
+ *
952
+ * @param params - Must include `propertyId`; supports optional `type`, `status`, `categoryId`, `floor` filters
953
+ *
954
+ * @example
955
+ * ```typescript
956
+ * const page = await booking.spaces.list({
957
+ * propertyId: "prop_abc123",
958
+ * type: "room",
959
+ * status: "available",
960
+ * limit: 20,
961
+ * });
962
+ * ```
963
+ */
964
+ list(params) {
965
+ return this._list(params);
966
+ }
967
+ /**
968
+ * Get a single space by ID.
969
+ *
970
+ * @example
971
+ * ```typescript
972
+ * const space = await booking.spaces.get("spc_abc123");
973
+ * ```
974
+ */
975
+ get(spaceId) {
976
+ return this._get(this._buildPath(spaceId));
977
+ }
978
+ /**
979
+ * Update an existing space.
980
+ *
981
+ * @example
982
+ * ```typescript
983
+ * const updated = await booking.spaces.update("spc_abc123", {
984
+ * name: "Room 101 Deluxe",
985
+ * capacity: 3,
986
+ * });
987
+ * ```
988
+ */
989
+ update(spaceId, input) {
990
+ return this._patch(this._buildPath(spaceId), input);
991
+ }
992
+ /**
993
+ * Delete a space.
994
+ *
995
+ * @example
996
+ * ```typescript
997
+ * await booking.spaces.delete("spc_abc123");
998
+ * ```
999
+ */
1000
+ delete(spaceId) {
1001
+ return this._delete(this._buildPath(spaceId));
1002
+ }
1003
+ /**
1004
+ * Bulk create multiple spaces for a property in a single API call.
1005
+ *
1006
+ * @example
1007
+ * ```typescript
1008
+ * const spaces = await booking.spaces.bulkCreate("prop_abc123", [
1009
+ * { propertyId: "prop_abc123", name: "Room 101", type: "room" },
1010
+ * { propertyId: "prop_abc123", name: "Room 102", type: "room" },
1011
+ * ]);
1012
+ * ```
1013
+ */
1014
+ bulkCreate(propertyId, spaces) {
1015
+ return this._post(this._buildPath("bulk"), {
1016
+ propertyId,
1017
+ spaces
1018
+ });
1019
+ }
1020
+ /**
1021
+ * Bulk update multiple spaces for a property in a single API call.
1022
+ *
1023
+ * @example
1024
+ * ```typescript
1025
+ * const updated = await booking.spaces.bulkUpdate("prop_abc123", [
1026
+ * { id: "spc_1", name: "Room 101 Deluxe" },
1027
+ * { id: "spc_2", capacity: 3 },
1028
+ * ]);
1029
+ * ```
1030
+ */
1031
+ bulkUpdate(propertyId, updates) {
1032
+ return this._patch(this._buildPath("bulk"), {
1033
+ propertyId,
1034
+ updates
1035
+ });
1036
+ }
1037
+ /**
1038
+ * Link a space to a POS table. Tables vertical only.
1039
+ *
1040
+ * Creates a cross-domain bridge between the inventory service and the POS system,
1041
+ * enabling a space to reference its physical POS table.
1042
+ *
1043
+ * @example
1044
+ * ```typescript
1045
+ * const linked = await booking.spaces.linkPosTable("spc_abc123", {
1046
+ * posTableId: "pos_table_42",
1047
+ * });
1048
+ * ```
1049
+ */
1050
+ linkPosTable(spaceId, input) {
1051
+ return this._post(this._buildPath(spaceId, "pos-table"), input);
1052
+ }
1053
+ };
1054
+
661
1055
  // src/client.ts
662
1056
  var BookingClient = class {
663
1057
  constructor(config) {
@@ -675,6 +1069,11 @@ var BookingClient = class {
675
1069
  logger: validated.logger
676
1070
  });
677
1071
  }
1072
+ /** Availability service — lazy-initialized on first access */
1073
+ get availability() {
1074
+ this._availability ?? (this._availability = new AvailabilityService(this.httpClient));
1075
+ return this._availability;
1076
+ }
678
1077
  /** Properties service — lazy-initialized on first access */
679
1078
  get properties() {
680
1079
  this._properties ?? (this._properties = new PropertiesService(this.httpClient));
@@ -685,6 +1084,11 @@ var BookingClient = class {
685
1084
  this._categories ?? (this._categories = new CategoriesService(this.httpClient));
686
1085
  return this._categories;
687
1086
  }
1087
+ /** Spaces service — lazy-initialized on first access */
1088
+ get spaces() {
1089
+ this._spaces ?? (this._spaces = new SpacesService(this.httpClient));
1090
+ return this._spaces;
1091
+ }
688
1092
  setApiKey(key) {
689
1093
  if (!key || key.trim().length === 0) {
690
1094
  throw new Error("apiKey must be a non-empty string");
@@ -748,11 +1152,32 @@ var DEFAULT_MODULES = {
748
1152
  pos: false
749
1153
  };
750
1154
 
1155
+ // src/types/spaces.ts
1156
+ var SPACE_TYPES = [
1157
+ "room",
1158
+ "table",
1159
+ "sunbed",
1160
+ "parking",
1161
+ "desk",
1162
+ "meeting_room",
1163
+ "locker",
1164
+ "service",
1165
+ "custom"
1166
+ ];
1167
+ var SPACE_STATUSES = [
1168
+ "available",
1169
+ "occupied",
1170
+ "maintenance",
1171
+ "blocked",
1172
+ "inactive"
1173
+ ];
1174
+
751
1175
  // src/index.ts
752
1176
  var VERSION = "0.1.0";
753
1177
  // Annotate the CommonJS export names for ESM import in node:
754
1178
  0 && (module.exports = {
755
1179
  AuthenticationError,
1180
+ AvailabilityService,
756
1181
  BookingClient,
757
1182
  BookingError,
758
1183
  CategoriesService,
@@ -765,7 +1190,10 @@ var VERSION = "0.1.0";
765
1190
  PaymentError,
766
1191
  PropertiesService,
767
1192
  RateLimitError,
1193
+ SPACE_STATUSES,
1194
+ SPACE_TYPES,
768
1195
  ServerError,
1196
+ SpacesService,
769
1197
  TimeoutError,
770
1198
  VERSION,
771
1199
  ValidationError,