more-apartments-astro-integration 1.0.1
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/.more-apartments/availability.json +36 -0
- package/.more-apartments/booking-response.json +15 -0
- package/.more-apartments/categories.json +11 -0
- package/.more-apartments/locations.json +3 -0
- package/.more-apartments/pages.json +46 -0
- package/.more-apartments/posts.json +3 -0
- package/.more-apartments/properties.json +1761 -0
- package/.more-apartments/settings-booking.json +13 -0
- package/.more-apartments/settings-main.json +32 -0
- package/.more-apartments/settings-properties.json +36 -0
- package/.more-apartments/settings-theme.json +78 -0
- package/README.md +982 -0
- package/dist/cli/index.js +1010 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.mts +2732 -0
- package/dist/index.d.ts +2732 -0
- package/dist/index.js +1009 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +964 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +75 -0
- package/routes/availability.js +40 -0
- package/routes/bookings.js +66 -0
- package/routes/locations.js +28 -0
- package/routes/page.js +27 -0
- package/routes/pages.js +27 -0
- package/routes/post.js +27 -0
- package/routes/posts.js +32 -0
- package/routes/properties.js +31 -0
- package/routes/property.js +27 -0
- package/routes/settings.js +50 -0
- package/src/components/PropertyBookingWidget.astro +169 -0
- package/src/components/PropertySearchGrid.astro +315 -0
- package/src/pages/booking-complete.astro +155 -0
|
@@ -0,0 +1,1010 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var commander = require('commander');
|
|
5
|
+
var dotenv = require('dotenv');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
var zod = require('zod');
|
|
8
|
+
var util = require('util');
|
|
9
|
+
var fs = require('fs');
|
|
10
|
+
|
|
11
|
+
var PaginationLinksSchema = zod.z.object({
|
|
12
|
+
first: zod.z.string().nullable(),
|
|
13
|
+
last: zod.z.string().nullable(),
|
|
14
|
+
prev: zod.z.string().nullable(),
|
|
15
|
+
next: zod.z.string().nullable()
|
|
16
|
+
});
|
|
17
|
+
var PaginationMetaSchema = zod.z.object({
|
|
18
|
+
current_page: zod.z.number(),
|
|
19
|
+
from: zod.z.number().nullable(),
|
|
20
|
+
last_page: zod.z.number(),
|
|
21
|
+
links: zod.z.array(zod.z.object({
|
|
22
|
+
url: zod.z.string().nullable(),
|
|
23
|
+
label: zod.z.string(),
|
|
24
|
+
active: zod.z.boolean()
|
|
25
|
+
})),
|
|
26
|
+
path: zod.z.string(),
|
|
27
|
+
per_page: zod.z.number(),
|
|
28
|
+
to: zod.z.number().nullable(),
|
|
29
|
+
total: zod.z.number()
|
|
30
|
+
});
|
|
31
|
+
var PaginatedResponseSchema = (dataSchema) => zod.z.object({
|
|
32
|
+
data: zod.z.array(dataSchema),
|
|
33
|
+
links: PaginationLinksSchema,
|
|
34
|
+
meta: PaginationMetaSchema
|
|
35
|
+
});
|
|
36
|
+
zod.z.object({
|
|
37
|
+
message: zod.z.string(),
|
|
38
|
+
errors: zod.z.record(zod.z.array(zod.z.string())).optional()
|
|
39
|
+
});
|
|
40
|
+
zod.z.object({
|
|
41
|
+
id: zod.z.number(),
|
|
42
|
+
url: zod.z.string(),
|
|
43
|
+
alt: zod.z.string().optional()
|
|
44
|
+
});
|
|
45
|
+
var PropertySchema = zod.z.object({
|
|
46
|
+
id: zod.z.number(),
|
|
47
|
+
external_id: zod.z.number().optional(),
|
|
48
|
+
name: zod.z.string(),
|
|
49
|
+
slug: zod.z.string(),
|
|
50
|
+
// Descriptions
|
|
51
|
+
short_description: zod.z.string().nullable(),
|
|
52
|
+
description: zod.z.string(),
|
|
53
|
+
area_description: zod.z.string().nullable(),
|
|
54
|
+
arrival_description: zod.z.string().nullable(),
|
|
55
|
+
// Property type & capacity
|
|
56
|
+
type: zod.z.string().nullable(),
|
|
57
|
+
max_persons: zod.z.number().nullable(),
|
|
58
|
+
bedrooms: zod.z.number().nullable(),
|
|
59
|
+
bathrooms: zod.z.number().nullable(),
|
|
60
|
+
toilets: zod.z.number().nullable(),
|
|
61
|
+
size: zod.z.number().nullable(),
|
|
62
|
+
floor: zod.z.number().nullable(),
|
|
63
|
+
// Location
|
|
64
|
+
street: zod.z.string().nullable(),
|
|
65
|
+
zipcode: zod.z.string().nullable(),
|
|
66
|
+
area: zod.z.string().nullable(),
|
|
67
|
+
city: zod.z.string(),
|
|
68
|
+
country: zod.z.string(),
|
|
69
|
+
latitude: zod.z.number(),
|
|
70
|
+
longitude: zod.z.number(),
|
|
71
|
+
// Beds
|
|
72
|
+
single_bed: zod.z.number().nullable(),
|
|
73
|
+
double_bed: zod.z.number().nullable(),
|
|
74
|
+
single_sofa: zod.z.number().nullable(),
|
|
75
|
+
double_sofa: zod.z.number().nullable(),
|
|
76
|
+
single_bunk: zod.z.number().nullable(),
|
|
77
|
+
// Amenities - Outdoor
|
|
78
|
+
balcony: zod.z.boolean(),
|
|
79
|
+
terrace: zod.z.boolean(),
|
|
80
|
+
view: zod.z.string().nullable(),
|
|
81
|
+
// Amenities - Climate
|
|
82
|
+
airco: zod.z.boolean(),
|
|
83
|
+
fans: zod.z.boolean(),
|
|
84
|
+
heating: zod.z.boolean(),
|
|
85
|
+
// Amenities - Connectivity
|
|
86
|
+
internet: zod.z.string().nullable(),
|
|
87
|
+
internet_connection: zod.z.string().nullable(),
|
|
88
|
+
tv: zod.z.string().nullable(),
|
|
89
|
+
tv_connection: zod.z.string().nullable(),
|
|
90
|
+
dvd: zod.z.boolean(),
|
|
91
|
+
computer: zod.z.boolean(),
|
|
92
|
+
printer: zod.z.boolean(),
|
|
93
|
+
// Amenities - Kitchen
|
|
94
|
+
dishwasher: zod.z.boolean(),
|
|
95
|
+
oven: zod.z.boolean(),
|
|
96
|
+
microwave: zod.z.boolean(),
|
|
97
|
+
fridge: zod.z.boolean(),
|
|
98
|
+
freezer: zod.z.boolean(),
|
|
99
|
+
toaster: zod.z.boolean(),
|
|
100
|
+
kettle: zod.z.boolean(),
|
|
101
|
+
coffeemachine: zod.z.boolean(),
|
|
102
|
+
// Amenities - Laundry
|
|
103
|
+
washingmachine: zod.z.boolean(),
|
|
104
|
+
dryer: zod.z.boolean(),
|
|
105
|
+
iron: zod.z.boolean(),
|
|
106
|
+
// Amenities - Bathroom
|
|
107
|
+
bathtub: zod.z.boolean(),
|
|
108
|
+
jacuzzi: zod.z.boolean(),
|
|
109
|
+
shower_regular: zod.z.boolean(),
|
|
110
|
+
shower_steam: zod.z.boolean(),
|
|
111
|
+
hairdryer: zod.z.boolean(),
|
|
112
|
+
// Amenities - Recreation
|
|
113
|
+
swimmingpool: zod.z.string().nullable(),
|
|
114
|
+
sauna: zod.z.string().nullable(),
|
|
115
|
+
// Amenities - General
|
|
116
|
+
parking: zod.z.string().nullable(),
|
|
117
|
+
entresol: zod.z.boolean(),
|
|
118
|
+
wheelchair_friendly: zod.z.boolean(),
|
|
119
|
+
smoking_allowed: zod.z.boolean(),
|
|
120
|
+
pets_allowed: zod.z.boolean(),
|
|
121
|
+
// Supplies
|
|
122
|
+
supplies_coffee: zod.z.boolean(),
|
|
123
|
+
supplies_tea: zod.z.boolean(),
|
|
124
|
+
supplies_milk: zod.z.boolean(),
|
|
125
|
+
supplies_sugar: zod.z.boolean(),
|
|
126
|
+
supplies_dishwasher_tablets: zod.z.boolean(),
|
|
127
|
+
// Services
|
|
128
|
+
service_linen: zod.z.boolean(),
|
|
129
|
+
service_towels: zod.z.boolean(),
|
|
130
|
+
// Costs & Policies
|
|
131
|
+
cleaning_costs: zod.z.number().nullable(),
|
|
132
|
+
deposit_costs: zod.z.number().nullable(),
|
|
133
|
+
min_rate: zod.z.number().nullable(),
|
|
134
|
+
minimal_nights: zod.z.number().nullable(),
|
|
135
|
+
maximal_nights: zod.z.number().nullable(),
|
|
136
|
+
// Check-in/out
|
|
137
|
+
check_in: zod.z.string().nullable(),
|
|
138
|
+
check_out: zod.z.string().nullable(),
|
|
139
|
+
// Media
|
|
140
|
+
images: zod.z.array(zod.z.object({
|
|
141
|
+
id: zod.z.number(),
|
|
142
|
+
url: zod.z.string(),
|
|
143
|
+
thumb_url: zod.z.string(),
|
|
144
|
+
alt: zod.z.string()
|
|
145
|
+
})).optional(),
|
|
146
|
+
// Metadata
|
|
147
|
+
status: zod.z.string().nullable(),
|
|
148
|
+
provider_name: zod.z.string().nullable(),
|
|
149
|
+
created_at: zod.z.string(),
|
|
150
|
+
updated_at: zod.z.string()
|
|
151
|
+
});
|
|
152
|
+
var AvailableDay = zod.z.object({
|
|
153
|
+
available: zod.z.boolean(),
|
|
154
|
+
morning_available: zod.z.boolean(),
|
|
155
|
+
date: zod.z.string(),
|
|
156
|
+
day: zod.z.number()
|
|
157
|
+
});
|
|
158
|
+
var AvailabilitySchema = zod.z.object({
|
|
159
|
+
days: zod.z.record(zod.z.string(), AvailableDay)
|
|
160
|
+
});
|
|
161
|
+
zod.z.object({
|
|
162
|
+
// Date filters
|
|
163
|
+
arrival: zod.z.string().optional(),
|
|
164
|
+
departure: zod.z.string().optional(),
|
|
165
|
+
// Guest capacity
|
|
166
|
+
guests: zod.z.number().optional(),
|
|
167
|
+
// General search (deprecated in favor of direct column filters)
|
|
168
|
+
destination: zod.z.string().optional(),
|
|
169
|
+
segment: zod.z.string().optional(),
|
|
170
|
+
// DEPRECATED: use city/area instead
|
|
171
|
+
// Direct column filters (preferred for headless instances)
|
|
172
|
+
city: zod.z.string().optional(),
|
|
173
|
+
area: zod.z.string().optional(),
|
|
174
|
+
propertyType: zod.z.string().optional(),
|
|
175
|
+
bedrooms: zod.z.number().optional(),
|
|
176
|
+
bathrooms: zod.z.number().optional(),
|
|
177
|
+
maxPersons: zod.z.number().optional(),
|
|
178
|
+
elevator: zod.z.boolean().optional(),
|
|
179
|
+
parking: zod.z.boolean().optional(),
|
|
180
|
+
balcony: zod.z.boolean().optional()
|
|
181
|
+
});
|
|
182
|
+
var PropertySearchResultSchema = zod.z.object({
|
|
183
|
+
data: zod.z.array(PropertySchema)
|
|
184
|
+
});
|
|
185
|
+
zod.z.object({
|
|
186
|
+
routing: zod.z.object({
|
|
187
|
+
base_url: zod.z.string()
|
|
188
|
+
}),
|
|
189
|
+
index: zod.z.object({
|
|
190
|
+
seo: zod.z.object({
|
|
191
|
+
title: zod.z.string(),
|
|
192
|
+
description: zod.z.string(),
|
|
193
|
+
openGraphTitle: zod.z.string().optional(),
|
|
194
|
+
tags: zod.z.array(zod.z.string()).optional()
|
|
195
|
+
})
|
|
196
|
+
}),
|
|
197
|
+
show: zod.z.object({
|
|
198
|
+
hero: zod.z.object({
|
|
199
|
+
provider: zod.z.boolean().optional(),
|
|
200
|
+
address: zod.z.boolean().optional()
|
|
201
|
+
}).optional(),
|
|
202
|
+
cancellation_policy: zod.z.object({
|
|
203
|
+
description: zod.z.string()
|
|
204
|
+
}).optional(),
|
|
205
|
+
related_properties: zod.z.object({
|
|
206
|
+
title: zod.z.string()
|
|
207
|
+
}).optional()
|
|
208
|
+
}).optional()
|
|
209
|
+
});
|
|
210
|
+
var PageSchema = zod.z.object({
|
|
211
|
+
id: zod.z.string(),
|
|
212
|
+
slug: zod.z.string(),
|
|
213
|
+
title: zod.z.string().nullable(),
|
|
214
|
+
description: zod.z.string().nullable(),
|
|
215
|
+
content: zod.z.string().nullable(),
|
|
216
|
+
sections: zod.z.array(zod.z.any()),
|
|
217
|
+
seo: zod.z.object({
|
|
218
|
+
title: zod.z.string(),
|
|
219
|
+
description: zod.z.string(),
|
|
220
|
+
image: zod.z.string().nullable()
|
|
221
|
+
}),
|
|
222
|
+
route_name: zod.z.string()
|
|
223
|
+
});
|
|
224
|
+
var PostSchema = zod.z.object({
|
|
225
|
+
id: zod.z.string(),
|
|
226
|
+
slug: zod.z.string(),
|
|
227
|
+
title: zod.z.string(),
|
|
228
|
+
description: zod.z.string().nullable(),
|
|
229
|
+
content: zod.z.string().nullable(),
|
|
230
|
+
excerpt: zod.z.string().nullable(),
|
|
231
|
+
author: zod.z.string().nullable(),
|
|
232
|
+
date: zod.z.string(),
|
|
233
|
+
// ISO date string
|
|
234
|
+
image: zod.z.string().nullable(),
|
|
235
|
+
tags: zod.z.array(zod.z.string()),
|
|
236
|
+
reading_time: zod.z.string().nullable(),
|
|
237
|
+
sections: zod.z.array(zod.z.any()),
|
|
238
|
+
seo: zod.z.object({
|
|
239
|
+
title: zod.z.string(),
|
|
240
|
+
description: zod.z.string(),
|
|
241
|
+
image: zod.z.string().nullable()
|
|
242
|
+
}),
|
|
243
|
+
route_name: zod.z.string()
|
|
244
|
+
});
|
|
245
|
+
var CategorySchema = zod.z.object({
|
|
246
|
+
slug: zod.z.string(),
|
|
247
|
+
name: zod.z.string(),
|
|
248
|
+
title: zod.z.string(),
|
|
249
|
+
description: zod.z.string().nullable(),
|
|
250
|
+
content: zod.z.string().nullable(),
|
|
251
|
+
segments: zod.z.union([zod.z.array(zod.z.string()), zod.z.number()]).optional()
|
|
252
|
+
});
|
|
253
|
+
var CategorySegmentSchema = zod.z.object({
|
|
254
|
+
name: zod.z.string(),
|
|
255
|
+
slug: zod.z.string(),
|
|
256
|
+
title: zod.z.string(),
|
|
257
|
+
description: zod.z.string().nullable(),
|
|
258
|
+
tags: zod.z.array(zod.z.string()).optional(),
|
|
259
|
+
sections: zod.z.array(zod.z.any()),
|
|
260
|
+
content: zod.z.string().nullable(),
|
|
261
|
+
image: zod.z.string()
|
|
262
|
+
});
|
|
263
|
+
var MainSettingsSchema = zod.z.object({
|
|
264
|
+
site: zod.z.object({
|
|
265
|
+
name: zod.z.string(),
|
|
266
|
+
domain: zod.z.string(),
|
|
267
|
+
locale: zod.z.string()
|
|
268
|
+
}),
|
|
269
|
+
contact: zod.z.object({
|
|
270
|
+
email: zod.z.string(),
|
|
271
|
+
phone: zod.z.string().optional()
|
|
272
|
+
}),
|
|
273
|
+
social: zod.z.object({
|
|
274
|
+
facebook: zod.z.string().optional(),
|
|
275
|
+
instagram: zod.z.string().optional()
|
|
276
|
+
}).optional(),
|
|
277
|
+
mail: zod.z.object({
|
|
278
|
+
from: zod.z.object({
|
|
279
|
+
address: zod.z.string(),
|
|
280
|
+
name: zod.z.string()
|
|
281
|
+
}),
|
|
282
|
+
contact_form_to: zod.z.string()
|
|
283
|
+
}).optional(),
|
|
284
|
+
pms: zod.z.object({
|
|
285
|
+
property_providers: zod.z.array(zod.z.object({
|
|
286
|
+
name: zod.z.string(),
|
|
287
|
+
system: zod.z.string(),
|
|
288
|
+
api_key: zod.z.string().optional(),
|
|
289
|
+
base_url: zod.z.string().optional(),
|
|
290
|
+
discount: zod.z.number().optional(),
|
|
291
|
+
enabled: zod.z.boolean().optional()
|
|
292
|
+
}))
|
|
293
|
+
}).optional(),
|
|
294
|
+
pricing: zod.z.object({
|
|
295
|
+
vat: zod.z.number(),
|
|
296
|
+
tourist_tax: zod.z.object({
|
|
297
|
+
type: zod.z.string(),
|
|
298
|
+
value: zod.z.number()
|
|
299
|
+
})
|
|
300
|
+
}).optional(),
|
|
301
|
+
discount: zod.z.number().optional()
|
|
302
|
+
});
|
|
303
|
+
var ThemeSettingsSchema = zod.z.object({
|
|
304
|
+
logo: zod.z.object({
|
|
305
|
+
path: zod.z.string(),
|
|
306
|
+
height: zod.z.number().optional()
|
|
307
|
+
}).optional(),
|
|
308
|
+
favicon_path: zod.z.string().optional(),
|
|
309
|
+
colors: zod.z.object({
|
|
310
|
+
primary: zod.z.string(),
|
|
311
|
+
secondary: zod.z.string()
|
|
312
|
+
}),
|
|
313
|
+
layout: zod.z.object({
|
|
314
|
+
homepage_style: zod.z.string().optional(),
|
|
315
|
+
navigation: zod.z.object({
|
|
316
|
+
variant: zod.z.string().optional(),
|
|
317
|
+
items: zod.z.array(zod.z.any()),
|
|
318
|
+
buttons: zod.z.array(zod.z.any()).optional()
|
|
319
|
+
}).optional(),
|
|
320
|
+
footer: zod.z.object({
|
|
321
|
+
blog_title: zod.z.string().optional(),
|
|
322
|
+
contact_title: zod.z.string().optional(),
|
|
323
|
+
categories: zod.z.array(zod.z.any()).optional()
|
|
324
|
+
}).optional()
|
|
325
|
+
}).optional()
|
|
326
|
+
});
|
|
327
|
+
var PropertySettingsSchema = zod.z.object({
|
|
328
|
+
routing: zod.z.object({
|
|
329
|
+
base_url: zod.z.string()
|
|
330
|
+
}),
|
|
331
|
+
seo: zod.z.object({
|
|
332
|
+
title: zod.z.string(),
|
|
333
|
+
description: zod.z.string(),
|
|
334
|
+
openGraphTitle: zod.z.string().optional(),
|
|
335
|
+
tags: zod.z.array(zod.z.string()).optional()
|
|
336
|
+
}).optional(),
|
|
337
|
+
index: zod.z.object({
|
|
338
|
+
seo: zod.z.object({
|
|
339
|
+
title: zod.z.string(),
|
|
340
|
+
description: zod.z.string(),
|
|
341
|
+
openGraphTitle: zod.z.string().optional(),
|
|
342
|
+
tags: zod.z.array(zod.z.string()).optional()
|
|
343
|
+
})
|
|
344
|
+
}),
|
|
345
|
+
show: zod.z.object({
|
|
346
|
+
hero: zod.z.object({
|
|
347
|
+
provider: zod.z.boolean().optional(),
|
|
348
|
+
address: zod.z.boolean().optional()
|
|
349
|
+
}).optional(),
|
|
350
|
+
cancellation_policy: zod.z.object({
|
|
351
|
+
description: zod.z.string()
|
|
352
|
+
}).optional(),
|
|
353
|
+
related_properties: zod.z.object({
|
|
354
|
+
title: zod.z.string()
|
|
355
|
+
}).optional()
|
|
356
|
+
}).optional()
|
|
357
|
+
});
|
|
358
|
+
var BookingSettingsSchema = zod.z.object({
|
|
359
|
+
booking_confirmation: zod.z.object({
|
|
360
|
+
sections: zod.z.object({
|
|
361
|
+
arrival_description: zod.z.boolean().optional()
|
|
362
|
+
}).optional(),
|
|
363
|
+
content: zod.z.object({
|
|
364
|
+
body: zod.z.string().optional(),
|
|
365
|
+
help: zod.z.string().optional()
|
|
366
|
+
}).optional()
|
|
367
|
+
}).optional()
|
|
368
|
+
});
|
|
369
|
+
zod.z.object({
|
|
370
|
+
property_id: zod.z.number(),
|
|
371
|
+
check_in: zod.z.string(),
|
|
372
|
+
check_out: zod.z.string(),
|
|
373
|
+
guests: zod.z.number(),
|
|
374
|
+
first_name: zod.z.string(),
|
|
375
|
+
last_name: zod.z.string(),
|
|
376
|
+
email: zod.z.string().email(),
|
|
377
|
+
phone: zod.z.string().optional(),
|
|
378
|
+
notes: zod.z.string().optional(),
|
|
379
|
+
total_amount: zod.z.number(),
|
|
380
|
+
payment_method: zod.z.enum(["stripe", "cash", "bank_transfer"]).optional()
|
|
381
|
+
});
|
|
382
|
+
var BookingResponseSchema = zod.z.object({
|
|
383
|
+
id: zod.z.string(),
|
|
384
|
+
property_id: zod.z.number(),
|
|
385
|
+
check_in: zod.z.string(),
|
|
386
|
+
check_out: zod.z.string(),
|
|
387
|
+
guests: zod.z.number(),
|
|
388
|
+
status: zod.z.enum(["pending", "confirmed", "cancelled", "completed"]),
|
|
389
|
+
total_amount: zod.z.number(),
|
|
390
|
+
payment_status: zod.z.enum(["pending", "paid", "refunded"]),
|
|
391
|
+
confirmation_code: zod.z.string(),
|
|
392
|
+
created_at: zod.z.string(),
|
|
393
|
+
updated_at: zod.z.string()
|
|
394
|
+
});
|
|
395
|
+
zod.z.object({
|
|
396
|
+
baseUrl: zod.z.string().optional(),
|
|
397
|
+
apiKey: zod.z.string().optional(),
|
|
398
|
+
instance: zod.z.string().optional(),
|
|
399
|
+
timeout: zod.z.number().optional(),
|
|
400
|
+
retry: zod.z.object({
|
|
401
|
+
attempts: zod.z.number(),
|
|
402
|
+
delay: zod.z.number()
|
|
403
|
+
}).optional(),
|
|
404
|
+
cache: zod.z.object({
|
|
405
|
+
enabled: zod.z.boolean(),
|
|
406
|
+
ttl: zod.z.number()
|
|
407
|
+
}).optional()
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// src/client.ts
|
|
411
|
+
var MoreApartmentsClient = class {
|
|
412
|
+
config;
|
|
413
|
+
cache = /* @__PURE__ */ new Map();
|
|
414
|
+
/**
|
|
415
|
+
* Clear all cached data
|
|
416
|
+
*/
|
|
417
|
+
clearCache() {
|
|
418
|
+
this.cache.clear();
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Get cache statistics
|
|
422
|
+
*/
|
|
423
|
+
getCacheStats() {
|
|
424
|
+
return {
|
|
425
|
+
entries: this.cache.size,
|
|
426
|
+
size: Array.from(this.cache.values()).reduce((total, entry) => {
|
|
427
|
+
return total + JSON.stringify(entry.data).length;
|
|
428
|
+
}, 0)
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
constructor(config2) {
|
|
432
|
+
this.config = {
|
|
433
|
+
baseUrl: config2.baseUrl?.replace(/\/$/, "") || "",
|
|
434
|
+
apiKey: config2.apiKey || "",
|
|
435
|
+
instance: config2.instance || "",
|
|
436
|
+
timeout: config2.timeout || 3e4,
|
|
437
|
+
retry: {
|
|
438
|
+
attempts: config2.retry?.attempts || 3,
|
|
439
|
+
delay: config2.retry?.delay || 1e3
|
|
440
|
+
},
|
|
441
|
+
cache: {
|
|
442
|
+
enabled: config2.cache?.enabled ?? true,
|
|
443
|
+
ttl: config2.cache?.ttl || 3e5
|
|
444
|
+
// 5 minutes default
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
async fetchWithRetry(url, options = {}, schema) {
|
|
449
|
+
const cacheKey = `${options.method || "GET"}:${url}`;
|
|
450
|
+
if (this.config.cache?.enabled && (!options.method || options.method === "GET")) {
|
|
451
|
+
const cached = this.cache.get(cacheKey);
|
|
452
|
+
if (cached && this.config.cache?.ttl && Date.now() - cached.timestamp < this.config.cache.ttl) {
|
|
453
|
+
return cached.data;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
const headers = {
|
|
457
|
+
"Content-Type": "application/json",
|
|
458
|
+
"Accept": "application/json",
|
|
459
|
+
...this.config.apiKey && { "Authorization": `Bearer ${this.config.apiKey}` },
|
|
460
|
+
...this.config.instance && { "X-Instance": this.config.instance },
|
|
461
|
+
...options.headers
|
|
462
|
+
};
|
|
463
|
+
let lastError = null;
|
|
464
|
+
for (let attempt = 0; attempt < (this.config.retry?.attempts ?? 3); attempt++) {
|
|
465
|
+
try {
|
|
466
|
+
const controller = new AbortController();
|
|
467
|
+
const timeoutId = setTimeout(() => {
|
|
468
|
+
controller.abort();
|
|
469
|
+
}, this.config.timeout);
|
|
470
|
+
const response = await fetch(url, {
|
|
471
|
+
...options,
|
|
472
|
+
headers,
|
|
473
|
+
signal: controller.signal
|
|
474
|
+
});
|
|
475
|
+
clearTimeout(timeoutId);
|
|
476
|
+
if (!response.ok) {
|
|
477
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
478
|
+
throw new Error(error.message || `HTTP ${response.status}: ${response.statusText}`);
|
|
479
|
+
}
|
|
480
|
+
const data = await response.json();
|
|
481
|
+
if (schema) {
|
|
482
|
+
const result = schema.safeParse(data);
|
|
483
|
+
if (!result.success) {
|
|
484
|
+
throw new Error(`Invalid response format: ${result.error.message}`);
|
|
485
|
+
}
|
|
486
|
+
const validatedData = result.data;
|
|
487
|
+
if (this.config.cache?.enabled && (!options.method || options.method === "GET")) {
|
|
488
|
+
this.cache.set(cacheKey, { data: validatedData, timestamp: Date.now() });
|
|
489
|
+
}
|
|
490
|
+
return validatedData;
|
|
491
|
+
}
|
|
492
|
+
if (this.config.cache?.enabled && (!options.method || options.method === "GET")) {
|
|
493
|
+
this.cache.set(cacheKey, { data, timestamp: Date.now() });
|
|
494
|
+
}
|
|
495
|
+
return data;
|
|
496
|
+
} catch (error) {
|
|
497
|
+
lastError = error;
|
|
498
|
+
if (attempt < (this.config.retry?.attempts ?? 3) - 1) {
|
|
499
|
+
await new Promise((resolve3) => setTimeout(resolve3, (this.config.retry?.delay ?? 1e3) * (attempt + 1)));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
throw lastError || new Error("Request failed");
|
|
504
|
+
}
|
|
505
|
+
// Property endpoints
|
|
506
|
+
async getProperties(params) {
|
|
507
|
+
const queryParams = new URLSearchParams();
|
|
508
|
+
if (params?.page) queryParams.append("page", params.page.toString());
|
|
509
|
+
if (params?.per_page) queryParams.append("per_page", params.per_page.toString());
|
|
510
|
+
const url = `${this.config.baseUrl}/api/v1/properties${queryParams.toString() ? "?" + queryParams.toString() : ""}`;
|
|
511
|
+
return this.fetchWithRetry(url, {}, PaginatedResponseSchema(PropertySchema));
|
|
512
|
+
}
|
|
513
|
+
async getProperty(propertyIdOrSlug) {
|
|
514
|
+
const url = `${this.config.baseUrl}/api/v1/properties/${propertyIdOrSlug}`;
|
|
515
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: PropertySchema }));
|
|
516
|
+
return response.data;
|
|
517
|
+
}
|
|
518
|
+
// Availability endpoints
|
|
519
|
+
async getAvailability(propertySlug, startDate, endDate) {
|
|
520
|
+
const queryParams = new URLSearchParams({
|
|
521
|
+
start_date: startDate,
|
|
522
|
+
end_date: endDate
|
|
523
|
+
});
|
|
524
|
+
const url = `${this.config.baseUrl}/api/v1/properties/${propertySlug}/availability?${queryParams}`;
|
|
525
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: AvailabilitySchema }));
|
|
526
|
+
return response.data;
|
|
527
|
+
}
|
|
528
|
+
// Content endpoints
|
|
529
|
+
async getPages() {
|
|
530
|
+
const url = `${this.config.baseUrl}/api/v1/pages`;
|
|
531
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: zod.z.array(PageSchema) }));
|
|
532
|
+
return response.data;
|
|
533
|
+
}
|
|
534
|
+
async getPage(slug) {
|
|
535
|
+
const url = `${this.config.baseUrl}/api/v1/pages/${slug}`;
|
|
536
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: PageSchema }));
|
|
537
|
+
return response.data;
|
|
538
|
+
}
|
|
539
|
+
async getPosts(params) {
|
|
540
|
+
const queryParams = new URLSearchParams();
|
|
541
|
+
if (params?.page) queryParams.append("page", params.page.toString());
|
|
542
|
+
if (params?.per_page) queryParams.append("per_page", params.per_page.toString());
|
|
543
|
+
if (params?.tag) queryParams.append("tag", params.tag);
|
|
544
|
+
const url = `${this.config.baseUrl}/api/v1/posts${queryParams.toString() ? "?" + queryParams.toString() : ""}`;
|
|
545
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: zod.z.array(PostSchema) }));
|
|
546
|
+
return response.data;
|
|
547
|
+
}
|
|
548
|
+
async getPost(slug) {
|
|
549
|
+
const url = `${this.config.baseUrl}/api/v1/posts/${slug}`;
|
|
550
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: PostSchema }));
|
|
551
|
+
return response.data;
|
|
552
|
+
}
|
|
553
|
+
async getLocations() {
|
|
554
|
+
const url = `${this.config.baseUrl}/api/v1/locations`;
|
|
555
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: zod.z.array(zod.z.string()) }));
|
|
556
|
+
return response.data;
|
|
557
|
+
}
|
|
558
|
+
async getCategories() {
|
|
559
|
+
const url = `${this.config.baseUrl}/api/v1/categories`;
|
|
560
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: zod.z.array(CategorySchema) }));
|
|
561
|
+
return response.data;
|
|
562
|
+
}
|
|
563
|
+
async getCategory(slug) {
|
|
564
|
+
const url = `${this.config.baseUrl}/api/v1/categories/${slug}`;
|
|
565
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: CategorySchema }));
|
|
566
|
+
return response.data;
|
|
567
|
+
}
|
|
568
|
+
async getCategorySegments(slug) {
|
|
569
|
+
const url = `${this.config.baseUrl}/api/v1/categories/${slug}/segments`;
|
|
570
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: zod.z.array(CategorySegmentSchema) }));
|
|
571
|
+
return response.data;
|
|
572
|
+
}
|
|
573
|
+
async getCategorySegment(slug, segment) {
|
|
574
|
+
const url = `${this.config.baseUrl}/api/v1/categories/${slug}/segments/${segment}`;
|
|
575
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: CategorySegmentSchema }));
|
|
576
|
+
return response.data;
|
|
577
|
+
}
|
|
578
|
+
// Settings endpoints
|
|
579
|
+
async getMainSettings() {
|
|
580
|
+
const url = `${this.config.baseUrl}/api/v1/settings/main`;
|
|
581
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: MainSettingsSchema }));
|
|
582
|
+
return response.data;
|
|
583
|
+
}
|
|
584
|
+
async getThemeSettings() {
|
|
585
|
+
const url = `${this.config.baseUrl}/api/v1/settings/theme`;
|
|
586
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: ThemeSettingsSchema }));
|
|
587
|
+
return response.data;
|
|
588
|
+
}
|
|
589
|
+
async getPropertySettings() {
|
|
590
|
+
const url = `${this.config.baseUrl}/api/v1/settings/properties`;
|
|
591
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: PropertySettingsSchema }));
|
|
592
|
+
return response.data;
|
|
593
|
+
}
|
|
594
|
+
async getBookingSettings() {
|
|
595
|
+
const url = `${this.config.baseUrl}/api/v1/settings/booking`;
|
|
596
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: BookingSettingsSchema }));
|
|
597
|
+
return response.data;
|
|
598
|
+
}
|
|
599
|
+
// Booking endpoints
|
|
600
|
+
async createBooking(booking) {
|
|
601
|
+
const url = `${this.config.baseUrl}/api/v1/bookings`;
|
|
602
|
+
const response = await this.fetchWithRetry(
|
|
603
|
+
url,
|
|
604
|
+
{
|
|
605
|
+
method: "POST",
|
|
606
|
+
body: JSON.stringify(booking)
|
|
607
|
+
},
|
|
608
|
+
zod.z.object({ data: BookingResponseSchema })
|
|
609
|
+
);
|
|
610
|
+
return response.data;
|
|
611
|
+
}
|
|
612
|
+
async getBooking(bookingId) {
|
|
613
|
+
const url = `${this.config.baseUrl}/api/v1/bookings/${bookingId}`;
|
|
614
|
+
const response = await this.fetchWithRetry(url, {}, zod.z.object({ data: BookingResponseSchema }));
|
|
615
|
+
return response.data;
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Search properties with advanced filtering
|
|
619
|
+
*/
|
|
620
|
+
async searchProperties(params) {
|
|
621
|
+
const searchParams = new URLSearchParams();
|
|
622
|
+
if (params.arrival) searchParams.set("arrival", params.arrival);
|
|
623
|
+
if (params.departure) searchParams.set("departure", params.departure);
|
|
624
|
+
if (params.guests) searchParams.set("guests", params.guests.toString());
|
|
625
|
+
if (params.destination) searchParams.set("destination", params.destination);
|
|
626
|
+
if (params.segment) searchParams.set("segment", params.segment);
|
|
627
|
+
if (params.city) searchParams.set("city", params.city);
|
|
628
|
+
if (params.area) searchParams.set("area", params.area);
|
|
629
|
+
if (params.propertyType) searchParams.set("property_type", params.propertyType);
|
|
630
|
+
if (params.bedrooms !== void 0) searchParams.set("bedrooms", params.bedrooms.toString());
|
|
631
|
+
if (params.bathrooms !== void 0) searchParams.set("bathrooms", params.bathrooms.toString());
|
|
632
|
+
if (params.maxPersons !== void 0) searchParams.set("max_persons", params.maxPersons.toString());
|
|
633
|
+
if (params.elevator !== void 0) searchParams.set("elevator", params.elevator ? "1" : "0");
|
|
634
|
+
if (params.parking !== void 0) searchParams.set("parking", params.parking ? "1" : "0");
|
|
635
|
+
if (params.balcony !== void 0) searchParams.set("balcony", params.balcony ? "1" : "0");
|
|
636
|
+
const url = `${this.config.baseUrl}/api/v1/properties/search?${searchParams.toString()}`;
|
|
637
|
+
const response = await this.fetchWithRetry(url, {}, PropertySearchResultSchema);
|
|
638
|
+
return response.data;
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
function formatOutput(data, format = "json") {
|
|
642
|
+
switch (format) {
|
|
643
|
+
case "json":
|
|
644
|
+
console.log(JSON.stringify(data, null, 2));
|
|
645
|
+
break;
|
|
646
|
+
case "yaml":
|
|
647
|
+
console.log(toYAML(data));
|
|
648
|
+
break;
|
|
649
|
+
case "table":
|
|
650
|
+
if (Array.isArray(data)) {
|
|
651
|
+
console.table(data);
|
|
652
|
+
} else {
|
|
653
|
+
console.table([data]);
|
|
654
|
+
}
|
|
655
|
+
break;
|
|
656
|
+
default:
|
|
657
|
+
console.log(util.inspect(data, { depth: null, colors: true }));
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
function toYAML(obj, indent = 0) {
|
|
661
|
+
const spaces = " ".repeat(indent);
|
|
662
|
+
if (obj === null || obj === void 0) {
|
|
663
|
+
return "null";
|
|
664
|
+
}
|
|
665
|
+
if (typeof obj === "string") {
|
|
666
|
+
return obj.includes("\n") ? `|
|
|
667
|
+
${obj.split("\n").map((line) => `${spaces} ${line}`).join("\n")}` : obj;
|
|
668
|
+
}
|
|
669
|
+
if (typeof obj === "number" || typeof obj === "boolean") {
|
|
670
|
+
return String(obj);
|
|
671
|
+
}
|
|
672
|
+
if (Array.isArray(obj)) {
|
|
673
|
+
if (obj.length === 0) return "[]";
|
|
674
|
+
return "\n" + obj.map((item) => `${spaces}- ${toYAML(item, indent + 1)}`).join("\n");
|
|
675
|
+
}
|
|
676
|
+
if (typeof obj === "object") {
|
|
677
|
+
const entries = Object.entries(obj);
|
|
678
|
+
if (entries.length === 0) return "{}";
|
|
679
|
+
return "\n" + entries.map(([key, value]) => {
|
|
680
|
+
const formattedValue = toYAML(value, indent + 1);
|
|
681
|
+
if (formattedValue.startsWith("\n")) {
|
|
682
|
+
return `${spaces}${key}:${formattedValue}`;
|
|
683
|
+
}
|
|
684
|
+
return `${spaces}${key}: ${formattedValue}`;
|
|
685
|
+
}).join("\n");
|
|
686
|
+
}
|
|
687
|
+
return String(obj);
|
|
688
|
+
}
|
|
689
|
+
function handleError(error) {
|
|
690
|
+
if (error.message) {
|
|
691
|
+
console.error(`Error: ${error.message}`);
|
|
692
|
+
} else {
|
|
693
|
+
console.error("An unexpected error occurred:", error);
|
|
694
|
+
}
|
|
695
|
+
process.exit(1);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// src/cli/commands/properties.ts
|
|
699
|
+
function propertiesCommand(program2) {
|
|
700
|
+
const properties = program2.command("properties").alias("props").description("Manage properties");
|
|
701
|
+
properties.command("list").description("List all properties").option("-p, --page <number>", "Page number", "1").option("-l, --limit <number>", "Items per page", "10").action(async (options, command) => {
|
|
702
|
+
try {
|
|
703
|
+
const client = command.parent.parent.client;
|
|
704
|
+
const format = command.parent.parent.format;
|
|
705
|
+
const result = await client.getProperties({
|
|
706
|
+
page: parseInt(options.page),
|
|
707
|
+
per_page: parseInt(options.limit)
|
|
708
|
+
});
|
|
709
|
+
formatOutput(result, format);
|
|
710
|
+
} catch (error) {
|
|
711
|
+
handleError(error);
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
properties.command("show <id>").description("Show property details by ID or slug").action(async (id, options, command) => {
|
|
715
|
+
try {
|
|
716
|
+
const client = command.parent.parent.client;
|
|
717
|
+
const format = command.parent.parent.format;
|
|
718
|
+
const property = await client.getProperty(id);
|
|
719
|
+
formatOutput(property, format);
|
|
720
|
+
} catch (error) {
|
|
721
|
+
handleError(error);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
properties.command("search").description("Search properties with filters").option("-d, --destination <destination>", "Destination (general search)").option("-c, --city <city>", "City name").option("-a, --area <area>", "Area/neighborhood").option("--arrival <date>", "Arrival date (YYYY-MM-DD)").option("--departure <date>", "Departure date (YYYY-MM-DD)").option("-g, --guests <number>", "Number of guests").option("-b, --bedrooms <number>", "Number of bedrooms").option("--bathrooms <number>", "Number of bathrooms").option("--max-persons <number>", "Maximum persons").option("--property-type <type>", "Property type").option("--elevator", "Has elevator").option("--parking", "Has parking").option("--balcony", "Has balcony").action(async (options, command) => {
|
|
725
|
+
try {
|
|
726
|
+
const client = command.parent.parent.client;
|
|
727
|
+
const format = command.parent.parent.format;
|
|
728
|
+
const searchParams = {};
|
|
729
|
+
if (options.destination) searchParams.destination = options.destination;
|
|
730
|
+
if (options.city) searchParams.city = options.city;
|
|
731
|
+
if (options.area) searchParams.area = options.area;
|
|
732
|
+
if (options.arrival) searchParams.arrival = options.arrival;
|
|
733
|
+
if (options.departure) searchParams.departure = options.departure;
|
|
734
|
+
if (options.guests) searchParams.guests = parseInt(options.guests);
|
|
735
|
+
if (options.bedrooms) searchParams.bedrooms = parseInt(options.bedrooms);
|
|
736
|
+
if (options.bathrooms) searchParams.bathrooms = parseInt(options.bathrooms);
|
|
737
|
+
if (options.maxPersons) searchParams.maxPersons = parseInt(options.maxPersons);
|
|
738
|
+
if (options.propertyType) searchParams.propertyType = options.propertyType;
|
|
739
|
+
if (options.elevator) searchParams.elevator = true;
|
|
740
|
+
if (options.parking) searchParams.parking = true;
|
|
741
|
+
if (options.balcony) searchParams.balcony = true;
|
|
742
|
+
const results = await client.searchProperties(searchParams);
|
|
743
|
+
formatOutput(results, format);
|
|
744
|
+
} catch (error) {
|
|
745
|
+
handleError(error);
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
properties.command("availability <id>").description("Get property availability").requiredOption("-s, --start <date>", "Start date (YYYY-MM-DD)").requiredOption("-e, --end <date>", "End date (YYYY-MM-DD)").action(async (id, options, command) => {
|
|
749
|
+
try {
|
|
750
|
+
const client = command.parent.parent.client;
|
|
751
|
+
const format = command.parent.parent.format;
|
|
752
|
+
const availability = await client.getAvailability(id, options.start, options.end);
|
|
753
|
+
formatOutput(availability, format);
|
|
754
|
+
} catch (error) {
|
|
755
|
+
handleError(error);
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// src/cli/commands/content.ts
|
|
761
|
+
function contentCommand(program2) {
|
|
762
|
+
const content = program2.command("content").description("Manage content (pages, posts, categories)");
|
|
763
|
+
const pages = content.command("pages").description("Manage pages");
|
|
764
|
+
pages.command("list").description("List all pages").action(async (options, command) => {
|
|
765
|
+
try {
|
|
766
|
+
const client = command.parent.parent.parent.client;
|
|
767
|
+
const format = command.parent.parent.parent.format;
|
|
768
|
+
const result = await client.getPages();
|
|
769
|
+
formatOutput(result, format);
|
|
770
|
+
} catch (error) {
|
|
771
|
+
handleError(error);
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
pages.command("show <slug>").description("Show page details by slug").action(async (slug, options, command) => {
|
|
775
|
+
try {
|
|
776
|
+
const client = command.parent.parent.parent.client;
|
|
777
|
+
const format = command.parent.parent.parent.format;
|
|
778
|
+
const page = await client.getPage(slug);
|
|
779
|
+
formatOutput(page, format);
|
|
780
|
+
} catch (error) {
|
|
781
|
+
handleError(error);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
const posts = content.command("posts").description("Manage posts");
|
|
785
|
+
posts.command("list").description("List all posts").option("-p, --page <number>", "Page number", "1").option("-l, --limit <number>", "Items per page", "10").option("-t, --tag <tag>", "Filter by tag").action(async (options, command) => {
|
|
786
|
+
try {
|
|
787
|
+
const client = command.parent.parent.parent.client;
|
|
788
|
+
const format = command.parent.parent.parent.format;
|
|
789
|
+
const params = {
|
|
790
|
+
page: parseInt(options.page),
|
|
791
|
+
per_page: parseInt(options.limit)
|
|
792
|
+
};
|
|
793
|
+
if (options.tag) params.tag = options.tag;
|
|
794
|
+
const result = await client.getPosts(params);
|
|
795
|
+
formatOutput(result, format);
|
|
796
|
+
} catch (error) {
|
|
797
|
+
handleError(error);
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
posts.command("show <slug>").description("Show post details by slug").action(async (slug, options, command) => {
|
|
801
|
+
try {
|
|
802
|
+
const client = command.parent.parent.parent.client;
|
|
803
|
+
const format = command.parent.parent.parent.format;
|
|
804
|
+
const post = await client.getPost(slug);
|
|
805
|
+
formatOutput(post, format);
|
|
806
|
+
} catch (error) {
|
|
807
|
+
handleError(error);
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
const categories = content.command("categories").alias("cats").description("Manage categories");
|
|
811
|
+
categories.command("list").description("List all categories").action(async (options, command) => {
|
|
812
|
+
try {
|
|
813
|
+
const client = command.parent.parent.parent.client;
|
|
814
|
+
const format = command.parent.parent.parent.format;
|
|
815
|
+
const result = await client.getCategories();
|
|
816
|
+
formatOutput(result, format);
|
|
817
|
+
} catch (error) {
|
|
818
|
+
handleError(error);
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
categories.command("show <slug>").description("Show category details by slug").action(async (slug, options, command) => {
|
|
822
|
+
try {
|
|
823
|
+
const client = command.parent.parent.parent.client;
|
|
824
|
+
const format = command.parent.parent.parent.format;
|
|
825
|
+
const category = await client.getCategory(slug);
|
|
826
|
+
formatOutput(category, format);
|
|
827
|
+
} catch (error) {
|
|
828
|
+
handleError(error);
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
categories.command("segments <slug>").description("List segments for a category").action(async (slug, options, command) => {
|
|
832
|
+
try {
|
|
833
|
+
const client = command.parent.parent.parent.client;
|
|
834
|
+
const format = command.parent.parent.parent.format;
|
|
835
|
+
const segments = await client.getCategorySegments(slug);
|
|
836
|
+
formatOutput(segments, format);
|
|
837
|
+
} catch (error) {
|
|
838
|
+
handleError(error);
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
categories.command("segment <category> <segment>").description("Show specific segment details").action(async (category, segment, options, command) => {
|
|
842
|
+
try {
|
|
843
|
+
const client = command.parent.parent.parent.client;
|
|
844
|
+
const format = command.parent.parent.parent.format;
|
|
845
|
+
const result = await client.getCategorySegment(category, segment);
|
|
846
|
+
formatOutput(result, format);
|
|
847
|
+
} catch (error) {
|
|
848
|
+
handleError(error);
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
content.command("locations").description("List all locations").action(async (options, command) => {
|
|
852
|
+
try {
|
|
853
|
+
const client = command.parent.parent.client;
|
|
854
|
+
const format = command.parent.parent.format;
|
|
855
|
+
const locations = await client.getLocations();
|
|
856
|
+
formatOutput(locations, format);
|
|
857
|
+
} catch (error) {
|
|
858
|
+
handleError(error);
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/cli/commands/settings.ts
|
|
864
|
+
function settingsCommand(program2) {
|
|
865
|
+
const settings = program2.command("settings").description("Manage settings");
|
|
866
|
+
settings.command("main").description("Get main site settings").action(async (options, command) => {
|
|
867
|
+
try {
|
|
868
|
+
const client = command.parent.parent.client;
|
|
869
|
+
const format = command.parent.parent.format;
|
|
870
|
+
const result = await client.getMainSettings();
|
|
871
|
+
formatOutput(result, format);
|
|
872
|
+
} catch (error) {
|
|
873
|
+
handleError(error);
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
settings.command("theme").description("Get theme settings").action(async (options, command) => {
|
|
877
|
+
try {
|
|
878
|
+
const client = command.parent.parent.client;
|
|
879
|
+
const format = command.parent.parent.format;
|
|
880
|
+
const result = await client.getThemeSettings();
|
|
881
|
+
formatOutput(result, format);
|
|
882
|
+
} catch (error) {
|
|
883
|
+
handleError(error);
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
settings.command("properties").alias("props").description("Get property settings").action(async (options, command) => {
|
|
887
|
+
try {
|
|
888
|
+
const client = command.parent.parent.client;
|
|
889
|
+
const format = command.parent.parent.format;
|
|
890
|
+
const result = await client.getPropertySettings();
|
|
891
|
+
formatOutput(result, format);
|
|
892
|
+
} catch (error) {
|
|
893
|
+
handleError(error);
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
settings.command("booking").description("Get booking settings").action(async (options, command) => {
|
|
897
|
+
try {
|
|
898
|
+
const client = command.parent.parent.client;
|
|
899
|
+
const format = command.parent.parent.format;
|
|
900
|
+
const result = await client.getBookingSettings();
|
|
901
|
+
formatOutput(result, format);
|
|
902
|
+
} catch (error) {
|
|
903
|
+
handleError(error);
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
settings.command("all").description("Get all settings").action(async (options, command) => {
|
|
907
|
+
try {
|
|
908
|
+
const client = command.parent.parent.client;
|
|
909
|
+
const format = command.parent.parent.format;
|
|
910
|
+
const [main, theme, properties, booking] = await Promise.all([
|
|
911
|
+
client.getMainSettings(),
|
|
912
|
+
client.getThemeSettings(),
|
|
913
|
+
client.getPropertySettings(),
|
|
914
|
+
client.getBookingSettings()
|
|
915
|
+
]);
|
|
916
|
+
const result = {
|
|
917
|
+
main,
|
|
918
|
+
theme,
|
|
919
|
+
properties,
|
|
920
|
+
booking
|
|
921
|
+
};
|
|
922
|
+
formatOutput(result, format);
|
|
923
|
+
} catch (error) {
|
|
924
|
+
handleError(error);
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
function bookingsCommand(program2) {
|
|
929
|
+
const bookings = program2.command("bookings").description("Manage bookings");
|
|
930
|
+
bookings.command("create").description("Create a new booking").requiredOption("-f, --file <path>", "Path to JSON file with booking data").action(async (options, command) => {
|
|
931
|
+
try {
|
|
932
|
+
const client = command.parent.parent.client;
|
|
933
|
+
const format = command.parent.parent.format;
|
|
934
|
+
const filePath = path.resolve(process.cwd(), options.file);
|
|
935
|
+
const bookingData = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
936
|
+
const result = await client.createBooking(bookingData);
|
|
937
|
+
console.log("\u2713 Booking created successfully");
|
|
938
|
+
formatOutput(result, format);
|
|
939
|
+
} catch (error) {
|
|
940
|
+
handleError(error);
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
bookings.command("show <id>").description("Show booking details by ID").action(async (id, options, command) => {
|
|
944
|
+
try {
|
|
945
|
+
const client = command.parent.parent.client;
|
|
946
|
+
const format = command.parent.parent.format;
|
|
947
|
+
const booking = await client.getBooking(id);
|
|
948
|
+
formatOutput(booking, format);
|
|
949
|
+
} catch (error) {
|
|
950
|
+
handleError(error);
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
bookings.command("example").description("Print example booking JSON structure").action(() => {
|
|
954
|
+
const example = {
|
|
955
|
+
property_id: 123,
|
|
956
|
+
customer: {
|
|
957
|
+
first_name: "John",
|
|
958
|
+
last_name: "Doe",
|
|
959
|
+
email: "john.doe@example.com",
|
|
960
|
+
phone: "+31612345678",
|
|
961
|
+
address: "123 Main St",
|
|
962
|
+
city: "Amsterdam",
|
|
963
|
+
country: "Netherlands",
|
|
964
|
+
postal_code: "1012AB"
|
|
965
|
+
},
|
|
966
|
+
arrival_date: "2024-06-01",
|
|
967
|
+
departure_date: "2024-06-07",
|
|
968
|
+
guests: 2,
|
|
969
|
+
total_price: 850,
|
|
970
|
+
notes: "Late check-in requested"
|
|
971
|
+
};
|
|
972
|
+
console.log("Example booking structure (save to file and use with --file):");
|
|
973
|
+
console.log(JSON.stringify(example, null, 2));
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/cli/index.ts
|
|
978
|
+
dotenv.config({ path: path.resolve(process.cwd(), ".env") });
|
|
979
|
+
var program = new commander.Command();
|
|
980
|
+
program.name("more-apartments").description("CLI to interact with More Apartments REST API").version("1.0.1").option("-u, --base-url <url>", "API base URL", process.env.MORE_APARTMENTS_BASE_URL).option("-k, --api-key <key>", "API key", process.env.MORE_APARTMENTS_API_KEY).option("-i, --instance <instance>", "Instance name", process.env.MORE_APARTMENTS_INSTANCE).option("-t, --timeout <ms>", "Request timeout in ms", "30000").option("-f, --format <format>", "Output format (json, table, yaml)", "json").hook("preAction", (thisCommand) => {
|
|
981
|
+
const opts = thisCommand.opts();
|
|
982
|
+
if (!opts.baseUrl) {
|
|
983
|
+
console.error("Error: --base-url is required (or set MORE_APARTMENTS_BASE_URL env var)");
|
|
984
|
+
process.exit(1);
|
|
985
|
+
}
|
|
986
|
+
if (!opts.apiKey) {
|
|
987
|
+
console.error("Error: --api-key is required (or set MORE_APARTMENTS_API_KEY env var)");
|
|
988
|
+
process.exit(1);
|
|
989
|
+
}
|
|
990
|
+
if (!opts.instance) {
|
|
991
|
+
console.error("Error: --instance is required (or set MORE_APARTMENTS_INSTANCE env var)");
|
|
992
|
+
process.exit(1);
|
|
993
|
+
}
|
|
994
|
+
const clientConfig = {
|
|
995
|
+
baseUrl: opts.baseUrl,
|
|
996
|
+
apiKey: opts.apiKey,
|
|
997
|
+
instance: opts.instance,
|
|
998
|
+
timeout: parseInt(opts.timeout),
|
|
999
|
+
cache: { enabled: false, ttl: 0 }
|
|
1000
|
+
};
|
|
1001
|
+
thisCommand.client = new MoreApartmentsClient(clientConfig);
|
|
1002
|
+
thisCommand.format = opts.format;
|
|
1003
|
+
});
|
|
1004
|
+
propertiesCommand(program);
|
|
1005
|
+
contentCommand(program);
|
|
1006
|
+
settingsCommand(program);
|
|
1007
|
+
bookingsCommand(program);
|
|
1008
|
+
program.parse();
|
|
1009
|
+
//# sourceMappingURL=index.js.map
|
|
1010
|
+
//# sourceMappingURL=index.js.map
|