@v-office/website-sdk 2.7.0 → 2.8.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 +28 -1
- package/dist/cli.mjs +25 -4
- package/dist/{client-45_ofP_d.mjs → client-BNbBfJtO.mjs} +385 -187
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +3 -3
- package/dist/instructions/CHANGELOG.md +3 -1
- package/dist/instructions/MIGRATION.md +3 -1
- package/dist/instructions/README.md +8 -3
- package/dist/instructions/creation.md +65 -64
- package/dist/instructions/custom-attributes.md +556 -0
- package/dist/instructions/filter.md +51 -23
- package/dist/instructions/rentals.md +26 -2
- package/dist/instructions/search.md +29 -3
- package/dist/instructions/versions/2.5.0/MIGRATION.md +5 -0
- package/dist/instructions/versions/2.6.0/CHANGELOG.md +3 -25
- package/dist/instructions/versions/2.6.0/MIGRATION.md +4 -72
- package/dist/instructions/versions/2.7.0/CHANGELOG.md +44 -0
- package/dist/instructions/versions/2.7.0/MIGRATION.md +79 -0
- package/dist/instructions/versions/2.8.0/CHANGELOG.md +63 -0
- package/dist/instructions/versions/2.8.0/MIGRATION.md +252 -0
- package/dist/{rentals-Lw1qUKIj.mjs → rentals-cCejb_2d.mjs} +21 -21
- package/dist/{search-wcoZw2rt.mjs → search-Dzzra6IW.mjs} +16 -133
- package/dist/{to-rental-highlights-CxWlq76f.mjs → to-rental-highlights-OvNe9ZQS.mjs} +8 -6
- package/dist/translations/v10/de-DE/core.json +2 -0
- package/dist/translations/v10/en-US/core.json +2 -0
- package/instructions/CHANGELOG.md +3 -1
- package/instructions/MIGRATION.md +3 -1
- package/instructions/README.md +8 -3
- package/instructions/creation.md +65 -64
- package/instructions/custom-attributes.md +556 -0
- package/instructions/filter.md +51 -23
- package/instructions/rentals.md +26 -2
- package/instructions/search.md +29 -3
- package/instructions/versions/2.5.0/MIGRATION.md +5 -0
- package/instructions/versions/2.6.0/CHANGELOG.md +3 -25
- package/instructions/versions/2.6.0/MIGRATION.md +4 -72
- package/instructions/versions/2.7.0/CHANGELOG.md +44 -0
- package/instructions/versions/2.7.0/MIGRATION.md +79 -0
- package/instructions/versions/2.8.0/CHANGELOG.md +63 -0
- package/instructions/versions/2.8.0/MIGRATION.md +252 -0
- package/package.json +5 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as VofficeUnitDataFieldSchemas, d as VofficeUnitDataPropertyMetadata, f as parseVofficeFacilityData, i as toLocalizedString, l as VofficeUnitDataPropertyCategoryLabelKeys, m as parseVofficeUnitData, n as toImages, o as rentalsAllFeedbacksQuery, p as parseVofficeFeedbackData, r as toAddress, s as rentalsAllWithoutFeedbacksQuery, t as toRentalHighlights, u as VofficeUnitDataPropertyCategoryValues } from "./to-rental-highlights-
|
|
2
|
-
import { makeTranslate,
|
|
1
|
+
import { c as VofficeUnitDataFieldSchemas, d as VofficeUnitDataPropertyMetadata, f as parseVofficeFacilityData, i as toLocalizedString, l as VofficeUnitDataPropertyCategoryLabelKeys, m as parseVofficeUnitData, n as toImages, o as rentalsAllFeedbacksQuery, p as parseVofficeFeedbackData, r as toAddress, s as rentalsAllWithoutFeedbacksQuery, t as toRentalHighlights, u as VofficeUnitDataPropertyCategoryValues } from "./to-rental-highlights-OvNe9ZQS.mjs";
|
|
2
|
+
import { makeTranslate, renderLabeledAttributeValue, renderResolvedCustomAttribute, toCustomAttributeList, toResolvedCustomAttributeCategoryTranslationKey } from "@v-office/sdk-core";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
//#region src/legacy-v9/parser/rentals/to-description.ts
|
|
5
5
|
const toDescription = (data, locale) => {
|
|
@@ -60,29 +60,30 @@ const PROPERTY_METADATA_ENTRIES = Object.entries(VofficeUnitDataPropertyMetadata
|
|
|
60
60
|
return (CATEGORY_ORDER.get(left.metadata.category.key) ?? Number.MAX_SAFE_INTEGER) - (CATEGORY_ORDER.get(right.metadata.category.key) ?? Number.MAX_SAFE_INTEGER) || left.index - right.index;
|
|
61
61
|
});
|
|
62
62
|
const canRenderLabeledAttributeValue$1 = (value) => value !== false && value !== 0 && value !== "false" && value !== "0" && value != null && value !== "";
|
|
63
|
-
const toRentalAttributes = ({ locale, translations, attributes,
|
|
63
|
+
const toRentalAttributes = ({ locale, translations, attributes, customAttributes }) => Effect.gen(function* () {
|
|
64
64
|
const result = [];
|
|
65
65
|
const categoriesByKey = /* @__PURE__ */ new Map();
|
|
66
66
|
const subCategoriesByKey = /* @__PURE__ */ new Map();
|
|
67
67
|
const knownAttributes = attributes.known;
|
|
68
68
|
const translate = makeTranslate(translations, locale);
|
|
69
|
-
const
|
|
70
|
-
|
|
69
|
+
const getCustomAttributeSubCategory = (categoryKey) => Effect.gen(function* () {
|
|
70
|
+
const labelKey = toResolvedCustomAttributeCategoryTranslationKey(categoryKey);
|
|
71
|
+
let category = categoriesByKey.get(categoryKey);
|
|
71
72
|
if (category == null) {
|
|
72
73
|
category = {
|
|
73
|
-
label: yield* translate(
|
|
74
|
+
label: yield* translate(labelKey, categoryKey),
|
|
74
75
|
subCategories: []
|
|
75
76
|
};
|
|
76
|
-
categoriesByKey.set(
|
|
77
|
+
categoriesByKey.set(categoryKey, category);
|
|
77
78
|
result.push(category);
|
|
78
79
|
}
|
|
79
|
-
let subCategory = subCategoriesByKey.get(
|
|
80
|
+
let subCategory = subCategoriesByKey.get(categoryKey);
|
|
80
81
|
if (subCategory == null) {
|
|
81
82
|
subCategory = {
|
|
82
83
|
label: category.label,
|
|
83
84
|
items: []
|
|
84
85
|
};
|
|
85
|
-
subCategoriesByKey.set(
|
|
86
|
+
subCategoriesByKey.set(categoryKey, subCategory);
|
|
86
87
|
category.subCategories.push(subCategory);
|
|
87
88
|
}
|
|
88
89
|
return subCategory;
|
|
@@ -118,18 +119,17 @@ const toRentalAttributes = ({ locale, translations, attributes, customAttributeF
|
|
|
118
119
|
}
|
|
119
120
|
subCategory.items.push(attribute);
|
|
120
121
|
}
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
key: definition.key,
|
|
122
|
+
for (const attribute of toCustomAttributeList(customAttributes)) {
|
|
123
|
+
const binding = attribute.v9;
|
|
124
|
+
if (binding === void 0) continue;
|
|
125
|
+
const rendered = renderResolvedCustomAttribute({
|
|
126
|
+
attribute,
|
|
127
127
|
locale,
|
|
128
|
-
value
|
|
128
|
+
value: knownAttributes[binding] ?? attributes.unknown[binding]
|
|
129
129
|
});
|
|
130
|
-
if (
|
|
130
|
+
if (rendered == null) continue;
|
|
131
|
+
(yield* getCustomAttributeSubCategory(attribute.category)).items.push(rendered);
|
|
131
132
|
}
|
|
132
|
-
if (customAttributeItems.length > 0) (yield* getGeneralSubCategory()).items.push(...customAttributeItems);
|
|
133
133
|
return result;
|
|
134
134
|
});
|
|
135
135
|
//#endregion
|
|
@@ -228,7 +228,7 @@ const toReviews = ({ locale, translations, rental }) => Effect.gen(function* ()
|
|
|
228
228
|
});
|
|
229
229
|
//#endregion
|
|
230
230
|
//#region src/legacy-v9/parser/rentals/to-rental-list-item.ts
|
|
231
|
-
const toRentalRentalsOutput = ({ rental, locale, translations, imageProxyBaseUrl, rentalHighlightPrioritization,
|
|
231
|
+
const toRentalRentalsOutput = ({ rental, locale, translations, imageProxyBaseUrl, rentalHighlightPrioritization, customAttributes }) => Effect.gen(function* () {
|
|
232
232
|
const data = parseVofficeUnitData(rental.data);
|
|
233
233
|
const rawRentalType = data.known.type?.trim();
|
|
234
234
|
const translatedRentalType = rawRentalType != null && rawRentalType.length > 0 ? yield* toRentalType({
|
|
@@ -244,7 +244,7 @@ const toRentalRentalsOutput = ({ rental, locale, translations, imageProxyBaseUrl
|
|
|
244
244
|
locale,
|
|
245
245
|
translations,
|
|
246
246
|
attributes: data,
|
|
247
|
-
|
|
247
|
+
customAttributes
|
|
248
248
|
});
|
|
249
249
|
const vicinity = yield* toRentalVicinity({
|
|
250
250
|
locale,
|
|
@@ -255,7 +255,7 @@ const toRentalRentalsOutput = ({ rental, locale, translations, imageProxyBaseUrl
|
|
|
255
255
|
locale,
|
|
256
256
|
translations,
|
|
257
257
|
highlightPrioritization: rentalHighlightPrioritization,
|
|
258
|
-
|
|
258
|
+
customAttributes,
|
|
259
259
|
attributes: data
|
|
260
260
|
});
|
|
261
261
|
const reviews = yield* toReviews({
|
|
@@ -1,133 +1,7 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import { a as searchQuery, c as VofficeUnitDataFieldSchemas, m as parseVofficeUnitData, n as toImages, r as toAddress, t as toRentalHighlights } from "./to-rental-highlights-
|
|
3
|
-
import { CoreSDKError, STABLE_SEARCH_INPUTS,
|
|
1
|
+
import { a as parseQueryParameters, i as collectQueryParameters, n as makeV9CustomAttributeFilterCapabilities, o as toQueryString, r as toBasicQueryInputs, s as applyVofficeFilterDerivedBasicQueryInputs } from "./client-BNbBfJtO.mjs";
|
|
2
|
+
import { a as searchQuery, c as VofficeUnitDataFieldSchemas, m as parseVofficeUnitData, n as toImages, r as toAddress, t as toRentalHighlights } from "./to-rental-highlights-OvNe9ZQS.mjs";
|
|
3
|
+
import { CoreSDKError, STABLE_SEARCH_INPUTS, daysBetweenLocalDates, expandCustomAttributeFilterCompositions, parseChildrenAges, parseOccupancyCount, resolveExpandedCompositions, toFormattedSearchPrice, toIsoDateFromPeriodQueryDate, toStableSearchInputBackendQueryKeys, toStableSearchInputParameterValues, toStableSearchInputQueryKeys, toUnusedFilterKeys } from "@v-office/sdk-core";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
|
-
//#region src/legacy-v9/parser/search/input/filter/apply-voffice-filter-derived-basic-query-inputs.ts
|
|
6
|
-
const hasBasicQueryInput = ({ basicQueryInputs, key }) => basicQueryInputs.some((input) => input.key === key);
|
|
7
|
-
const derivedBooleanFilters = [{
|
|
8
|
-
key: "pets",
|
|
9
|
-
isSelected: (filter) => (filter.petsCount ?? 0) > 0
|
|
10
|
-
}];
|
|
11
|
-
const applyVofficeFilterDerivedBasicQueryInputs = ({ appliedFilters, basicQueryInputs, filter, locale, translations }) => Effect.gen(function* () {
|
|
12
|
-
const nextAppliedFilters = [...appliedFilters];
|
|
13
|
-
const nextBasicQueryInputs = [...basicQueryInputs];
|
|
14
|
-
for (const derivedFilter of derivedBooleanFilters) {
|
|
15
|
-
if (!derivedFilter.isSelected(filter) || hasBasicQueryInput({
|
|
16
|
-
basicQueryInputs: nextBasicQueryInputs,
|
|
17
|
-
key: derivedFilter.key
|
|
18
|
-
})) continue;
|
|
19
|
-
nextBasicQueryInputs.push({
|
|
20
|
-
key: derivedFilter.key,
|
|
21
|
-
value: true
|
|
22
|
-
});
|
|
23
|
-
nextAppliedFilters.push({
|
|
24
|
-
key: derivedFilter.key,
|
|
25
|
-
label: yield* translations.translate(locale, `filter.${derivedFilter.key}.label`, derivedFilter.key)
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
appliedFilters: nextAppliedFilters,
|
|
30
|
-
basicQueryInputs: nextBasicQueryInputs
|
|
31
|
-
};
|
|
32
|
-
});
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region src/legacy-v9/parser/search/input/filter/filter-query-keys.ts
|
|
35
|
-
const FILTER_QUERY_KEYS = new Set(Object.keys(stable_filters_default));
|
|
36
|
-
//#endregion
|
|
37
|
-
//#region src/legacy-v9/parser/search/input/filter/to-basic-query-inputs.ts
|
|
38
|
-
const isEnabledBooleanFilter = (value) => {
|
|
39
|
-
const normalizedValue = value.toLowerCase();
|
|
40
|
-
return normalizedValue === "" || normalizedValue === "true" || normalizedValue === "1";
|
|
41
|
-
};
|
|
42
|
-
const toBasicQueryInput = ({ queryKey, value, filter }) => {
|
|
43
|
-
if (filter.type === "BooleanFilter") return isEnabledBooleanFilter(value) ? {
|
|
44
|
-
key: queryKey,
|
|
45
|
-
value: true
|
|
46
|
-
} : void 0;
|
|
47
|
-
if (filter.type === "InputFilter") {
|
|
48
|
-
const numberValue = Number(value);
|
|
49
|
-
if (!Number.isInteger(numberValue) || numberValue < 0) return;
|
|
50
|
-
return {
|
|
51
|
-
key: queryKey,
|
|
52
|
-
value: numberValue
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
const toCustomBackendFilterInput = ({ queryKey, value, filter }) => {
|
|
57
|
-
switch (filter.type) {
|
|
58
|
-
case "boolean": return isEnabledBooleanFilter(value) ? {
|
|
59
|
-
key: queryKey,
|
|
60
|
-
value: true
|
|
61
|
-
} : void 0;
|
|
62
|
-
case "int": {
|
|
63
|
-
const numberValue = Number(value);
|
|
64
|
-
return Number.isInteger(numberValue) && numberValue >= 0 ? {
|
|
65
|
-
key: queryKey,
|
|
66
|
-
value: numberValue
|
|
67
|
-
} : void 0;
|
|
68
|
-
}
|
|
69
|
-
case "string": return value.length > 0 ? {
|
|
70
|
-
key: queryKey,
|
|
71
|
-
value
|
|
72
|
-
} : void 0;
|
|
73
|
-
case "option": return filter.options.some((option) => option.value === value) ? {
|
|
74
|
-
key: queryKey,
|
|
75
|
-
value
|
|
76
|
-
} : void 0;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
const toBasicQueryInputs = ({ query, customAttributeFilterDefinitions, locale, translations }) => {
|
|
80
|
-
const appliedFilterEffects = [];
|
|
81
|
-
const basicQueryInputs = [];
|
|
82
|
-
const remainingParameters = [];
|
|
83
|
-
const seenScalarFilters = /* @__PURE__ */ new Set();
|
|
84
|
-
const customBackendFiltersByKey = new Map(customAttributeFilterDefinitions.filter((definition) => definition.source === "backendFilter" && definition.searchable).map((definition) => [definition.key, definition]));
|
|
85
|
-
for (const [queryKey, value] of parseQueryParameters(query)) {
|
|
86
|
-
const filter = stable_filters_default[queryKey];
|
|
87
|
-
const customBackendFilter = customBackendFiltersByKey.get(queryKey);
|
|
88
|
-
if ((!FILTER_QUERY_KEYS.has(queryKey) || filter == null) && customBackendFilter == null) {
|
|
89
|
-
remainingParameters.push([queryKey, value]);
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (seenScalarFilters.has(queryKey)) {
|
|
93
|
-
remainingParameters.push([queryKey, value]);
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
const basicQueryInput = filter == null ? customBackendFilter != null ? toCustomBackendFilterInput({
|
|
97
|
-
queryKey,
|
|
98
|
-
value,
|
|
99
|
-
filter: customBackendFilter
|
|
100
|
-
}) : void 0 : toBasicQueryInput({
|
|
101
|
-
queryKey,
|
|
102
|
-
value,
|
|
103
|
-
filter
|
|
104
|
-
});
|
|
105
|
-
if (basicQueryInput == null) {
|
|
106
|
-
remainingParameters.push([queryKey, value]);
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
seenScalarFilters.add(queryKey);
|
|
110
|
-
basicQueryInputs.push(basicQueryInput);
|
|
111
|
-
if (customBackendFilter != null) appliedFilterEffects.push(Effect.succeed({
|
|
112
|
-
key: queryKey,
|
|
113
|
-
label: toCustomAttributeFilterLabel({
|
|
114
|
-
definition: customBackendFilter,
|
|
115
|
-
locale,
|
|
116
|
-
value
|
|
117
|
-
})
|
|
118
|
-
}));
|
|
119
|
-
else appliedFilterEffects.push(translations.translate(locale, `filter.${queryKey}.label`, queryKey).pipe(Effect.map((label) => ({
|
|
120
|
-
key: queryKey,
|
|
121
|
-
label
|
|
122
|
-
}))));
|
|
123
|
-
}
|
|
124
|
-
return {
|
|
125
|
-
appliedFilters: Effect.all(appliedFilterEffects),
|
|
126
|
-
basicQueryInputs,
|
|
127
|
-
remainingQuery: toQueryString(remainingParameters)
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
//#endregion
|
|
131
5
|
//#region src/legacy-v9/parser/search/input/search-input-error.ts
|
|
132
6
|
const failInvalidV9SearchInput = (message) => Effect.fail(new CoreSDKError({
|
|
133
7
|
source: "v10",
|
|
@@ -305,6 +179,7 @@ const toVofficeSorting = (sort) => {
|
|
|
305
179
|
//#region src/legacy-v9/parser/search/input/to-query-input.ts
|
|
306
180
|
const toQueryInput = ({ query, sort, customAttributeFilterDefinitions, locale, translations }) => Effect.gen(function* () {
|
|
307
181
|
const compositionResult = expandCustomAttributeFilterCompositions({
|
|
182
|
+
capabilities: makeV9CustomAttributeFilterCapabilities(customAttributeFilterDefinitions),
|
|
308
183
|
customAttributeFilterDefinitions,
|
|
309
184
|
locale,
|
|
310
185
|
query
|
|
@@ -330,8 +205,16 @@ const toQueryInput = ({ query, sort, customAttributeFilterDefinitions, locale, t
|
|
|
330
205
|
locale,
|
|
331
206
|
translations
|
|
332
207
|
});
|
|
208
|
+
const compositionFilters = resolveExpandedCompositions({
|
|
209
|
+
compositions: compositionResult.compositions,
|
|
210
|
+
unusedFilterKeys: [
|
|
211
|
+
...compositionResult.unusedFilterKeys,
|
|
212
|
+
...occupancyResult?.unusedFilterKeys ?? [],
|
|
213
|
+
...toUnusedFilterKeys(basicQueryResult.remainingQuery)
|
|
214
|
+
]
|
|
215
|
+
});
|
|
333
216
|
return {
|
|
334
|
-
appliedFilters: [...
|
|
217
|
+
appliedFilters: [...compositionFilters.appliedFilters, ...appliedFilters],
|
|
335
218
|
queryInput: {
|
|
336
219
|
vofficeData: {
|
|
337
220
|
filter: Object.keys(filter).length > 0 ? filter : void 0,
|
|
@@ -340,7 +223,7 @@ const toQueryInput = ({ query, sort, customAttributeFilterDefinitions, locale, t
|
|
|
340
223
|
},
|
|
341
224
|
basicQueryInputs
|
|
342
225
|
},
|
|
343
|
-
unusedFilterKeys:
|
|
226
|
+
unusedFilterKeys: compositionFilters.unusedFilterKeys
|
|
344
227
|
};
|
|
345
228
|
});
|
|
346
229
|
//#endregion
|
|
@@ -356,7 +239,7 @@ const toFormattedPrice = ({ locale, calc }) => {
|
|
|
356
239
|
};
|
|
357
240
|
//#endregion
|
|
358
241
|
//#region src/legacy-v9/parser/search/to-search-output-item.ts
|
|
359
|
-
const toSearchOutputItem = ({ locale, imageProxyBaseUrl, rentalHighlightPrioritization,
|
|
242
|
+
const toSearchOutputItem = ({ locale, imageProxyBaseUrl, rentalHighlightPrioritization, customAttributes, rental, translations, includeFormattedTotal }) => Effect.gen(function* () {
|
|
360
243
|
const data = parseVofficeUnitData(rental.data);
|
|
361
244
|
const item = {
|
|
362
245
|
id: rental.voffice_id.toString(),
|
|
@@ -371,7 +254,7 @@ const toSearchOutputItem = ({ locale, imageProxyBaseUrl, rentalHighlightPrioriti
|
|
|
371
254
|
locale,
|
|
372
255
|
translations,
|
|
373
256
|
highlightPrioritization: rentalHighlightPrioritization,
|
|
374
|
-
|
|
257
|
+
customAttributes,
|
|
375
258
|
attributes: data
|
|
376
259
|
});
|
|
377
260
|
if (highlights != null) item.highlights = highlights;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { localeToLanguage, makeTranslate,
|
|
1
|
+
import { localeToLanguage, makeTranslate, renderLabeledAttributeValue, renderResolvedCustomAttribute, toCountry } from "@v-office/sdk-core";
|
|
2
2
|
import { Effect, Schema } from "effect";
|
|
3
3
|
//#region codegen/v9/heuristic-generation/v9-data.ts
|
|
4
4
|
/**
|
|
@@ -5870,7 +5870,7 @@ const toV9RentalHighlightKey = (key) => {
|
|
|
5870
5870
|
};
|
|
5871
5871
|
//#endregion
|
|
5872
5872
|
//#region src/legacy-v9/parser/rentals/to-rental-highlights.ts
|
|
5873
|
-
const toRentalHighlights = ({ locale, translations, highlightPrioritization,
|
|
5873
|
+
const toRentalHighlights = ({ locale, translations, highlightPrioritization, customAttributes, attributes }) => Effect.gen(function* () {
|
|
5874
5874
|
const highlights = [];
|
|
5875
5875
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
5876
5876
|
const knownAttributes = attributes.known;
|
|
@@ -5880,11 +5880,13 @@ const toRentalHighlights = ({ locale, translations, highlightPrioritization, cus
|
|
|
5880
5880
|
if (v9Key == null) {
|
|
5881
5881
|
if (seenKeys.has(highlightKey)) continue;
|
|
5882
5882
|
seenKeys.add(highlightKey);
|
|
5883
|
-
const
|
|
5884
|
-
|
|
5885
|
-
|
|
5883
|
+
const attribute = customAttributes.byKey[highlightKey];
|
|
5884
|
+
if (attribute === void 0) continue;
|
|
5885
|
+
const binding = attribute.v9;
|
|
5886
|
+
const highlight = renderResolvedCustomAttribute({
|
|
5887
|
+
attribute,
|
|
5886
5888
|
locale,
|
|
5887
|
-
value: knownAttributes[
|
|
5889
|
+
value: binding === void 0 ? void 0 : knownAttributes[binding] ?? attributes.unknown[binding]
|
|
5888
5890
|
});
|
|
5889
5891
|
if (highlight != null) highlights.push(highlight);
|
|
5890
5892
|
continue;
|
|
@@ -5077,6 +5077,8 @@
|
|
|
5077
5077
|
"RentalAttributesCategory.MEDIA.label": "Medien",
|
|
5078
5078
|
"RentalAttributesCategory.OTHER.label": "Andere",
|
|
5079
5079
|
"RentalAttributesCategory.OUTDOORS.label": "Außenbereich",
|
|
5080
|
+
"RentalAttributesCategory.roomSummary.label": "Zimmer",
|
|
5081
|
+
"RentalAttributesCategory.vicinity.label": "Umgebung",
|
|
5080
5082
|
"RentalAttributesCategory.PRACTICAL_NECESSITIES.label": "Praktische Notwendigkeiten",
|
|
5081
5083
|
"RentalAttributesCategory.PROPERTY_DETAILS_RULES.label": "Objektdetails & Regeln",
|
|
5082
5084
|
"RentalAttributesCategory.PROPERTY_TYPE_LOCATION.label": "Unterkunftstyp & Standort",
|
|
@@ -5077,6 +5077,8 @@
|
|
|
5077
5077
|
"RentalAttributesCategory.MEDIA.label": "Media",
|
|
5078
5078
|
"RentalAttributesCategory.OTHER.label": "Other",
|
|
5079
5079
|
"RentalAttributesCategory.OUTDOORS.label": "Outdoor Area",
|
|
5080
|
+
"RentalAttributesCategory.roomSummary.label": "Rooms",
|
|
5081
|
+
"RentalAttributesCategory.vicinity.label": "Vicinity",
|
|
5080
5082
|
"RentalAttributesCategory.PRACTICAL_NECESSITIES.label": "Practical Necessities",
|
|
5081
5083
|
"RentalAttributesCategory.PROPERTY_DETAILS_RULES.label": "Property Details & Rules",
|
|
5082
5084
|
"RentalAttributesCategory.PROPERTY_TYPE_LOCATION.label": "Property Type & Location",
|
|
@@ -4,7 +4,9 @@ This file is the versioned changelog index for the website SDK instructions.
|
|
|
4
4
|
|
|
5
5
|
## Versions
|
|
6
6
|
|
|
7
|
-
- `versions/2.
|
|
7
|
+
- `versions/2.8.0/CHANGELOG.md`: `@v-office/website-sdk` 2.8.0 release notes.
|
|
8
|
+
- `versions/2.7.0/CHANGELOG.md`: `@v-office/website-sdk` 2.7.0 release notes.
|
|
9
|
+
- `versions/2.6.0/CHANGELOG.md`: compatibility note for an unreleased version label.
|
|
8
10
|
- `versions/2.5.0/CHANGELOG.md`: `@v-office/website-sdk` 2.5.0 release notes.
|
|
9
11
|
- `versions/2.4.3/CHANGELOG.md`: `@v-office/website-sdk` 2.4.3 documentation release notes.
|
|
10
12
|
- `versions/2.4.2/CHANGELOG.md`: `@v-office/website-sdk` 2.4.2 release notes.
|
|
@@ -4,7 +4,9 @@ This file is the versioned migration index for the website SDK instructions.
|
|
|
4
4
|
|
|
5
5
|
## Available Guides
|
|
6
6
|
|
|
7
|
-
- `versions/2.
|
|
7
|
+
- `versions/2.8.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.7.0 to 2.8.0.
|
|
8
|
+
- `versions/2.7.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.5.x to 2.7.0.
|
|
9
|
+
- `versions/2.6.0/MIGRATION.md`: compatibility note for an unreleased version label.
|
|
8
10
|
- `versions/2.5.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.3 to 2.5.0.
|
|
9
11
|
- `versions/2.4.3/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.2 to 2.4.3.
|
|
10
12
|
- `versions/2.4.2/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.1 to 2.4.2.
|
package/instructions/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Website SDK Instructions
|
|
2
2
|
|
|
3
|
-
These instructions describe
|
|
3
|
+
These instructions describe the current source targeted for
|
|
4
|
+
`@v-office/website-sdk` 2.8.0. Package versions remain unchanged until the release
|
|
5
|
+
workflow performs the coordinated core and website bumps.
|
|
4
6
|
|
|
5
7
|
Use this directory as the consumer-facing reference for the package:
|
|
6
8
|
|
|
7
9
|
- `creation.md`: SDK construction, config, options, and CLI config files.
|
|
8
10
|
- `rentals.md`: `sdk.static.rentals.getRentals`.
|
|
9
11
|
- `filter.md`: `sdk.static.filter.getFilters`.
|
|
12
|
+
- `custom-attributes.md`: custom attribute catalog, configuration, per-backend behaviour, and the v9-to-v10 move.
|
|
10
13
|
- `search.md`: `sdk.live.search.search`.
|
|
11
14
|
- `availability.md`: date-picker availability flows.
|
|
12
15
|
- `quote.md`: quote, additional services, cancellation policy, and insurance flows.
|
|
@@ -15,7 +18,9 @@ Use this directory as the consumer-facing reference for the package:
|
|
|
15
18
|
- `document-structured-json.md`: `sdk.static.documents.getTermsAndPrivacyPolicy` and structured document JSON rendering rules.
|
|
16
19
|
- `CHANGELOG.md`: versioned changelog index.
|
|
17
20
|
- `MIGRATION.md`: versioned migration index.
|
|
18
|
-
- `versions/2.
|
|
21
|
+
- `versions/2.8.0/`: 2.8.0 custom-attribute release notes and 2.7.0-to-2.8.0 migration guide.
|
|
22
|
+
- `versions/2.7.0/`: 2.7.0 release notes and 2.5.x-to-2.7.0 migration guide.
|
|
23
|
+
- `versions/2.6.0/`: compatibility pointers for the unreleased 2.6.0 version label.
|
|
19
24
|
- `versions/2.5.0/`: 2.5.0 release notes and 2.4.3-to-2.5.0 migration guide.
|
|
20
25
|
- `versions/2.4.3/`: 2.4.3 documentation release notes and migration guide.
|
|
21
26
|
- `versions/2.4.2/`: 2.4.2 release notes and 2.4.1-to-2.4.2 migration guide.
|
|
@@ -69,4 +74,4 @@ website-sdk --backend v10 search --locale de-DE --query "adults=2"
|
|
|
69
74
|
website-sdk --backend v10 search --locale de-DE --query "adults=2" --sort '{"by":"field","orderBy":{"label":"ASC"}}'
|
|
70
75
|
```
|
|
71
76
|
|
|
72
|
-
Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced in 2.0.0 and kept in 2.
|
|
77
|
+
Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced in 2.0.0 and kept in 2.8.0. v10 config additionally requires `searchEndpoint` as of 2.5.0.
|
package/instructions/creation.md
CHANGED
|
@@ -81,6 +81,7 @@ const options = defineWebsiteSDKOptions({
|
|
|
81
81
|
},
|
|
82
82
|
rentalHighlightPrioritization: ["bedrooms", "bathrooms", "maxPersons", "wifi"],
|
|
83
83
|
rentalPropertyHighlightPrioritization: ["wifi", "parking"],
|
|
84
|
+
customAttributes,
|
|
84
85
|
customAttributeFilterDefinitions: [],
|
|
85
86
|
translationOverrides: {},
|
|
86
87
|
});
|
|
@@ -91,8 +92,8 @@ const options = defineWebsiteSDKOptions({
|
|
|
91
92
|
```ts
|
|
92
93
|
type WebsiteSDKOptions = {
|
|
93
94
|
translationOverrides?: TranslationOverrides;
|
|
95
|
+
customAttributes?: CustomAttributeRegistrySnapshot;
|
|
94
96
|
customAttributeFilterDefinitions?: readonly CustomAttributeFilterDefinition[];
|
|
95
|
-
customAttributeDefinitionManifest?: CustomAttributeDefinitionManifest;
|
|
96
97
|
rentalHighlightPrioritization?: readonly RentalHighlightPrioritizationKey[];
|
|
97
98
|
rentalPropertyHighlightPrioritization?: readonly RentalPropertyHighlightPrioritizationKey[];
|
|
98
99
|
rentalScope?: RentalScope;
|
|
@@ -102,8 +103,8 @@ type WebsiteSDKOptions = {
|
|
|
102
103
|
|
|
103
104
|
Unset options are normalized by the SDK:
|
|
104
105
|
|
|
106
|
+
- `customAttributes` defaults to an empty registry.
|
|
105
107
|
- `customAttributeFilterDefinitions` defaults to `[]`.
|
|
106
|
-
- `customAttributeDefinitionManifest` is omitted unless provided; an absent manifest is treated as empty.
|
|
107
108
|
- `rentalHighlightPrioritization` defaults to the SDK default rental highlight order.
|
|
108
109
|
- `rentalPropertyHighlightPrioritization` defaults to the SDK default property highlight order.
|
|
109
110
|
- `rentalScope` defaults to `{}`.
|
|
@@ -130,31 +131,45 @@ const options = defineWebsiteSDKOptions({
|
|
|
130
131
|
|
|
131
132
|
The scope is always applied internally and is not returned by `static.filter.getFilters(...)`. Use it for website-level or tenant-level constraints.
|
|
132
133
|
|
|
133
|
-
## Custom
|
|
134
|
+
## Custom Attributes
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
Custom attributes are configured through `customAttributes`, built by
|
|
137
|
+
`defineCustomAttributes` from the workspace catalog plus your product policy:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const customAttributes = defineCustomAttributes({
|
|
141
|
+
catalog,
|
|
142
|
+
select: {
|
|
143
|
+
region: {
|
|
144
|
+
label: { "de-DE": "Region", "en-US": "Region" },
|
|
145
|
+
filter: true,
|
|
146
|
+
optionLabels: {
|
|
147
|
+
north: { "de-DE": "Nord", "en-US": "North" },
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const options = defineWebsiteSDKOptions({ customAttributes });
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
See `custom-attributes.md` for the catalog, the selection shape, per-backend
|
|
157
|
+
behaviour, and the v9-to-v10 move.
|
|
158
|
+
|
|
159
|
+
## Backend Filters and Composed Filters
|
|
160
|
+
|
|
161
|
+
`customAttributeFilterDefinitions` holds the two filter concepts that are _not_
|
|
162
|
+
custom attributes:
|
|
136
163
|
|
|
137
164
|
```ts
|
|
138
165
|
const options = defineWebsiteSDKOptions({
|
|
139
166
|
customAttributeFilterDefinitions: [
|
|
140
167
|
{
|
|
141
|
-
key: "
|
|
142
|
-
source: "
|
|
143
|
-
category: "
|
|
144
|
-
label: {
|
|
145
|
-
|
|
146
|
-
"en-US": "Region",
|
|
147
|
-
},
|
|
148
|
-
type: "option",
|
|
149
|
-
options: [
|
|
150
|
-
{
|
|
151
|
-
value: "north",
|
|
152
|
-
label: {
|
|
153
|
-
"de-DE": "Nord",
|
|
154
|
-
"en-US": "North",
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
],
|
|
168
|
+
key: "atLeastTwoBedrooms",
|
|
169
|
+
source: "backendFilter",
|
|
170
|
+
category: "LIVING_SLEEPING",
|
|
171
|
+
label: { "de-DE": "Mind. zwei Schlafzimmer", "en-US": "At least two bedrooms" },
|
|
172
|
+
type: "boolean",
|
|
158
173
|
searchable: true,
|
|
159
174
|
internal: false,
|
|
160
175
|
},
|
|
@@ -165,59 +180,27 @@ const options = defineWebsiteSDKOptions({
|
|
|
165
180
|
Supported filter types:
|
|
166
181
|
|
|
167
182
|
- `boolean`: accepts enabled query values such as `?key`, `?key=true`, or `?key=1`.
|
|
168
|
-
- `int`: accepts integer query values
|
|
183
|
+
- `int`: accepts integer query values. The definition includes a `numericBounds`
|
|
184
|
+
object; omit its `min` and `max` fields when the UI needs no bounds.
|
|
169
185
|
- `option`: accepts one of the configured `options` values and exposes those options through `getFilters`.
|
|
170
186
|
- `string`: accepts any non-empty query value as an exact raw value.
|
|
171
187
|
- `complex`: composition-only type that expands one boolean query-string filter into other configured filters.
|
|
172
188
|
|
|
173
189
|
Supported sources:
|
|
174
190
|
|
|
175
|
-
- `
|
|
176
|
-
- `
|
|
177
|
-
|
|
191
|
+
- `backendFilter`: backed by backend-defined search filter keys, mainly for v9 hub filters. Advertised and executed by v9 only.
|
|
192
|
+
- `composition`: expands one boolean query-string filter into other configured
|
|
193
|
+
filters. It is advertised only when every configured leaf can execute on the
|
|
194
|
+
active backend, and no generated leaf is committed unless all leaves are valid.
|
|
195
|
+
Nested compositions are rejected while recursive expansion is unsupported.
|
|
178
196
|
|
|
179
|
-
|
|
197
|
+
Exposure:
|
|
180
198
|
|
|
181
199
|
- `internal: false` exposes searchable filters through `static.filter.getFilters(...)`.
|
|
182
200
|
- `internal: true` keeps filters usable by search and compositions but hides them from `getFilters`.
|
|
183
|
-
- `searchable: false` keeps custom attributes as display metadata only.
|
|
184
201
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
The v10 REST search backend filters and returns custom attributes by definition ID, while SDK configuration and query strings use keys. Because definition IDs are workspace/environment specific, use `customAttributeDefinitionManifest` to give the SDK a key-to-ID and ID-to-key mapping:
|
|
188
|
-
|
|
189
|
-
```ts
|
|
190
|
-
const options = defineWebsiteSDKOptions({
|
|
191
|
-
customAttributeDefinitionManifest: {
|
|
192
|
-
byKey: {
|
|
193
|
-
region: { id: "def-1", key: "region", type: "OPTION", visibility: "PUBLIC" },
|
|
194
|
-
},
|
|
195
|
-
byId: {
|
|
196
|
-
"def-1": { id: "def-1", key: "region", type: "OPTION", visibility: "PUBLIC" },
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
});
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
|
-
type CustomAttributeDefinitionManifestEntry = {
|
|
204
|
-
id: string;
|
|
205
|
-
key: string;
|
|
206
|
-
type: "BOOLEAN" | "INT" | "STRING" | "OPTION";
|
|
207
|
-
visibility: "PUBLIC" | string | null;
|
|
208
|
-
options?: readonly { value: string; label?: Record<string, string> }[];
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
type CustomAttributeDefinitionManifest = {
|
|
212
|
-
byKey: Record<string, CustomAttributeDefinitionManifestEntry>;
|
|
213
|
-
byId: Record<string, CustomAttributeDefinitionManifestEntry>;
|
|
214
|
-
};
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
- Generate the manifest at build time from your definitions source, and pass a separate manifest per workspace/environment because IDs are not portable.
|
|
218
|
-
- Custom-attribute keys that have no manifest entry are left in `unusedFilterKeys` instead of being applied as filters.
|
|
219
|
-
- Only definitions with `visibility` of `PUBLIC` (or `null`) are surfaced as v10 search highlights; others are ignored.
|
|
220
|
-
- The manifest is only used by v10 search. v9 and the non-search v10 endpoints ignore it.
|
|
202
|
+
`internal` is a UI-visibility choice, not a security boundary — an internal filter is
|
|
203
|
+
still parseable from a query string. See `custom-attributes.md`.
|
|
221
204
|
|
|
222
205
|
## Translation Overrides
|
|
223
206
|
|
|
@@ -262,8 +245,26 @@ Example `website-sdk-options.json`:
|
|
|
262
245
|
"rentalScope": {
|
|
263
246
|
"propertyId": "property-1"
|
|
264
247
|
},
|
|
265
|
-
"
|
|
248
|
+
"customAttributes": {
|
|
249
|
+
"catalog": {
|
|
250
|
+
"privateSauna": {
|
|
251
|
+
"id": "GQYKYgMVh28X7VLGursbkt",
|
|
252
|
+
"type": "BOOLEAN"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"select": {
|
|
256
|
+
"privateSauna": {
|
|
257
|
+
"label": { "de-DE": "Sauna", "en-US": "Sauna" },
|
|
258
|
+
"filter": true
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"rentalHighlightPrioritization": ["bedrooms", "privateSauna", "wifi"],
|
|
266
263
|
"customAttributeFilterDefinitions": [],
|
|
267
264
|
"translationOverrides": {}
|
|
268
265
|
}
|
|
269
266
|
```
|
|
267
|
+
|
|
268
|
+
CLI options carry the custom-attribute **catalog and selection inputs**, not a
|
|
269
|
+
pre-built registry. The CLI validates and joins them before creating the SDK. See
|
|
270
|
+
`custom-attributes.md` for the complete shape and key-collision rules.
|