@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 +5 -5
- package/src/amenities/index.ts +3 -0
- package/src/cancellation-policies.ts +1 -1
- package/src/constants/locales.ts +2 -0
- package/src/icons/index.ts +13 -1
- package/src/schemas/hotel-offer-request.ts +1 -1
- package/src/schemas/hotel-offer.ts +2 -4
- package/src/schemas/hotel-room-offer.ts +3 -3
- package/src/schemas/list-polling-meta.ts +5 -1
- package/src/schemas/taxes.ts +2 -2
- package/src/types/booking.ts +3 -1
- package/src/types/elements/allowed-payment-method.ts +17 -0
- package/src/types/elements/booking-policy.ts +35 -0
- package/src/types/elements/booking.ts +3 -3
- package/src/types/elements/elements-events.ts +6 -8
- package/src/types/elements/hotel-offer-request.ts +14 -15
- package/src/types/elements/hotel-room.ts +1 -1
- package/src/types/elements/index.ts +3 -0
- package/src/types/elements/payment-method.ts +56 -143
- package/src/types/http-exception/base.exception.ts +1 -1
- package/src/utils/create-dummy-hotel-images.ts +15 -0
- package/src/utils/generate-dummy-hotel-images.ts +15 -0
- package/src/utils/generate-random-nearby-geolocation.ts +31 -0
- package/src/utils/get-hotel-room-offer-room-count.ts +7 -0
- package/src/utils/get-night-count.ts +11 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/to-lang.ts +39 -0
- package/src/utils/to-locale.ts +39 -0
- package/src/utils/transform-schema-keys.ts +36 -43
- package/src/assets/index.ts +0 -3
- package/src/assets/placeholder-hotel.png +0 -0
- package/src/assets/placeholder-room.png +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revolugo/common",
|
|
3
|
-
"version": "
|
|
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.
|
|
35
|
+
"ky": "1.14.3",
|
|
36
36
|
"slugify": "1.6.6",
|
|
37
|
-
"type-fest": "5.3
|
|
37
|
+
"type-fest": "5.4.3",
|
|
38
38
|
"uuid": "13.0.0",
|
|
39
|
-
"zod": "3.
|
|
39
|
+
"zod": "4.3.6"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"test": "vitest"
|
package/src/amenities/index.ts
CHANGED
|
@@ -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
|
|
457
|
+
timezone?: string
|
|
458
458
|
initialDate?: string
|
|
459
459
|
}): ICancellationPolicy[] {
|
|
460
460
|
if (!cancellationPolicies.length) {
|
package/src/constants/locales.ts
CHANGED
|
@@ -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()) {
|
package/src/icons/index.ts
CHANGED
|
@@ -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
|
-
.
|
|
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
|
|
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.
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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 */
|
package/src/schemas/taxes.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
}),
|
package/src/types/booking.ts
CHANGED
|
@@ -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 {
|
|
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<
|
|
151
|
+
* @type {Array<PaymentMethod>}
|
|
152
152
|
* @memberof Booking
|
|
153
153
|
*/
|
|
154
|
-
paymentMethods?:
|
|
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 '
|
|
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
|
|
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
|
|
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
|
|
160
|
-
HotelOfferRequest
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
+
}
|
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
export interface PaymentMethodCreditCard extends BasePaymentMethodCreditCard {
|
|
27
|
+
payload: {
|
|
28
|
+
amount: number
|
|
29
|
+
couponId?: string | null
|
|
30
|
+
token: string
|
|
31
|
+
}
|
|
47
32
|
}
|
|
48
33
|
|
|
49
|
-
|
|
34
|
+
export interface BasePaymentMethodCoupon extends BasePaymentMethod {
|
|
35
|
+
name: 'COUPON'
|
|
36
|
+
}
|
|
50
37
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
}
|
|
@@ -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,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
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -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 {
|
|
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:
|
|
14
|
+
schema: z.ZodType,
|
|
12
15
|
transformer: (str: string) => string,
|
|
13
|
-
):
|
|
14
|
-
let result:
|
|
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.
|
|
19
|
-
const transformedShape: Record<string,
|
|
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
|
|
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 {
|
|
39
|
+
const { element } = schema.def
|
|
37
40
|
result = z.array(
|
|
38
|
-
transformSchemaKeysWithTransformer(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
85
|
-
const transformedOptions = options.map((option:
|
|
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 [
|
|
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.
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
|
125
|
+
export function transformSchemaKeys<T extends z.ZodType>(
|
|
133
126
|
schema: T,
|
|
134
127
|
toCase: CaseTransformer,
|
|
135
128
|
): T {
|
package/src/assets/index.ts
DELETED
|
Binary file
|
|
Binary file
|