@v-office/website-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +263 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +337 -0
- package/dist/client-BbAfk-qa.mjs +33672 -0
- package/dist/custom-attribute-ChCbJKf_.mjs +54 -0
- package/dist/errors-2cuUGSvi.mjs +5 -0
- package/dist/index.d.mts +16130 -0
- package/dist/index.mjs +3 -0
- package/dist/operations-BanW36PK.mjs +12616 -0
- package/dist/operations-CHxEQ3jG.mjs +904 -0
- package/dist/parser-D6UAf8Ld.mjs +65 -0
- package/dist/quote-C3HZsFua.mjs +313 -0
- package/dist/quote-Vl6Nutaa.mjs +513 -0
- package/dist/rentals-BFmmp26v.mjs +323 -0
- package/dist/rentals-cQAg5TTW.mjs +403 -0
- package/dist/search-JqA3v_Fx.mjs +342 -0
- package/dist/search-filter-metadata-DZP0-Udc.mjs +4294 -0
- package/dist/to-rental-highlights-BcRa9Odv.mjs +402 -0
- package/dist/translations/shared/de-DE/availability.json +15 -0
- package/dist/translations/shared/de-DE/booking.json +15 -0
- package/dist/translations/shared/de-DE/insurance.json +18 -0
- package/dist/translations/shared/de-DE/quote.json +8 -0
- package/dist/translations/shared/de-DE/reviews.json +11 -0
- package/dist/translations/shared/en-US/availability.json +15 -0
- package/dist/translations/shared/en-US/booking.json +15 -0
- package/dist/translations/shared/en-US/insurance.json +18 -0
- package/dist/translations/shared/en-US/quote.json +8 -0
- package/dist/translations/shared/en-US/reviews.json +11 -0
- package/dist/translations/v10/de-DE/core.json +7027 -0
- package/dist/translations/v10/en-US/core.json +7027 -0
- package/dist/translations/v9/de-DE/core.json +4 -0
- package/dist/translations/v9/de-DE/filter.json +25 -0
- package/dist/translations/v9/de-DE/rental-attribute-categories.json +19 -0
- package/dist/translations/v9/de-DE/rental-attributes.json +451 -0
- package/dist/translations/v9/en-US/core.json +4 -0
- package/dist/translations/v9/en-US/filter.json +25 -0
- package/dist/translations/v9/en-US/rental-attribute-categories.json +19 -0
- package/dist/translations/v9/en-US/rental-attributes.json +451 -0
- package/package.json +90 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { A as toUnusedFilterKeys, C as parseChildrenAges, D as parseQueryParameters, E as collectQueryParameters, L as parseVofficeUnitData, O as expandCustomAttributeFilterCompositions, T as toQueryString, an as toStableSearchInputParameterValues, in as toStableSearchInputBackendQueryKeys, j as stable_filters_default, k as toCustomAttributeFilterLabel, nn as STABLE_SEARCH_INPUTS, on as toStableSearchInputQueryKeys, w as parseOccupancyCount } from "./client-BbAfk-qa.mjs";
|
|
2
|
+
import { t as CMSError } from "./errors-2cuUGSvi.mjs";
|
|
3
|
+
import { d as daysBetweenLocalDates, l as toIsoDateFromPeriodQueryDate } from "./parser-D6UAf8Ld.mjs";
|
|
4
|
+
import { n as toAddress, t as toRentalHighlights } from "./to-rental-highlights-BcRa9Odv.mjs";
|
|
5
|
+
import { Effect } from "effect";
|
|
6
|
+
//#region src/adapters/v9/parser/search/input/filter/apply-voffice-filter-derived-basic-query-inputs.ts
|
|
7
|
+
const hasBasicQueryInput = ({ basicQueryInputs, key }) => basicQueryInputs.some((input) => input.key === key);
|
|
8
|
+
const derivedBooleanFilters = [{
|
|
9
|
+
key: "pets",
|
|
10
|
+
isSelected: (filter) => (filter.petsCount ?? 0) > 0
|
|
11
|
+
}];
|
|
12
|
+
const applyVofficeFilterDerivedBasicQueryInputs = ({ appliedFilters, basicQueryInputs, filter, locale, translations }) => Effect.gen(function* () {
|
|
13
|
+
const nextAppliedFilters = [...appliedFilters];
|
|
14
|
+
const nextBasicQueryInputs = [...basicQueryInputs];
|
|
15
|
+
for (const derivedFilter of derivedBooleanFilters) {
|
|
16
|
+
if (!derivedFilter.isSelected(filter) || hasBasicQueryInput({
|
|
17
|
+
basicQueryInputs: nextBasicQueryInputs,
|
|
18
|
+
key: derivedFilter.key
|
|
19
|
+
})) continue;
|
|
20
|
+
nextBasicQueryInputs.push({
|
|
21
|
+
key: derivedFilter.key,
|
|
22
|
+
value: true
|
|
23
|
+
});
|
|
24
|
+
nextAppliedFilters.push({
|
|
25
|
+
key: derivedFilter.key,
|
|
26
|
+
label: yield* translations.translate(locale, `filter.${derivedFilter.key}.label`, derivedFilter.key)
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
appliedFilters: nextAppliedFilters,
|
|
31
|
+
basicQueryInputs: nextBasicQueryInputs
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/adapters/v9/parser/search/input/filter/filter-query-keys.ts
|
|
36
|
+
const FILTER_QUERY_KEYS = new Set(Object.keys(stable_filters_default));
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/adapters/v9/parser/search/input/filter/to-basic-query-inputs.ts
|
|
39
|
+
const isEnabledBooleanFilter = (value) => {
|
|
40
|
+
const normalizedValue = value.toLowerCase();
|
|
41
|
+
return normalizedValue === "" || normalizedValue === "true" || normalizedValue === "1";
|
|
42
|
+
};
|
|
43
|
+
const toBasicQueryInput = ({ queryKey, value, filter }) => {
|
|
44
|
+
if (filter.type === "BooleanFilter") return isEnabledBooleanFilter(value) ? {
|
|
45
|
+
key: queryKey,
|
|
46
|
+
value: true
|
|
47
|
+
} : void 0;
|
|
48
|
+
if (filter.type === "InputFilter") {
|
|
49
|
+
const numberValue = Number(value);
|
|
50
|
+
if (!Number.isInteger(numberValue) || numberValue < 0) return;
|
|
51
|
+
return {
|
|
52
|
+
key: queryKey,
|
|
53
|
+
value: numberValue
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const toCustomBackendFilterInput = ({ queryKey, value, filter }) => {
|
|
58
|
+
switch (filter.type) {
|
|
59
|
+
case "boolean": return isEnabledBooleanFilter(value) ? {
|
|
60
|
+
key: queryKey,
|
|
61
|
+
value: true
|
|
62
|
+
} : void 0;
|
|
63
|
+
case "int": {
|
|
64
|
+
const numberValue = Number(value);
|
|
65
|
+
return Number.isInteger(numberValue) && numberValue >= 0 ? {
|
|
66
|
+
key: queryKey,
|
|
67
|
+
value: numberValue
|
|
68
|
+
} : void 0;
|
|
69
|
+
}
|
|
70
|
+
case "option": return filter.options.some((option) => option.value === value) ? {
|
|
71
|
+
key: queryKey,
|
|
72
|
+
value
|
|
73
|
+
} : void 0;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const toBasicQueryInputs = ({ query, customAttributeFilterDefinitions, locale, translations }) => {
|
|
77
|
+
const appliedFilterEffects = [];
|
|
78
|
+
const basicQueryInputs = [];
|
|
79
|
+
const remainingParameters = [];
|
|
80
|
+
const seenScalarFilters = /* @__PURE__ */ new Set();
|
|
81
|
+
const customBackendFiltersByKey = new Map(customAttributeFilterDefinitions.filter((definition) => definition.source === "backendFilter" && definition.searchable).map((definition) => [definition.key, definition]));
|
|
82
|
+
for (const [queryKey, value] of parseQueryParameters(query)) {
|
|
83
|
+
const filter = stable_filters_default[queryKey];
|
|
84
|
+
const customBackendFilter = customBackendFiltersByKey.get(queryKey);
|
|
85
|
+
if ((!FILTER_QUERY_KEYS.has(queryKey) || filter == null) && customBackendFilter == null) {
|
|
86
|
+
remainingParameters.push([queryKey, value]);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (seenScalarFilters.has(queryKey)) {
|
|
90
|
+
remainingParameters.push([queryKey, value]);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const basicQueryInput = filter == null ? customBackendFilter != null ? toCustomBackendFilterInput({
|
|
94
|
+
queryKey,
|
|
95
|
+
value,
|
|
96
|
+
filter: customBackendFilter
|
|
97
|
+
}) : void 0 : toBasicQueryInput({
|
|
98
|
+
queryKey,
|
|
99
|
+
value,
|
|
100
|
+
filter
|
|
101
|
+
});
|
|
102
|
+
if (basicQueryInput == null) {
|
|
103
|
+
remainingParameters.push([queryKey, value]);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
seenScalarFilters.add(queryKey);
|
|
107
|
+
basicQueryInputs.push(basicQueryInput);
|
|
108
|
+
if (customBackendFilter != null) appliedFilterEffects.push(Effect.succeed({
|
|
109
|
+
key: queryKey,
|
|
110
|
+
label: toCustomAttributeFilterLabel({
|
|
111
|
+
definition: customBackendFilter,
|
|
112
|
+
locale,
|
|
113
|
+
value
|
|
114
|
+
})
|
|
115
|
+
}));
|
|
116
|
+
else appliedFilterEffects.push(translations.translate(locale, `filter.${queryKey}.label`, queryKey).pipe(Effect.map((label) => ({
|
|
117
|
+
key: queryKey,
|
|
118
|
+
label
|
|
119
|
+
}))));
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
appliedFilters: Effect.all(appliedFilterEffects),
|
|
123
|
+
basicQueryInputs,
|
|
124
|
+
remainingQuery: toQueryString(remainingParameters)
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/adapters/v9/parser/search/input/occupancy/occupancy-query-keys.ts
|
|
129
|
+
const OCCUPANCY_QUERY_KEYS = toStableSearchInputQueryKeys(STABLE_SEARCH_INPUTS.occupancy);
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/adapters/v9/parser/search/input/occupancy/collect-occupancy-query-parameters.ts
|
|
132
|
+
const hasOccupancyInput = (query) => parseQueryParameters(query).some(([key]) => OCCUPANCY_QUERY_KEYS.has(key));
|
|
133
|
+
const collectOccupancyQueryParameters = ({ query }) => {
|
|
134
|
+
const { matchingParameters, remainingParameters } = collectQueryParameters({
|
|
135
|
+
query,
|
|
136
|
+
queryKeys: OCCUPANCY_QUERY_KEYS
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
occupancyParameters: matchingParameters,
|
|
140
|
+
remainingParameters
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/adapters/v9/parser/search/input/occupancy/to-occupancy-input.ts
|
|
145
|
+
const parseStableOccupancyCount = ({ key, occupancyParameters }) => Effect.gen(function* () {
|
|
146
|
+
const values = toStableSearchInputParameterValues({
|
|
147
|
+
key,
|
|
148
|
+
group: STABLE_SEARCH_INPUTS.occupancy,
|
|
149
|
+
parameters: occupancyParameters
|
|
150
|
+
});
|
|
151
|
+
if (values.length === 0) return;
|
|
152
|
+
return yield* parseOccupancyCount({
|
|
153
|
+
key,
|
|
154
|
+
values
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
const toOccupancyInput = ({ query }) => Effect.gen(function* () {
|
|
158
|
+
const { occupancyParameters, remainingParameters } = collectOccupancyQueryParameters({ query });
|
|
159
|
+
const childrenAges = yield* parseChildrenAges({ values: occupancyParameters.get("childrenAges") ?? [] });
|
|
160
|
+
const children = yield* parseOccupancyCount({
|
|
161
|
+
key: "children",
|
|
162
|
+
values: occupancyParameters.get("children") ?? []
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
occupancyFilter: {
|
|
166
|
+
adults: (yield* parseOccupancyCount({
|
|
167
|
+
key: "adults",
|
|
168
|
+
values: occupancyParameters.get("adults") ?? []
|
|
169
|
+
})) ?? 0,
|
|
170
|
+
children: children ?? childrenAges?.length ?? 0,
|
|
171
|
+
babys: (yield* parseOccupancyCount({
|
|
172
|
+
key: "babies",
|
|
173
|
+
values: occupancyParameters.get("babies") ?? []
|
|
174
|
+
})) ?? 0,
|
|
175
|
+
petsCount: (yield* parseStableOccupancyCount({
|
|
176
|
+
key: "petsCount",
|
|
177
|
+
occupancyParameters
|
|
178
|
+
})) ?? 0
|
|
179
|
+
},
|
|
180
|
+
remainingQuery: toQueryString(remainingParameters)
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/adapters/v9/parser/search/input/search-input-error.ts
|
|
185
|
+
const failInvalidV9SearchInput = (message) => Effect.fail(new CMSError({
|
|
186
|
+
backend: "v9",
|
|
187
|
+
operation: "search",
|
|
188
|
+
message
|
|
189
|
+
}));
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region src/adapters/v9/parser/search/input/period/period-query-keys.ts
|
|
192
|
+
const PERIOD_QUERY_KEYS = toStableSearchInputBackendQueryKeys({
|
|
193
|
+
backend: "v9",
|
|
194
|
+
group: STABLE_SEARCH_INPUTS.period
|
|
195
|
+
});
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/adapters/v9/parser/search/input/period/collect-period-query-parameters.ts
|
|
198
|
+
const hasPeriodInput = (query) => parseQueryParameters(query).some(([key]) => PERIOD_QUERY_KEYS.has(key));
|
|
199
|
+
const collectPeriodQueryParameters = ({ query }) => {
|
|
200
|
+
const { matchingParameters, remainingParameters } = collectQueryParameters({
|
|
201
|
+
query,
|
|
202
|
+
queryKeys: PERIOD_QUERY_KEYS
|
|
203
|
+
});
|
|
204
|
+
return {
|
|
205
|
+
periodParameters: matchingParameters,
|
|
206
|
+
remainingParameters
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/adapters/v9/parser/search/input/period/to-period-input.ts
|
|
211
|
+
const parseScalarParameter = ({ key, values }) => {
|
|
212
|
+
if (values.length > 1) return failInvalidV9SearchInput(`Expected at most one "${key}" query parameter.`);
|
|
213
|
+
return Effect.succeed(values[0]);
|
|
214
|
+
};
|
|
215
|
+
const parsePositiveInt = ({ key, values }) => Effect.gen(function* () {
|
|
216
|
+
const value = yield* parseScalarParameter({
|
|
217
|
+
key,
|
|
218
|
+
values
|
|
219
|
+
});
|
|
220
|
+
if (value === void 0) return;
|
|
221
|
+
const numberValue = Number(value);
|
|
222
|
+
if (!Number.isInteger(numberValue) || numberValue <= 0) return yield* failInvalidV9SearchInput(`Expected "${key}" to be a positive integer.`);
|
|
223
|
+
return numberValue;
|
|
224
|
+
});
|
|
225
|
+
const toPeriodInput = ({ query }) => Effect.gen(function* () {
|
|
226
|
+
const { periodParameters, remainingParameters } = collectPeriodQueryParameters({ query });
|
|
227
|
+
const from = yield* parseScalarParameter({
|
|
228
|
+
key: "start",
|
|
229
|
+
values: toStableSearchInputParameterValues({
|
|
230
|
+
key: "start",
|
|
231
|
+
group: STABLE_SEARCH_INPUTS.period,
|
|
232
|
+
parameters: periodParameters
|
|
233
|
+
})
|
|
234
|
+
});
|
|
235
|
+
const till = yield* parseScalarParameter({
|
|
236
|
+
key: "end",
|
|
237
|
+
values: toStableSearchInputParameterValues({
|
|
238
|
+
key: "end",
|
|
239
|
+
group: STABLE_SEARCH_INPUTS.period,
|
|
240
|
+
parameters: periodParameters
|
|
241
|
+
})
|
|
242
|
+
});
|
|
243
|
+
const nightsMin = yield* parsePositiveInt({
|
|
244
|
+
key: "minNights",
|
|
245
|
+
values: toStableSearchInputParameterValues({
|
|
246
|
+
key: "minNights",
|
|
247
|
+
group: STABLE_SEARCH_INPUTS.period,
|
|
248
|
+
parameters: periodParameters
|
|
249
|
+
})
|
|
250
|
+
});
|
|
251
|
+
const nightsMax = yield* parsePositiveInt({
|
|
252
|
+
key: "maxNights",
|
|
253
|
+
values: toStableSearchInputParameterValues({
|
|
254
|
+
key: "maxNights",
|
|
255
|
+
group: STABLE_SEARCH_INPUTS.period,
|
|
256
|
+
parameters: periodParameters
|
|
257
|
+
})
|
|
258
|
+
});
|
|
259
|
+
if (from === void 0 || till === void 0) return yield* failInvalidV9SearchInput("Expected both \"from\" and \"till\" query parameters.");
|
|
260
|
+
const isoFrom = toIsoDateFromPeriodQueryDate(from);
|
|
261
|
+
const isoTill = toIsoDateFromPeriodQueryDate(till);
|
|
262
|
+
if (isoFrom === void 0 || isoTill === void 0) return yield* failInvalidV9SearchInput("Expected \"start\" and \"end\" to use DD-MM-YYYY or YYYY-MM-DD dates.");
|
|
263
|
+
const periodNights = daysBetweenLocalDates({
|
|
264
|
+
start: isoFrom,
|
|
265
|
+
end: isoTill
|
|
266
|
+
});
|
|
267
|
+
if (periodNights <= 0) return yield* failInvalidV9SearchInput("Expected \"end\" to be after \"start\".");
|
|
268
|
+
if (nightsMin === void 0 && nightsMax !== void 0 || nightsMin !== void 0 && nightsMax === void 0) return yield* failInvalidV9SearchInput("Expected both \"nights_min\" and \"nights_max\" query parameters, or neither.");
|
|
269
|
+
const nextNightsMin = nightsMin ?? periodNights;
|
|
270
|
+
const nextNightsMax = nightsMax ?? periodNights;
|
|
271
|
+
if (nextNightsMin > nextNightsMax) return yield* failInvalidV9SearchInput("Expected \"nights_min\" to be less than or equal to \"nights_max\".");
|
|
272
|
+
return {
|
|
273
|
+
periodFilter: {
|
|
274
|
+
from: isoFrom,
|
|
275
|
+
till: isoTill,
|
|
276
|
+
nights_min: nextNightsMin,
|
|
277
|
+
nights_max: nextNightsMax
|
|
278
|
+
},
|
|
279
|
+
remainingQuery: toQueryString(remainingParameters)
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/adapters/v9/parser/search/input/to-query-input.ts
|
|
284
|
+
const toQueryInput = ({ query, customAttributeFilterDefinitions, locale, translations }) => Effect.gen(function* () {
|
|
285
|
+
const compositionResult = expandCustomAttributeFilterCompositions({
|
|
286
|
+
customAttributeFilterDefinitions,
|
|
287
|
+
locale,
|
|
288
|
+
query
|
|
289
|
+
});
|
|
290
|
+
const expandedQuery = compositionResult.query;
|
|
291
|
+
const periodResult = hasPeriodInput(expandedQuery) ? yield* toPeriodInput({ query: expandedQuery }) : void 0;
|
|
292
|
+
const queryWithoutPeriod = periodResult?.remainingQuery ?? expandedQuery;
|
|
293
|
+
const occupancyResult = hasOccupancyInput(queryWithoutPeriod) ? yield* toOccupancyInput({ query: queryWithoutPeriod }) : void 0;
|
|
294
|
+
const basicQueryResult = toBasicQueryInputs({
|
|
295
|
+
query: occupancyResult?.remainingQuery ?? queryWithoutPeriod,
|
|
296
|
+
customAttributeFilterDefinitions,
|
|
297
|
+
locale,
|
|
298
|
+
translations
|
|
299
|
+
});
|
|
300
|
+
const filter = {
|
|
301
|
+
...periodResult?.periodFilter,
|
|
302
|
+
...occupancyResult?.occupancyFilter
|
|
303
|
+
};
|
|
304
|
+
const { appliedFilters, basicQueryInputs } = yield* applyVofficeFilterDerivedBasicQueryInputs({
|
|
305
|
+
appliedFilters: yield* basicQueryResult.appliedFilters,
|
|
306
|
+
basicQueryInputs: basicQueryResult.basicQueryInputs,
|
|
307
|
+
filter,
|
|
308
|
+
locale,
|
|
309
|
+
translations
|
|
310
|
+
});
|
|
311
|
+
return {
|
|
312
|
+
appliedFilters: [...compositionResult.appliedFilters, ...appliedFilters],
|
|
313
|
+
queryInput: {
|
|
314
|
+
vofficeData: Object.keys(filter).length > 0 ? { filter } : void 0,
|
|
315
|
+
basicQueryInputs
|
|
316
|
+
},
|
|
317
|
+
unusedFilterKeys: toUnusedFilterKeys(basicQueryResult.remainingQuery)
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region src/adapters/v9/parser/search/to-search-output-item.ts
|
|
322
|
+
const toSearchOutputItem = ({ locale, rentalHighlightPrioritization, customAttributeFilterDefinitions, rental, translations }) => Effect.gen(function* () {
|
|
323
|
+
const data = parseVofficeUnitData(rental.data);
|
|
324
|
+
const item = {
|
|
325
|
+
id: rental.voffice_id.toString(),
|
|
326
|
+
nameOrLabel: typeof data.known.name === "string" ? data.known.name : rental.voffice_id.toString(),
|
|
327
|
+
timeZone: "Europe/Berlin"
|
|
328
|
+
};
|
|
329
|
+
const address = toAddress(data, locale);
|
|
330
|
+
if (Object.keys(address).length > 0) item.address = address;
|
|
331
|
+
const highlights = yield* toRentalHighlights({
|
|
332
|
+
locale,
|
|
333
|
+
translations,
|
|
334
|
+
highlightPrioritization: rentalHighlightPrioritization,
|
|
335
|
+
customAttributeFilterDefinitions,
|
|
336
|
+
attributes: data
|
|
337
|
+
});
|
|
338
|
+
if (highlights != null) item.highlights = highlights;
|
|
339
|
+
return item;
|
|
340
|
+
});
|
|
341
|
+
//#endregion
|
|
342
|
+
export { toQueryInput, toSearchOutputItem };
|