@revolugo/common 6.15.8 → 7.0.0-rc.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revolugo/common",
3
- "version": "6.15.8",
3
+ "version": "7.0.0-rc.0",
4
4
  "private": false,
5
5
  "description": "Revolugo common",
6
6
  "author": "Revolugo",
@@ -16,7 +16,6 @@
16
16
  ],
17
17
  "exports": {
18
18
  "./amenities": "./src/amenities/index.ts",
19
- "./assets": "./src/assets/index.ts",
20
19
  "./cancellation-policies": "./src/cancellation-policies.ts",
21
20
  "./countries": "./src/countries/index.ts",
22
21
  "./constants": "./src/constants/index.ts",
@@ -30,13 +29,14 @@
30
29
  "./utils": "./src/utils/index.ts"
31
30
  },
32
31
  "dependencies": {
32
+ "@asteasolutions/zod-to-openapi": "8.4.0",
33
33
  "change-case": "5.4.4",
34
34
  "dayjs": "1.11.19",
35
- "ky": "1.14.1",
35
+ "ky": "1.14.3",
36
36
  "slugify": "1.6.6",
37
- "type-fest": "5.3.0",
37
+ "type-fest": "5.4.3",
38
38
  "uuid": "13.0.0",
39
- "zod": "3.25.76"
39
+ "zod": "4.3.6"
40
40
  },
41
41
  "scripts": {
42
42
  "test": "vitest"
@@ -1,6 +1,7 @@
1
1
  export const AMENITY_TO_ICONS = Object.freeze({
2
2
  AirConditioning: 'wind',
3
3
  AirportTransportation: 'planeTakeOff',
4
+ Bed: 'bed',
4
5
  BusinessCenter: 'building',
5
6
  CarRentDesk: 'car',
6
7
  ChildrenAllowed: 'baby',
@@ -14,6 +15,7 @@ export const AMENITY_TO_ICONS = Object.freeze({
14
15
  ExteriorRoomEntrance: 'doorOpen',
15
16
  FamilyRooms: 'usersThree',
16
17
  FitnessFacility: 'gym',
18
+ Floor: 'arrowHorizontal',
17
19
  GameRoom: 'gameController',
18
20
  GolfCourse: 'golf',
19
21
  HairDryer: 'hairDryer',
@@ -38,6 +40,7 @@ export const AMENITY_TO_ICONS = Object.freeze({
38
40
  TennisCourt: 'tennisBall',
39
41
  TvInRoom: 'monitor',
40
42
  TwentyFourHourSecurity: 'shield',
43
+ Users: 'users',
41
44
  ValetParking: 'car',
42
45
  VideoCheckOut: 'filmReel',
43
46
  VoiceMail: 'phone',
@@ -454,7 +454,7 @@ export function getSanitizedCancellationPolicies({
454
454
  }: {
455
455
  checkInDate: string
456
456
  cancellationPolicies: ICancellationPolicy[]
457
- timezone: string
457
+ timezone?: string
458
458
  initialDate?: string
459
459
  }): ICancellationPolicy[] {
460
460
  if (!cancellationPolicies.length) {
@@ -19,6 +19,8 @@ export enum Lang {
19
19
  PT = 'pt',
20
20
  }
21
21
 
22
+ export type ExtendedLocale = Locale | Lang
23
+
22
24
  export function langFromString(langStr: string): Lang | undefined {
23
25
  return Object.entries(Lang).find(entry => {
24
26
  if (entry[0].toLocaleLowerCase() === langStr.toLocaleLowerCase()) {
@@ -1,5 +1,6 @@
1
1
  export const ICONS_NAME = Object.freeze({
2
2
  airplane: 'ph:airplane',
3
+ appleBrand: 'logos:apple',
3
4
  archive: 'ph:archive',
4
5
  arrowDown: 'ph:arrow-down',
5
6
  arrowHorizontal: 'ph:arrows-horizontal',
@@ -39,6 +40,7 @@ export const ICONS_NAME = Object.freeze({
39
40
  circle: 'ph:circle',
40
41
  circleNotch: 'ph:circle-notch',
41
42
  clock: 'ph:clock',
43
+ clockClockwise: 'ph:clock-clockwise',
42
44
  close: 'ph:x',
43
45
  closeCircle: 'ph:x-circle',
44
46
  cloud: 'ph:cloud',
@@ -87,6 +89,7 @@ export const ICONS_NAME = Object.freeze({
87
89
  gear: 'ph:gear',
88
90
  globe: 'ph:globe',
89
91
  golf: 'ph:golf',
92
+ googleCalendar: 'logos:google-calendar',
90
93
  graph: 'ph:graph',
91
94
  gym: 'ph:barbell',
92
95
  hairDryer: 'ph:hair-dryer',
@@ -100,16 +103,19 @@ export const ICONS_NAME = Object.freeze({
100
103
  images: 'ph:images',
101
104
  imagesSquare: 'ph:images-square',
102
105
  info: 'ph:info',
106
+ instagram: 'ph:instagram-logo',
103
107
  key: 'ph:key',
104
108
  leaf: 'ph:leaf',
105
109
  lightning: 'ph:lightning',
106
110
  link: 'ph:link',
107
111
  linkBreak: 'ph:link-break',
112
+ linkedin: 'ph:linkedin-logo',
108
113
  lock: 'ph:lock',
109
114
  lockKey: 'ph:lock-key',
110
115
  lockKeyOpen: 'ph:lock-key-open',
111
116
  lockOpen: 'ph:lock-open',
112
117
  magnifyingGlass: 'ph:magnifying-glass',
118
+ magnifyingGlassList: 'ph:list-magnifying-glass',
113
119
  mapPin: 'ph:map-pin',
114
120
  mapPinArea: 'ph:map-pin-area',
115
121
  mapPinSimpleArea: 'ph:map-pin-simple-area',
@@ -119,6 +125,8 @@ export const ICONS_NAME = Object.freeze({
119
125
  money: 'ph:money',
120
126
  monitor: 'ph:monitor',
121
127
  mosque: 'ph:mosque',
128
+ msOffice365: 'custom:ms-office-365',
129
+ msOutlook: 'custom:ms-outlook',
122
130
  musicNotes: 'ph:music-notes',
123
131
  noSmoking: 'ph:cigarette-slash',
124
132
  note: 'ph:note',
@@ -137,11 +145,13 @@ export const ICONS_NAME = Object.freeze({
137
145
  policeCar: 'ph:police-car',
138
146
  praying: 'ph:hands-praying',
139
147
  questionMark: 'ph:question-mark',
148
+ receiptFail: 'ph:receipt-x',
140
149
  refresh: 'ph:arrows-counter-clockwise',
141
150
  running: 'ph:person-simple-run',
142
151
  scissors: 'ph:scissors',
143
152
  shield: 'ph:shield',
144
153
  shirt: 'ph:shirt-folded',
154
+ shoppingBag: 'ph:shopping-bag',
145
155
  shoppingCart: 'ph:shopping-cart',
146
156
  shrink: 'ph:arrows-in-simple',
147
157
  signOut: 'ph:sign-out',
@@ -163,9 +173,10 @@ export const ICONS_NAME = Object.freeze({
163
173
  tent: 'ph:tent',
164
174
  thermometerHot: 'ph:thermometer-hot',
165
175
  thumbsUp: 'ph:thumbs-up',
176
+ timer: 'ph:timer',
166
177
  tooth: 'ph:tooth',
167
178
  train: 'ph:train',
168
- trash: 'ph:trash',
179
+ trash: 'ph:trash-simple',
169
180
  tree: 'ph:tree',
170
181
  trendDown: 'ph:trend-down',
171
182
  trendUp: 'ph:trend-up',
@@ -178,6 +189,7 @@ export const ICONS_NAME = Object.freeze({
178
189
  van: 'ph:van',
179
190
  vault: 'ph:vault',
180
191
  walking: 'ph:person-simple-walk',
192
+ wallet: 'ph:wallet',
181
193
  warning: 'ph:warning',
182
194
  warningCircle: 'ph:warning-circle',
183
195
  wheelchair: 'ph:wheelchair',
@@ -26,7 +26,7 @@ export const CHILDREN_SCHEMA = z
26
26
  })
27
27
 
28
28
  export const COUNTRY_ISO2_CODE_SCHEMA = z
29
- .nativeEnum(CountryIso2Code)
29
+ .enum(CountryIso2Code)
30
30
  .refine(check => Object.values(CountryIso2Code).includes(check), {
31
31
  message: 'Invalid ISO Alpha-2 country code.',
32
32
  })
@@ -23,7 +23,7 @@ List of hotel images in various sizes featuring an indicator for the primary (he
23
23
  hotel_room_offers: z.array(HOTEL_ROOM_OFFER_SCHEMA),
24
24
  tags: TAGS_SCHEMA,
25
25
  venues: VENUES_SCHEMA,
26
- })
26
+ }).openapi('hotelOfferApi')
27
27
 
28
28
  export const HOTEL_OFFERS_SCHEMA = z.array(HOTEL_OFFER_SCHEMA)
29
29
 
@@ -52,7 +52,5 @@ export const HOTEL_OFFERS_RESPONSE_SCHEMA = z.object({
52
52
  }),
53
53
  }),
54
54
  event: z.any().optional(),
55
- meta: LIST_POLLING_META_SCHEMA.extend({
56
- total_count: z.number(),
57
- }),
55
+ meta: LIST_POLLING_META_SCHEMA,
58
56
  })
@@ -31,7 +31,7 @@ export const HOTEL_ROOM_OFFER_SCHEMA = z
31
31
  description:
32
32
  'Quantity of breakfast per night included in the given **Hotel Room Offer**',
33
33
  }),
34
- breakfast_option: z.nativeEnum(BreakfastOption).openapi({
34
+ breakfast_option: z.enum(BreakfastOption).openapi({
35
35
  description: BREAKFAST_OPTION_DESCRIPTION,
36
36
  }),
37
37
  breakfast_price_per_guest_per_night: z
@@ -69,7 +69,7 @@ export const HOTEL_ROOM_OFFER_SCHEMA = z
69
69
  }),
70
70
  id: z.string().openapi({ description: 'Hotel Room Offer id.' }).optional(),
71
71
  package_type: z
72
- .nativeEnum(PackageType)
72
+ .enum(PackageType)
73
73
  .openapi({
74
74
  description: PACKAGE_TYPES_DESCRIPTION,
75
75
  })
@@ -86,7 +86,7 @@ export const HOTEL_ROOM_OFFER_SCHEMA = z
86
86
  }),
87
87
  taxes: TAXES_SCHEMA,
88
88
  type: z
89
- .nativeEnum(HotelRoomOfferType)
89
+ .enum(HotelRoomOfferType)
90
90
  .openapi({
91
91
  description: `Hotel Room Offer type.\n\n **Hotel Room Offers** with **type = "${HotelRoomOfferType.Package}"** are **Hotel Room Offers** that are already bookable and you'll be able to follow the next step of the **Booking Flow** calling **[Create Booking Policies endpoint](/v1/documentation#operation/postV1Booking_policies)**. \n\n Otherwise, you'll be able to create a new **Hotel Room Offer** with **type = "${HotelRoomOfferType.Package}"** from multiple **Hotel Room Offers** with **type = "${HotelRoomOfferType.HotelRoom}"**. See **[Create Hotel Room Offer endpoint](/v1/documentation#operation/postV1Hotel_room_offers)** for details.`,
92
92
  })
@@ -14,7 +14,7 @@ export const STARTING_AFTER_SCHEMA = z.string().optional().nullable().openapi({
14
14
  })
15
15
 
16
16
  export const STATUS_SCHEMA = z
17
- .nativeEnum(PollerStatus)
17
+ .enum(PollerStatus)
18
18
  .openapi({ description: 'Status of the response data.' })
19
19
  .openapi('pollerStatus')
20
20
 
@@ -39,5 +39,9 @@ export const LIST_META_SCHEMA = z
39
39
 
40
40
  export const LIST_POLLING_META_SCHEMA = LIST_META_SCHEMA.extend({
41
41
  status: STATUS_SCHEMA,
42
+ total_count: z
43
+ .number()
44
+ .optional()
45
+ .openapi({ description: 'Total count of the response list.' }),
42
46
  }).openapi('metaApiPollingResponse')
43
47
  /* eslint-enable camelcase */
@@ -19,11 +19,11 @@ export const TAX_SCHEMA = z
19
19
  .optional()
20
20
  .nullish()
21
21
  .openapi({ description: 'Tax percentage on the total amount.' }),
22
- tax_frequency: z.nativeEnum(TaxFrequency).openapi({
22
+ tax_frequency: z.enum(TaxFrequency).openapi({
23
23
  description:
24
24
  'Tax frequency. Specifies if the tax applies per stay or per night',
25
25
  }),
26
- tax_mode: z.nativeEnum(TaxMode).openapi({
26
+ tax_mode: z.enum(TaxMode).openapi({
27
27
  description:
28
28
  'Tax mode. Specifies if the tax applies per occupant, per booking or per room',
29
29
  }),
@@ -1,5 +1,7 @@
1
- export enum PayLaterStatus {
1
+ export enum PayLaterStatusEnum {
2
2
  Disabled = 'DISABLED',
3
3
  Enabled = 'ENABLED',
4
4
  Forced = 'FORCED',
5
5
  }
6
+
7
+ export type PayLaterStatus = `${PayLaterStatusEnum}`
@@ -0,0 +1,17 @@
1
+ import type {
2
+ BasePaymentMethodCoupon,
3
+ BasePaymentMethodCreditCard,
4
+ BasePaymentMethodDepositAccount,
5
+ BasePaymentMethodPayLater,
6
+ PayloadPayLater,
7
+ } from './payment-method.ts'
8
+
9
+ export type AllowedPaymentMethod =
10
+ | BasePaymentMethodCoupon
11
+ | BasePaymentMethodCreditCard
12
+ | BasePaymentMethodDepositAccount
13
+ | AllowedPaymentMethodPayLater
14
+
15
+ export interface AllowedPaymentMethodPayLater extends BasePaymentMethodPayLater {
16
+ payload: PayloadPayLater
17
+ }
@@ -47,6 +47,8 @@ export interface BookingPolicies {
47
47
  * @memberof BookingPolicies
48
48
  */
49
49
  expiresAt: string | null
50
+
51
+ hasRoomingLists: boolean
50
52
  /**
51
53
  * Hotel id
52
54
  * @type {string}
@@ -78,3 +80,36 @@ export interface BookingPolicies {
78
80
  */
79
81
  isPriceIncreased: boolean
80
82
  }
83
+
84
+ /**
85
+ *
86
+ * @export
87
+ * @interface BookingCreateApiGuestsListInner
88
+ */
89
+ export interface BookingCreateApiGuestsListInner {
90
+ /**
91
+ *
92
+ * @type {Array<BookingCreateApiGuestsListInnerGuestsInner>}
93
+ * @memberof BookingCreateApiGuestsListInner
94
+ */
95
+ guests: BookingCreateApiGuestsListInnerGuestsInner[]
96
+ /**
97
+ *
98
+ * @type {string}
99
+ * @memberof BookingCreateApiGuestsListInner
100
+ */
101
+ hotelRoomId: string
102
+ }
103
+ /**
104
+ *
105
+ * @export
106
+ * @interface BookingCreateApiGuestsListInnerGuestsInner
107
+ */
108
+ export interface BookingCreateApiGuestsListInnerGuestsInner {
109
+ /**
110
+ *
111
+ * @type {string}
112
+ * @memberof BookingCreateApiGuestsListInnerGuestsInner
113
+ */
114
+ fullname: string
115
+ }
@@ -5,7 +5,7 @@ import type { Event } from './event.ts'
5
5
  import type { HotelRoomOffer } from './hotel-room-offer.ts'
6
6
  import type { HotelRoomingList } from './hotel-rooming-list.ts'
7
7
  import type { InvoiceApi } from './invoice.ts'
8
- import type { PaymentMethodApi } from './payment-method.ts'
8
+ import type { PaymentMethod } from './payment-method.ts'
9
9
  import type { SourceMarket } from './source-market.ts'
10
10
  import type { Tax } from './tax.ts'
11
11
 
@@ -148,10 +148,10 @@ export interface Booking {
148
148
  * List of preferred payment methods to be used along with their respective payload (when applicable) in order to fulfill the booking.
149
149
  *
150
150
  * ⚠️ This field is only returned when **booking.status = bkg-created**
151
- * @type {Array<PaymentMethodApi>}
151
+ * @type {Array<PaymentMethod>}
152
152
  * @memberof Booking
153
153
  */
154
- paymentMethods?: PaymentMethodApi[]
154
+ paymentMethods?: PaymentMethod[]
155
155
  /**
156
156
  * Penalty percentage of the requested Booking.
157
157
  *
@@ -13,7 +13,7 @@ import type {
13
13
  HotelRoomOffersResponse,
14
14
  } from './hotel-room-offer.ts'
15
15
  import type { Hotel } from './hotel.ts'
16
- import type { Locale } from 'change-case'
16
+ import type { Locale } from '@revolugo/common/constants'
17
17
 
18
18
  export enum ElementsEvent {
19
19
  BookingCreated = 'booking:created',
@@ -34,7 +34,6 @@ export enum ElementsEvent {
34
34
  HotelOffersMarkerClick = 'hotel-offers:marker:click',
35
35
  HotelOffersPollingStarted = 'hotel-offers:polling:started',
36
36
  HotelOffersRetrieved = 'hotel-offers:retrieved',
37
- HotelOffersViewShowMap = 'hotel-offers-view:show-map',
38
37
  HotelRetrieved = 'hotel:retrieved',
39
38
  HotelRoomOfferRequestCreated = 'hotel-room-offer-request:created',
40
39
  HotelRoomOfferRequestRetrieved = 'hotel-room-offer-request:retrieved',
@@ -57,18 +56,17 @@ export interface ElementsEventCallbacks {
57
56
  [ElementsEvent.BookingPolicyCreated]: BookingPolicies
58
57
  [ElementsEvent.CancellationPoliciesUpdated]: CancellationPolicy[]
59
58
  [ElementsEvent.CurrencyUpdated]: CurrencyType
60
- [ElementsEvent.HotelOfferItemMouseleave]: [HotelOffer, number]
61
- [ElementsEvent.HotelOfferItemMouseover]: [HotelOffer, number]
62
- [ElementsEvent.HotelOfferItemVisible]: [HotelOffer, number]
59
+ [ElementsEvent.HotelOfferItemMouseleave]: HotelOffer | [HotelOffer, number]
60
+ [ElementsEvent.HotelOfferItemMouseover]: HotelOffer | [HotelOffer, number]
61
+ [ElementsEvent.HotelOfferItemVisible]: HotelOffer | [HotelOffer, number]
63
62
  [ElementsEvent.HotelOfferRequestCreated]: HotelOfferRequestResponse
64
63
  [ElementsEvent.HotelOfferRequestRetrieved]: HotelOfferRequestResponse
65
64
  [ElementsEvent.HotelOffersFiltersUpdated]: Partial<HotelOffersFilters>
66
- [ElementsEvent.HotelOffersItemClick]: [HotelOffer, number]
67
- [ElementsEvent.HotelOffersMarkerClick]: HotelOffer
65
+ [ElementsEvent.HotelOffersItemClick]: HotelOffer | [HotelOffer, number]
66
+ [ElementsEvent.HotelOffersMarkerClick]: HotelOffer | [HotelOffer, number]
68
67
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
68
  [ElementsEvent.HotelOffersPollingStarted]: any
70
69
  [ElementsEvent.HotelOffersRetrieved]: HotelOffer[]
71
- [ElementsEvent.HotelOffersViewShowMap]: boolean
72
70
  [ElementsEvent.HotelRetrieved]: Hotel
73
71
  [ElementsEvent.HotelRoomOfferRequestCreated]: HotelRoomOfferRequestResponse
74
72
  [ElementsEvent.HotelRoomOfferRequestRetrieved]: HotelRoomOfferRequestResponse
@@ -40,14 +40,14 @@ export interface HotelOfferRequest {
40
40
  * <b style="color: red;"> when no address parameter passed.</b>
41
41
  * @type {number}
42
42
  */
43
- latitude?: number | null
43
+ latitude: number
44
44
  /**
45
45
  * Search location longitude.
46
46
  *
47
47
  * <b style="color: red;"> when no address parameter passed.</b>
48
48
  * @type {number}
49
49
  */
50
- longitude?: number | null
50
+ longitude: number
51
51
  /**
52
52
  * The total number of rooms requested for the stay. Results may display offers matching a different room count than the requested one, however those results will always provide enough occupancy for the total guest count needed.
53
53
  *
@@ -156,16 +156,15 @@ export interface HotelOfferRequestResponse {
156
156
  id: string
157
157
  }
158
158
 
159
- export type HotelOfferRequestCreate = Pick<
160
- HotelOfferRequest,
161
- | 'address'
162
- | 'adultCount'
163
- | 'checkInDate'
164
- | 'checkOutDate'
165
- | 'children'
166
- | 'eventMetadata'
167
- | 'latitude'
168
- | 'longitude'
169
- | 'roomCount'
170
- | 'sourceMarket'
171
- >
159
+ export interface HotelOfferRequestCreate {
160
+ address?: HotelOfferRequest['address']
161
+ adultCount: HotelOfferRequest['adultCount']
162
+ checkInDate: HotelOfferRequest['checkInDate']
163
+ checkOutDate: HotelOfferRequest['checkOutDate']
164
+ children?: HotelOfferRequest['children']
165
+ eventMetadata?: HotelOfferRequest['eventMetadata']
166
+ latitude?: HotelOfferRequest['latitude']
167
+ longitude?: HotelOfferRequest['longitude']
168
+ roomCount: HotelOfferRequest['roomCount']
169
+ sourceMarket: HotelOfferRequest['sourceMarket']
170
+ }
@@ -57,7 +57,7 @@ export interface HotelRoom {
57
57
  * @type {string}
58
58
  * @memberof HotelRoom
59
59
  */
60
- id?: string
60
+ id: string
61
61
  /**
62
62
  * List of indexes corresponding to image names for the given Hotel Room among the related hotel images.
63
63
  * @type {Array<number>}
@@ -2,6 +2,7 @@ export type * from './bed.ts'
2
2
  export type * from './booking-flow.ts'
3
3
  export type * from './booking-policy.ts'
4
4
  export type * from './cancellation-policy.ts'
5
+ export type * from './currency.ts'
5
6
  export * from './elements-events.ts'
6
7
  export type * from './event-metadata.ts'
7
8
  export type * from './hotel-image.ts'
@@ -26,3 +27,5 @@ export type * from './hotel-review-rating.ts'
26
27
  export type * from './travel-times.ts'
27
28
  export * from './hotel-offer-list.ts'
28
29
  export type * from './hotel-room-offer-list.ts'
30
+ export type * from './hotel-rooming-list.ts'
31
+ export type * from './allowed-payment-method.ts'
@@ -1,159 +1,72 @@
1
- export interface PaymentMethodRequestPayloadApi {
2
- /**
3
- *
4
- * @type {string}
5
- * @memberof PaymentMethodRequestPayloadApi
6
- */
7
- couponId?: string | null
1
+ import type { PayLaterStatus } from '../booking.ts'
2
+
3
+ export enum PaymentMethodNameEnum {
4
+ CreditCard = 'CREDIT_CARD',
5
+ Coupon = 'COUPON',
6
+ DepositAccount = 'DEPOSIT_ACCOUNT',
7
+ PayLater = 'PAY_LATER',
8
8
  }
9
9
 
10
- export interface PaymentMethodRequestApi {
11
- /**
12
- *
13
- * @type {string}
14
- * @memberof PaymentMethodRequestApi
15
- */
16
- name: PaymentMethodApiName
17
- /**
18
- *
19
- * @type {PaymentMethodRequestPayloadApi}
20
- * @memberof PaymentMethodRequestApi
21
- */
22
- payload?: PaymentMethodRequestPayloadApi
10
+ export type PaymentMethodName = `${PaymentMethodNameEnum}`
11
+
12
+ export interface BasePaymentMethod {
13
+ name: PaymentMethodName
23
14
  }
24
15
 
25
- export interface PaymentMethodApi {
26
- /**
27
- *
28
- * @type {string}
29
- * @memberof PaymentMethodApiOneOf
30
- */
31
- name: PaymentMethodApiName
32
- /**
33
- *
34
- * @type {PaymentMethodApiOneOfPayload}
35
- * @memberof PaymentMethodApiOneOf
36
- */
37
- payload:
38
- | PaymentMethodApiOneOfPayload
39
- | PaymentMethodApiOneOf1Payload
40
- | PaymentMethodApiOneOf2Payload
16
+ export type PaymentMethod =
17
+ | PaymentMethodCoupon
18
+ | PaymentMethodCreditCard
19
+ | PaymentMethodDepositAccount
20
+ | PaymentMethodPayLater
21
+
22
+ export interface BasePaymentMethodCreditCard extends BasePaymentMethod {
23
+ name: 'CREDIT_CARD'
41
24
  }
42
25
 
43
- export enum PaymentMethodApiNameEnum {
44
- CreditCard = 'CREDIT_CARD',
45
- Coupon = 'COUPON',
46
- DepositAccount = 'DEPOSIT_ACCOUNT',
26
+ export interface PaymentMethodCreditCard extends BasePaymentMethodCreditCard {
27
+ payload: {
28
+ amount: number
29
+ couponId?: string | null
30
+ token: string
31
+ }
47
32
  }
48
33
 
49
- type PaymentMethodApiName = `${PaymentMethodApiNameEnum}`
34
+ export interface BasePaymentMethodCoupon extends BasePaymentMethod {
35
+ name: 'COUPON'
36
+ }
50
37
 
51
- /**
52
- *
53
- * @export
54
- * @interface PaymentMethodApiOneOf1
55
- */
56
- export interface PaymentMethodApiOneOf1 {
57
- /**
58
- *
59
- * @type {string}
60
- * @memberof PaymentMethodApiOneOf1
61
- */
62
- name: PaymentMethodApiName
63
- /**
64
- *
65
- * @type {PaymentMethodApiOneOf1Payload}
66
- * @memberof PaymentMethodApiOneOf1
67
- */
68
- payload: PaymentMethodApiOneOf1Payload
38
+ export interface PaymentMethodCoupon extends BasePaymentMethodCoupon {
39
+ payload: {
40
+ amount: number
41
+ couponId: string
42
+ }
69
43
  }
70
44
 
71
- /**
72
- *
73
- * @export
74
- * @interface PaymentMethodApiOneOf1Payload
75
- */
76
- export interface PaymentMethodApiOneOf1Payload {
77
- /**
78
- *
79
- * @type {number}
80
- * @memberof PaymentMethodApiOneOf1Payload
81
- */
82
- amount: number
83
- /**
84
- *
85
- * @type {string}
86
- * @memberof PaymentMethodApiOneOf1Payload
87
- */
88
- couponId?: string | null
89
- /**
90
- *
91
- * @type {string}
92
- * @memberof PaymentMethodApiOneOf1Payload
93
- */
94
- token: string
45
+ export interface BasePaymentMethodDepositAccount extends BasePaymentMethod {
46
+ name: 'DEPOSIT_ACCOUNT'
95
47
  }
96
- /**
97
- *
98
- * @export
99
- * @interface PaymentMethodApiOneOf2
100
- */
101
- export interface PaymentMethodApiOneOf2 {
102
- /**
103
- *
104
- * @type {string}
105
- * @memberof PaymentMethodApiOneOf2
106
- */
107
- name: PaymentMethodApiName
108
- /**
109
- *
110
- * @type {PaymentMethodApiOneOf2Payload}
111
- * @memberof PaymentMethodApiOneOf2
112
- */
113
- payload: PaymentMethodApiOneOf2Payload
48
+
49
+ export interface PaymentMethodDepositAccount extends BasePaymentMethodDepositAccount {
50
+ payload: {
51
+ amount: number
52
+ couponId?: string | null
53
+ }
114
54
  }
115
55
 
116
- /**
117
- *
118
- * @export
119
- * @interface PaymentMethodApiOneOf2Payload
120
- */
121
- export interface PaymentMethodApiOneOf2Payload {
122
- /**
123
- *
124
- * @type {number}
125
- * @memberof PaymentMethodApiOneOf2Payload
126
- */
127
- amount: number
128
- /**
129
- *
130
- * @type {string}
131
- * @memberof PaymentMethodApiOneOf2Payload
132
- */
133
- couponId?: string | null
134
- /**
135
- *
136
- * @type {string}
137
- * @memberof PaymentMethodApiOneOf2Payload
138
- */
139
- token?: string | null
56
+ export interface BasePaymentMethodPayLater extends BasePaymentMethod {
57
+ name: 'PAY_LATER'
140
58
  }
141
- /**
142
- *
143
- * @export
144
- * @interface PaymentMethodApiOneOfPayload
145
- */
146
- export interface PaymentMethodApiOneOfPayload {
147
- /**
148
- *
149
- * @type {number}
150
- * @memberof PaymentMethodApiOneOfPayload
151
- */
152
- amount: number
153
- /**
154
- *
155
- * @type {string}
156
- * @memberof PaymentMethodApiOneOfPayload
157
- */
158
- couponId: string
59
+
60
+ export interface PayloadPayLater {
61
+ status: PayLaterStatus
62
+ }
63
+ export interface PaymentMethodPayLater extends BasePaymentMethodPayLater {
64
+ payload: { amount: number; couponId?: string | null } & PayloadPayLater
65
+ }
66
+
67
+ export interface PaymentMethodRequest {
68
+ name: PaymentMethodName
69
+ payload?: {
70
+ couponId?: string | null
71
+ }
159
72
  }
@@ -1,3 +1,3 @@
1
1
  export class HttpException extends Error {
2
- declare status: number
2
+ status!: number
3
3
  }
@@ -0,0 +1,15 @@
1
+ import { getRandomHexColor } from './get-random-hex-color.ts'
2
+ import { getRandomInt } from './get-random-int.ts'
3
+
4
+ import type { HotelImage } from '../types/index.ts'
5
+
6
+ export function createDummyHotelImage(count: number): HotelImage[] {
7
+ return Array.from({ length: count }, () => ({
8
+ isHeroImage: false,
9
+ l: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
10
+ m: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
11
+ s: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
12
+ xl: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
13
+ xs: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
14
+ }))
15
+ }
@@ -0,0 +1,15 @@
1
+ import { getRandomHexColor } from './get-random-hex-color.ts'
2
+ import { getRandomInt } from './get-random-int.ts'
3
+
4
+ import type { HotelImage } from '../types/index.ts'
5
+
6
+ export function generateDummyHotelImages(): HotelImage {
7
+ return {
8
+ isHeroImage: false,
9
+ l: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
10
+ m: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
11
+ s: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
12
+ xl: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
13
+ xs: `https://dummyimage.com/${getRandomInt(300, 900)}x${getRandomInt(300, 900)}/${getRandomHexColor()}/${getRandomHexColor()}`,
14
+ }
15
+ }
@@ -0,0 +1,31 @@
1
+ import type { GeoCoordinates } from '../types/geo-coordinates.ts'
2
+
3
+ /**
4
+ * Generate random coordinates near a given latitude and longitude.
5
+ *
6
+ * @param lat - Base latitude
7
+ * @param lon - Base longitude
8
+ * @param radiusInMeters - Max distance from base point, in meters
9
+ * @returns { lat: number, lon: number }
10
+ */
11
+ export function generateRandomNearbyGeolocation(
12
+ { latitude: lat, longitude: lon }: GeoCoordinates,
13
+ radiusInMeters: number,
14
+ ): GeoCoordinates {
15
+ // Convert radius from meters to degrees
16
+ const radiusInDegrees = radiusInMeters / 111_320
17
+
18
+ // Random distance and angle
19
+ const u = Math.random()
20
+ const v = Math.random()
21
+ const w = radiusInDegrees * Math.sqrt(u)
22
+ const t = 2 * Math.PI * v
23
+
24
+ const deltaLat = w * Math.cos(t)
25
+ const deltaLon = (w * Math.sin(t)) / Math.cos((lat * Math.PI) / 180)
26
+
27
+ const newLat = lat + deltaLat
28
+ const newLon = lon + deltaLon
29
+
30
+ return { latitude: newLat, longitude: newLon }
31
+ }
@@ -0,0 +1,7 @@
1
+ import type { HotelRoomOffer } from '../types/elements/index.ts'
2
+
3
+ export function getHotelRoomOfferRoomCount(
4
+ hotelRoomOffer: HotelRoomOffer,
5
+ ): number {
6
+ return hotelRoomOffer.hotelRooms.reduce((acc, room) => acc + room.count, 0)
7
+ }
@@ -0,0 +1,11 @@
1
+ import { dayjs } from './dayjs.ts'
2
+
3
+ /**
4
+ * Get the number of nights between two dates.
5
+ * @param startDate - The start date
6
+ * @param endDate - The end date
7
+ * @returns The number of nights
8
+ */
9
+ export function getNightCount(startDate: string, endDate: string): number {
10
+ return dayjs(endDate).diff(dayjs(startDate), 'day')
11
+ }
@@ -15,9 +15,13 @@ export * from './debounce.ts'
15
15
  export * from './defaults-deep.ts'
16
16
  export * from './delay.ts'
17
17
  export * from './find-unique-keys.ts'
18
+ export * from './generate-dummy-hotel-images.ts'
18
19
  export * from './generate-numbers-from-str.ts'
19
20
  export * from './generate-pseudo-random-string.ts'
21
+ export * from './generate-random-nearby-geolocation.ts'
20
22
  export * from './get-guest-count.ts'
23
+ export * from './get-night-count.ts'
24
+ export * from './get-hotel-room-offer-room-count.ts'
21
25
  export * from './get-random-element-from-array.ts'
22
26
  export * from './get-random-hex-color.ts'
23
27
  export * from './get-random-int.ts'
@@ -48,9 +52,12 @@ export * from './sort-by.ts'
48
52
  export * from './sum-by.ts'
49
53
  export * from './sum.ts'
50
54
  export * from './to-boolean.ts'
55
+ export * from './to-lang.ts'
56
+ export * from './to-locale.ts'
51
57
  export * from './transform-schema-keys.ts'
52
58
  export * from './uniq.ts'
53
59
  export * from './uniq-by.ts'
54
60
  export * from './uniq-with.ts'
55
61
  export * from './validators.ts'
56
62
  export * from './weighted-mean.ts'
63
+ export * from './create-dummy-hotel-images.ts'
@@ -0,0 +1,39 @@
1
+ import { Lang, Locale } from '../constants/locales.ts'
2
+
3
+ import type { ExtendedLocale } from '../constants/locales.ts'
4
+
5
+ export function toLang(localeOrLang: ExtendedLocale): Lang {
6
+ switch (localeOrLang) {
7
+ case Lang.EN:
8
+ case Locale.en_US: {
9
+ return Lang.EN
10
+ }
11
+ case Lang.FR:
12
+ case Locale.fr_FR: {
13
+ return Lang.FR
14
+ }
15
+ case Lang.DE:
16
+ case Locale.de_DE: {
17
+ return Lang.DE
18
+ }
19
+ case Lang.ES:
20
+ case Locale.es_ES: {
21
+ return Lang.ES
22
+ }
23
+ case Lang.IT:
24
+ case Locale.it_IT: {
25
+ return Lang.IT
26
+ }
27
+ case Lang.NL:
28
+ case Locale.nl_NL: {
29
+ return Lang.NL
30
+ }
31
+ case Lang.PT:
32
+ case Locale.pt_PT: {
33
+ return Lang.PT
34
+ }
35
+ default: {
36
+ return Lang.EN
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,39 @@
1
+ import { Lang, Locale } from '../constants/locales.ts'
2
+
3
+ import type { ExtendedLocale } from '../constants/locales.ts'
4
+
5
+ export function toLocale(localeOrLang: ExtendedLocale): Locale {
6
+ switch (localeOrLang) {
7
+ case Lang.EN:
8
+ case Locale.en_US: {
9
+ return Locale.en_US
10
+ }
11
+ case Lang.FR:
12
+ case Locale.fr_FR: {
13
+ return Locale.fr_FR
14
+ }
15
+ case Lang.DE:
16
+ case Locale.de_DE: {
17
+ return Locale.de_DE
18
+ }
19
+ case Lang.ES:
20
+ case Locale.es_ES: {
21
+ return Locale.es_ES
22
+ }
23
+ case Lang.IT:
24
+ case Locale.it_IT: {
25
+ return Locale.it_IT
26
+ }
27
+ case Lang.NL:
28
+ case Locale.nl_NL: {
29
+ return Locale.nl_NL
30
+ }
31
+ case Lang.PT:
32
+ case Locale.pt_PT: {
33
+ return Locale.pt_PT
34
+ }
35
+ default: {
36
+ return Locale.en_US
37
+ }
38
+ }
39
+ }
@@ -1,22 +1,25 @@
1
- import { type ZodTypeAny, z } from 'zod'
1
+ import { getOpenApiMetadata, getRefId } from '@asteasolutions/zod-to-openapi'
2
+ import { z } from 'zod'
2
3
 
3
4
  import {
4
5
  CASE_TRANSFORMERS_MAPPING,
5
6
  type CaseTransformer,
6
7
  } from './case-transformers.ts'
7
8
 
9
+ import type { $ZodType } from 'zod/v4/core'
10
+
8
11
  /* eslint-disable no-underscore-dangle, max-statements */
9
12
 
10
13
  function transformSchemaKeysWithTransformer(
11
- schema: ZodTypeAny,
14
+ schema: z.ZodType,
12
15
  transformer: (str: string) => string,
13
- ): ZodTypeAny {
14
- let result: ZodTypeAny = schema
16
+ ): z.ZodType {
17
+ let result: z.ZodType = schema
15
18
 
16
19
  // Handle ZodObject
17
20
  if (schema instanceof z.ZodObject) {
18
- const shape = schema._def.shape()
19
- const transformedShape: Record<string, ZodTypeAny> = {}
21
+ const { shape } = schema.def
22
+ const transformedShape: Record<string, $ZodType> = {}
20
23
 
21
24
  for (const key in shape) {
22
25
  if (Object.hasOwn(shape, key)) {
@@ -28,86 +31,76 @@ function transformSchemaKeysWithTransformer(
28
31
  }
29
32
  }
30
33
 
31
- result = z.object(transformedShape) as ZodTypeAny
34
+ result = z.object(transformedShape) as z.ZodType
32
35
  }
33
36
 
34
37
  // Handle ZodArray
35
38
  else if (schema instanceof z.ZodArray) {
36
- const { type: elementSchema } = schema._def
39
+ const { element } = schema.def
37
40
  result = z.array(
38
- transformSchemaKeysWithTransformer(elementSchema, transformer),
41
+ transformSchemaKeysWithTransformer(element as z.ZodType, transformer),
39
42
  )
40
43
  }
41
44
 
42
45
  // Handle ZodOptional
43
46
  else if (schema instanceof z.ZodOptional) {
44
- const { innerType: innerSchema } = schema._def
47
+ const { innerType: innerSchema } = schema.def
45
48
  result = transformSchemaKeysWithTransformer(
46
- innerSchema,
49
+ innerSchema as z.ZodType,
47
50
  transformer,
48
51
  ).optional()
49
52
  }
50
53
 
51
54
  // Handle ZodNullable
52
55
  else if (schema instanceof z.ZodNullable) {
53
- const { innerType: innerSchema } = schema._def
56
+ const { innerType: innerSchema } = schema.def
54
57
  result = transformSchemaKeysWithTransformer(
55
- innerSchema,
58
+ innerSchema as z.ZodType,
56
59
  transformer,
57
60
  ).nullable()
58
61
  }
59
62
 
60
63
  // Handle ZodDefault
61
64
  else if (schema instanceof z.ZodDefault) {
62
- const { defaultValue, innerType: innerSchema } = schema._def
65
+ const { defaultValue, innerType: innerSchema } = schema.def
66
+ const defaultValueValue =
67
+ typeof defaultValue === 'function' ? defaultValue() : defaultValue
63
68
  result = transformSchemaKeysWithTransformer(
64
- innerSchema,
65
- transformer,
66
- ).default(defaultValue())
67
- }
68
-
69
- // Handle ZodEffects (includes .refine(), .transform(), etc.)
70
- else if (schema instanceof z.ZodEffects) {
71
- const { schema: innerSchema } = schema._def
72
- const transformedInner = transformSchemaKeysWithTransformer(
73
- innerSchema,
69
+ innerSchema as z.ZodType,
74
70
  transformer,
75
- )
76
-
77
- // We need to reconstruct the effects
78
- // This is a simplified version - effects are not transformed, just passed through
79
- result = transformedInner
71
+ ).default(defaultValueValue)
80
72
  }
81
73
 
82
74
  // Handle ZodUnion
83
75
  else if (schema instanceof z.ZodUnion) {
84
- const { options } = schema._def
85
- const transformedOptions = options.map((option: ZodTypeAny) =>
86
- transformSchemaKeysWithTransformer(option, transformer),
76
+ const { options } = schema.def
77
+ const transformedOptions = options.map((option: $ZodType) =>
78
+ transformSchemaKeysWithTransformer(option as z.ZodType, transformer),
87
79
  )
88
80
  result = z.union(
89
- transformedOptions as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]],
81
+ transformedOptions as [z.ZodType, z.ZodType, ...z.ZodType[]],
90
82
  )
91
83
  }
92
84
 
93
85
  // Handle ZodIntersection
94
86
  else if (schema instanceof z.ZodIntersection) {
95
- const { left, right } = schema._def
87
+ const { left, right } = schema.def
96
88
  result = z.intersection(
97
- transformSchemaKeysWithTransformer(left, transformer),
98
- transformSchemaKeysWithTransformer(right, transformer),
89
+ transformSchemaKeysWithTransformer(left as z.ZodType, transformer),
90
+ transformSchemaKeysWithTransformer(right as z.ZodType, transformer),
99
91
  )
100
92
  }
101
93
 
102
94
  // Propagate openapi metadata
103
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
- const { openapi } = schema._def as any
105
- if (openapi && result !== schema) {
106
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
107
- ;(result._def as any).openapi = openapi
95
+ const openapiRefId = getRefId(schema)
96
+
97
+ const openapiMetadata = getOpenApiMetadata(schema)
98
+
99
+ if (openapiRefId) {
100
+ result = result.openapi(openapiRefId)
108
101
  }
109
102
 
110
- return result
103
+ return result.openapi(openapiMetadata)
111
104
  }
112
105
 
113
106
  /**
@@ -129,7 +122,7 @@ function transformSchemaKeysWithTransformer(
129
122
  * // Results in: { firstName: z.string(), lastName: z.string() }
130
123
  * ```
131
124
  */
132
- export function transformSchemaKeys<T extends ZodTypeAny>(
125
+ export function transformSchemaKeys<T extends z.ZodType>(
133
126
  schema: T,
134
127
  toCase: CaseTransformer,
135
128
  ): T {
@@ -1,3 +0,0 @@
1
- export { default as hotelImagePlaceholder } from './placeholder-hotel.png'
2
-
3
- export { default as roomImagePlaceholder } from './placeholder-room.png'
Binary file
Binary file