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