@v-office/website-sdk 2.10.0 → 2.12.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.
Files changed (31) hide show
  1. package/README.md +7 -3
  2. package/dist/cli.d.mts +1 -1
  3. package/dist/cli.mjs +2 -2
  4. package/dist/{client-DYAHnU5F.mjs → client-Bmxh2SAu.mjs} +54 -30
  5. package/dist/index.d.mts +590 -291
  6. package/dist/index.mjs +1 -1
  7. package/dist/instructions/CHANGELOG.md +2 -0
  8. package/dist/instructions/MIGRATION.md +2 -0
  9. package/dist/instructions/README.md +10 -3
  10. package/dist/instructions/quote.md +95 -3
  11. package/dist/instructions/search.md +118 -13
  12. package/dist/instructions/versions/2.11.0/CHANGELOG.md +28 -0
  13. package/dist/instructions/versions/2.11.0/MIGRATION.md +72 -0
  14. package/dist/instructions/versions/2.12.0/CHANGELOG.md +56 -0
  15. package/dist/instructions/versions/2.12.0/MIGRATION.md +194 -0
  16. package/dist/instructions/versions/2.5.0/MIGRATION.md +6 -0
  17. package/dist/{quote-Cs6jGoRS.mjs → quote-Qy_affum.mjs} +4 -4
  18. package/dist/{rentals-CFod9H4m.mjs → rentals-BG1diZoo.mjs} +7 -4
  19. package/dist/{search-QlZrI7ue.mjs → search-BlL8vSPY.mjs} +39 -19
  20. package/dist/{to-rental-highlights-B6a_fi0j.mjs → to-rental-highlights-BVikT4Iz.mjs} +4 -2
  21. package/instructions/CHANGELOG.md +2 -0
  22. package/instructions/MIGRATION.md +2 -0
  23. package/instructions/README.md +10 -3
  24. package/instructions/quote.md +95 -3
  25. package/instructions/search.md +118 -13
  26. package/instructions/versions/2.11.0/CHANGELOG.md +28 -0
  27. package/instructions/versions/2.11.0/MIGRATION.md +72 -0
  28. package/instructions/versions/2.12.0/CHANGELOG.md +56 -0
  29. package/instructions/versions/2.12.0/MIGRATION.md +194 -0
  30. package/instructions/versions/2.5.0/MIGRATION.md +6 -0
  31. package/package.json +15 -13
@@ -87,17 +87,38 @@ Use `&` to combine period, occupancy, and filter parameters:
87
87
  "start=20-06-2026&end=27-06-2026&adults=2&wifi";
88
88
  ```
89
89
 
90
+ ### Empty Queries
91
+
92
+ On v9, an empty query returns the first page of searchable inventory under the
93
+ configured rental scope:
94
+
95
+ ```ts
96
+ await sdk.live.search.search({
97
+ locale: "de-DE",
98
+ query: "",
99
+ });
100
+ ```
101
+
102
+ The v9 facade serializes an empty backend-filter set as GraphQL `data: null`.
103
+ Pagination and the configured `limit` still apply; an undated query does not
104
+ assert availability for a particular stay.
105
+
90
106
  ### Period Queries
91
107
 
92
108
  Use one supported period structure per query.
93
109
 
94
- Exact period search:
110
+ Fixed-period search is supported by both v9 and v10:
95
111
 
96
112
  ```ts
97
113
  "start=20-06-2026&end=27-06-2026";
98
114
  ```
99
115
 
100
- Flexible search by month:
116
+ Flexible-period search is supported by v10 only. Legacy v9 rejects the `month`,
117
+ `dates`, `nights`, and `weekend` keys before transport instead of silently
118
+ returning an unpriced item list. Keep the flexible selector unavailable on v9
119
+ sites and use `start` plus `end` for a fixed-period search.
120
+
121
+ Flexible v10 search by month:
101
122
 
102
123
  ```ts
103
124
  "month=06-2026&nights=7";
@@ -106,7 +127,7 @@ Flexible search by month:
106
127
  "month=06-2026&month=07-2026&weekend";
107
128
  ```
108
129
 
109
- Flexible search by exact date tuples:
130
+ Flexible v10 search by exact date tuples:
110
131
 
111
132
  ```ts
112
133
  "dates=20-06-2026,22-06-2026&nights=2";
@@ -134,6 +155,9 @@ Boolean filters can be provided as presence-only flags when supported:
134
155
 
135
156
  ### Invalid Combinations
136
157
 
158
+ The following flexible-query validation rules apply to v10. Legacy v9 rejects
159
+ every flexible-period key as described above.
160
+
137
161
  Do not mix exact period search with flexible period options:
138
162
 
139
163
  ```ts
@@ -155,7 +179,7 @@ Flexible queries require either `nights` or `weekend`, but not both:
155
179
  "month=06-2026&nights=7&weekend";
156
180
  ```
157
181
 
158
- Dates should use `DD-MM-YYYY`; months should use `MM-YYYY`.
182
+ Flexible date tuples accept `DD-MM-YYYY` and `YYYY-MM-DD`; months use `MM-YYYY`.
159
183
 
160
184
  Use `rentalIdsIn` to restrict results to specific rental IDs. This option is currently supported by `v10` only.
161
185
  Use `voucher` to price v10 search results with a voucher code. This option is currently supported by `v10` only.
@@ -227,6 +251,18 @@ The supported fields are `label`, `name`, all six `roomSummary` counters, `attri
227
251
 
228
252
  Returns `Promise<RentalSearchOutput>`.
229
253
 
254
+ Priced items and alternative periods share this optional discount shape:
255
+
256
+ ```ts
257
+ type SearchDiscount = {
258
+ readonly formattedOriginalTotal: string;
259
+ readonly applied: readonly {
260
+ readonly label: string;
261
+ readonly formattedAmount: string;
262
+ }[];
263
+ };
264
+ ```
265
+
230
266
  Sample:
231
267
 
232
268
  ```json
@@ -250,7 +286,16 @@ Sample:
250
286
  }
251
287
  ],
252
288
  "highlights": ["2 bedrooms", "WiFi", "Parking"],
253
- "formattedTotal": "1.234,00 €"
289
+ "formattedTotal": "1.111,00 €",
290
+ "discount": {
291
+ "formattedOriginalTotal": "1.234,00 €",
292
+ "applied": [
293
+ {
294
+ "label": "Frühbucher-Rabatt",
295
+ "formattedAmount": "-123,00 €"
296
+ }
297
+ ]
298
+ }
254
299
  }
255
300
  ],
256
301
  "alternatives": [
@@ -264,7 +309,16 @@ Sample:
264
309
  {
265
310
  "start": "2026-07-10",
266
311
  "end": "2026-07-17",
267
- "formattedTotal": "1.456,00 €"
312
+ "formattedTotal": "1.310,00 €",
313
+ "discount": {
314
+ "formattedOriginalTotal": "1.456,00 €",
315
+ "applied": [
316
+ {
317
+ "label": "Frühbucher-Rabatt",
318
+ "formattedAmount": "-146,00 €"
319
+ }
320
+ ]
321
+ }
268
322
  }
269
323
  ]
270
324
  }
@@ -288,7 +342,15 @@ Sample:
288
342
  }
289
343
  ```
290
344
 
291
- Search items share the rental base fields and may include `scope`, `address`, `property`, `highlights`, and `formattedTotal`. Exact-period results are returned in `items`; alternative-period suggestions are returned in root-level `alternatives`.
345
+ Search items share the rental base fields and may include `scope`, `address`,
346
+ `property`, `highlights`, and `formattedTotal`. A priced item or alternative period
347
+ may also include `discount`. When it does, `formattedTotal` is the final price and
348
+ `discount.formattedOriginalTotal` is the price before the applied discounts.
349
+ Discount totals, labels, and amounts are already localized and formatted for the
350
+ requested locale; backend numeric amounts and modifier type keys are not exposed.
351
+ `applied` may be empty when the backend supplies an original total without
352
+ individual modifier lines. Exact-period results are returned in `items`;
353
+ alternative-period suggestions are returned in root-level `alternatives`.
292
354
 
293
355
  `appliedFilters` reports what the backend actually applied, and is what a "remove
294
356
  this filter" chip should be built from. `label` is localized presentation and can
@@ -311,15 +373,58 @@ the expanded leaf entries. A UI may collapse those leaves under the composition
311
373
  display, but should keep the returned keys and canonical values when removing direct
312
374
  filters.
313
375
 
314
- ## v10 Backend
376
+ ## Backend Behavior
377
+
378
+ ### v10
315
379
 
316
- v10 search runs against the dedicated REST search backend (`POST` to the configured `searchEndpoint`). Existing calls and the output type remain compatible, while the input additionally supports optional sorting. v10 results reflect the REST projection:
380
+ v10 search runs against the dedicated REST search backend (`POST` to the configured
381
+ `searchEndpoint`). Existing calls and the output type remain compatible, while the
382
+ input additionally supports optional sorting. v10 results reflect the REST
383
+ projection:
317
384
 
318
385
  - At most five images per item, and no image `category`.
319
- - `property` is the minimal `{ id, nameOrLabel }` shape. Hydrate `property.location`, `property.images`, or `property.address` from `sdk.static.rentals.getRentals(...)` when a card needs them.
320
- - Custom-attribute search filters and highlights require the `customAttributes` registry. A definition with no catalog ID cannot be executed, so its query key is left in `unusedFilterKeys`. v9 never executes a custom-attribute filter at all. See `custom-attributes.md`.
321
- - Fixed-period and flexible searches are priced by the REST backend and require occupancy.
322
- - Pagination uses the backend `from`/`size` window behind the same opaque `cursor`, capped at 1,000 results.
386
+ - `property` is the minimal `{ id, nameOrLabel }` shape. Hydrate
387
+ `property.location`, `property.images`, or `property.address` from
388
+ `sdk.static.rentals.getRentals(...)` when a card needs them.
389
+ - Custom-attribute search filters and highlights require the `customAttributes`
390
+ registry. A definition with no catalog ID cannot be executed, so its query key
391
+ is left in `unusedFilterKeys`. See `custom-attributes.md`.
392
+ - Fixed-period and flexible searches are priced by the REST backend and require
393
+ occupancy.
394
+ - Priced items and alternative periods may include localized `discount` details
395
+ with multiple applied modifiers when the REST backend returns them.
396
+ - The v10 public search input shape is unchanged. The SDK keeps
397
+ alternative-cancellation-policy
398
+ pricing out of search; cancellation-policy selection remains part of the quote
399
+ and booking flow.
400
+ - Pagination uses the backend `from`/`size` window behind the same opaque `cursor`,
401
+ capped at 1,000 results.
402
+
403
+ ### Legacy v9
404
+
405
+ Legacy v9 maps its aggregated search calculation into the shared price and discount
406
+ shape:
407
+
408
+ - Flexible-period keys (`month`, `dates`, `nights`, and `weekend`) are rejected
409
+ before transport. v9 sites must use a fixed `start`/`end` period.
410
+ - Empty basic-filter sets are sent as GraphQL `data: null`, allowing an empty
411
+ query to browse the scoped searchable inventory without a dummy occupancy
412
+ value.
413
+ - `calc.total` becomes `formattedTotal`.
414
+ - `discount` is included only when `calc.oTotal` is greater than `calc.total`.
415
+ - `calc.oTotal` becomes `discount.formattedOriginalTotal`.
416
+ - A non-empty `calc.discountName` becomes the label of the single `applied` entry.
417
+ - The applied amount is the formatted negative difference
418
+ `calc.total - calc.oTotal`.
419
+ - Missing discount names produce an empty `applied` array without discarding the
420
+ formatted original total.
421
+ - The same mapping applies to exact-period items and individual alternative
422
+ periods.
423
+ - v9 never executes a custom-attribute search filter.
424
+
425
+ The field is omitted when v9 returns no final total or when its original total is
426
+ not greater than the final total. v9 exposes at most one aggregated applied entry,
427
+ whereas v10 can expose multiple detailed modifiers.
323
428
 
324
429
  ## Configuration
325
430
 
@@ -0,0 +1,28 @@
1
+ # Changelog: 2.11.0
2
+
3
+ This release exposes localized v10 REST search discount details on priced search
4
+ results.
5
+
6
+ ## Added
7
+
8
+ - Priced v10 search items may include an optional `discount` with the localized
9
+ pre-discount total in `formattedOriginalTotal`.
10
+ - `discount.applied` lists each applied discount as a localized `label` and
11
+ `formattedAmount`.
12
+ - Alternative-period suggestions expose the same optional discount shape on each
13
+ priced period.
14
+
15
+ ## Changed
16
+
17
+ - When `discount` is present, `formattedTotal` remains the final price after the
18
+ listed discounts.
19
+ - Backend modifier types and numeric amounts remain internal; the public search
20
+ output contains presentation-ready localized strings.
21
+
22
+ ## Migration Impact
23
+
24
+ - Existing search calls require no changes because `discount` is optional.
25
+ - Search configuration and input are unchanged.
26
+ - Legacy v9 search does not populate `discount`.
27
+ - Sites can opt in to strike-through pricing and discount labels by reading the
28
+ new field. See `versions/2.11.0/MIGRATION.md` and `../../search.md`.
@@ -0,0 +1,72 @@
1
+ # Migration: 2.10.0 to 2.11.0
2
+
3
+ 2.11.0 adds optional localized discount information to priced v10 search results.
4
+ Existing search calls and rendering remain valid without changes.
5
+
6
+ ## 1. Read the Optional Discount
7
+
8
+ Exact-period items and individual alternative periods may now include:
9
+
10
+ ```ts
11
+ type SearchDiscount = {
12
+ readonly formattedOriginalTotal: string;
13
+ readonly applied: readonly {
14
+ readonly label: string;
15
+ readonly formattedAmount: string;
16
+ }[];
17
+ };
18
+ ```
19
+
20
+ The field is omitted when the REST search backend returns no discount. Keep
21
+ rendering `formattedTotal` as before and add discount presentation only when
22
+ `discount` is present.
23
+
24
+ ## 2. Distinguish Final and Original Totals
25
+
26
+ When a discount is present:
27
+
28
+ - `formattedTotal` is the final price after the applied discounts.
29
+ - `discount.formattedOriginalTotal` is the total before those discounts.
30
+ - `discount.applied` contains presentation-ready localized labels and formatted
31
+ amounts.
32
+
33
+ All monetary values already include locale-aware currency formatting. Backend
34
+ numeric amounts and modifier type keys are intentionally not exposed.
35
+
36
+ ## 3. Handle Exact and Alternative Periods
37
+
38
+ For a fixed-period match, read the field from the item:
39
+
40
+ ```ts
41
+ result.items[0]?.discount;
42
+ ```
43
+
44
+ For a nearby-period suggestion, read it from the individual period:
45
+
46
+ ```ts
47
+ result.alternatives?.[0]?.alternativePeriods[0]?.discount;
48
+ ```
49
+
50
+ Each alternative period has independent pricing and may have a different discount
51
+ or no discount.
52
+
53
+ ## 4. Keep Search Inputs Unchanged
54
+
55
+ No configuration or input migration is required. The SDK continues to request the
56
+ existing default v10 search pricing and does not opt search into alternative
57
+ cancellation-policy pricing.
58
+
59
+ Legacy v9 search does not populate `discount`; consumers supporting both backends
60
+ must treat it as optional.
61
+
62
+ ## Recommended Verification
63
+
64
+ 1. Run a priced v10 exact-period search that has a configured discount and verify
65
+ the final and original totals.
66
+ 2. Verify each applied entry has a localized label and formatted amount in every
67
+ supported locale.
68
+ 3. Run a priced search without a discount and confirm existing rendering is
69
+ unchanged.
70
+ 4. Check nearby alternative periods independently because discounts can differ by
71
+ period.
72
+ 5. If the site supports v9, confirm its existing search output remains unchanged.
@@ -0,0 +1,56 @@
1
+ # Changelog: 2.12.0
2
+
3
+ This release extends the optional search discount output introduced in 2.11.0 to
4
+ legacy v9 search results, keeps zero-value lines out of quote booking-card
5
+ breakdowns, and completes v10 card-level pre-modifier totals across all modifier
6
+ presentation paths. It also rejects unsupported v9 flexible-period searches before
7
+ transport and restores empty-query inventory browsing on v9.
8
+
9
+ ## Added
10
+
11
+ - Priced legacy v9 exact-period items may include the shared optional `discount`
12
+ output.
13
+ - Individual legacy v9 alternative periods expose the same optional discount
14
+ shape.
15
+ - v9 maps its aggregated original total and discount name into
16
+ `formattedOriginalTotal` and at most one localized `applied` entry.
17
+
18
+ ## Changed
19
+
20
+ - Legacy v9 search now rejects the unsupported flexible-period query keys
21
+ `month`, `dates`, `nights`, and `weekend` before transport instead of silently
22
+ returning an unpriced item list. Fixed `start`/`end` searches are unchanged.
23
+ - Legacy v9 search serializes an empty backend-filter set as GraphQL `data: null`
24
+ instead of `data: []`. Empty queries can therefore browse searchable inventory
25
+ without seeding a dummy occupancy value.
26
+ - When a v9 discount is present, `formattedTotal` remains the final price and the
27
+ applied amount is the formatted difference from the original total.
28
+ - v10 search discount behavior is unchanged from 2.11.0 and can continue to expose
29
+ multiple applied modifiers.
30
+ - Quote booking cards now omit zero-value lines without subitems from the `other`
31
+ section on both v10 and legacy v9, matching the existing empty-line behavior of
32
+ the included and tax sections.
33
+ - If an `other` section contains both zero-value and non-zero lines, only the
34
+ non-zero lines remain. The section is omitted when no lines remain.
35
+ - v10 derives card-level `totalBeforeModifiers` from all backend modifiers,
36
+ including negative modifiers rendered as dedicated booking-card lines.
37
+ - Booking-card items omit the optional `modifiers` field when no modifier entries
38
+ are present instead of producing `modifiers: []`.
39
+
40
+ ## Migration Impact
41
+
42
+ - Existing supported search calls require no changes because `discount` remains
43
+ optional. v9 sites must keep flexible search unavailable and use `start`/`end`
44
+ period queries.
45
+ - v9 sites that inject `adults=1` only to make an empty query return results
46
+ should remove that workaround. Real occupancy filters remain supported.
47
+ - Search configuration, the public input type, and the discount schema are
48
+ unchanged. Runtime validation is stricter for unsupported v9 flexible-period
49
+ keys.
50
+ - Cross-backend sites can use one discount renderer for v9 and v10, while allowing
51
+ v9 to return at most one applied entry.
52
+ - Quote inputs and booking-card types are unchanged. Consumers may receive fewer
53
+ booking-card lines and may now receive the existing optional card-level
54
+ `totalBeforeModifiers` in additional v10 modifier cases. Do not rely on
55
+ zero-value rows to represent declined services.
56
+ - See `versions/2.12.0/MIGRATION.md`, `../../search.md`, and `../../quote.md`.
@@ -0,0 +1,194 @@
1
+ # Migration: 2.11.0 to 2.12.0
2
+
3
+ 2.12.0 adds optional discount information to priced legacy v9 search results,
4
+ normalizes empty quote booking-card lines across v9 and v10, and completes v10
5
+ card-level pre-modifier totals across all modifier presentation paths. It also
6
+ rejects unsupported v9 flexible-period searches before transport and restores
7
+ empty-query inventory browsing on v9. Existing supported calls remain valid
8
+ without changes.
9
+
10
+ ## 1. Reuse the Shared Discount Output
11
+
12
+ Legacy v9 now uses the same optional shape introduced for v10 in 2.11.0:
13
+
14
+ ```ts
15
+ type SearchDiscount = {
16
+ readonly formattedOriginalTotal: string;
17
+ readonly applied: readonly {
18
+ readonly label: string;
19
+ readonly formattedAmount: string;
20
+ }[];
21
+ };
22
+ ```
23
+
24
+ For exact-period results, read `discount` from the item:
25
+
26
+ ```ts
27
+ result.items[0]?.discount;
28
+ ```
29
+
30
+ For nearby suggestions, read it from the individual alternative period:
31
+
32
+ ```ts
33
+ result.alternatives?.[0]?.alternativePeriods[0]?.discount;
34
+ ```
35
+
36
+ ## 2. Understand the Legacy v9 Mapping
37
+
38
+ For priced v9 results:
39
+
40
+ - `calc.total` remains the final `formattedTotal`.
41
+ - `discount` is present only when `calc.oTotal` is greater than `calc.total`.
42
+ - `discount.formattedOriginalTotal` is formatted from `calc.oTotal`.
43
+ - A non-empty `calc.discountName` becomes the label of the single applied entry.
44
+ - The applied amount is the formatted negative difference
45
+ `calc.total - calc.oTotal`.
46
+ - If the backend supplies no usable discount name, `applied` is empty while the
47
+ formatted original total remains available.
48
+
49
+ The SDK omits `discount` when there is no final total or when the original total is
50
+ not greater than the final total.
51
+
52
+ ## 3. Account for Backend Detail Differences
53
+
54
+ v9 exposes one aggregated discount name and therefore returns at most one
55
+ `discount.applied` entry. v10 search can expose multiple `discount.applied`
56
+ entries. Consumers should render the array without assuming a fixed length.
57
+
58
+ Both backends return presentation-ready localized strings. Backend numeric amounts
59
+ and internal modifier keys are not part of the public output.
60
+
61
+ ## 4. Account for Booking-Card Cleanup
62
+
63
+ Quote booking cards on both backends now omit numeric zero-value lines without
64
+ subitems from the `other` section, matching the existing handling of included and
65
+ tax sections.
66
+
67
+ - A zero-only `other` section is omitted.
68
+ - A mixed `other` section retains its non-zero lines unchanged.
69
+ - Lines with subitems remain available because they still carry descriptive
70
+ content.
71
+
72
+ No required booking-card property was added and the public schema remains
73
+ source-compatible. Runtime output can contain fewer empty rows. Sites that used a
74
+ zero-value row to represent a declined service should use explicit selection or
75
+ service state instead of inferring that state from the price breakdown.
76
+
77
+ ## 5. Render v10 Quote Modifiers
78
+
79
+ On v10, an item at `bookingCardInformation.sections[].lines[].item` can include:
80
+
81
+ ```ts
82
+ {
83
+ modifiers?: readonly {
84
+ label: string;
85
+ amount: string;
86
+ }[];
87
+ totalBeforeModifiers?: string;
88
+ }
89
+ ```
90
+
91
+ The card can also include `bookingCardInformation.totalBeforeModifiers`.
92
+ `appliedCharge` and `total` are the final amounts after modifiers. The
93
+ corresponding `totalBeforeModifiers` is the formatted amount before modifiers and
94
+ is omitted when there is no non-zero net modifier effect. `modifiers` is omitted
95
+ when the item has none; entries with the same localized label are grouped and
96
+ their amounts are summed before formatting.
97
+
98
+ Included, tax, and other lines attach their adjustments to `item.modifiers`.
99
+ Negative modifiers from backend lines that do not map to those sections may
100
+ instead appear as dedicated booking-card lines. In 2.12.0, card-level
101
+ `totalBeforeModifiers` accounts for both forms. v9 quote cards omit these fields.
102
+
103
+ Example for `de-DE`:
104
+
105
+ ```json
106
+ {
107
+ "bookingCardInformation": {
108
+ "sections": [
109
+ {
110
+ "lines": [
111
+ {
112
+ "item": {
113
+ "position": "Inklusivpreis",
114
+ "appliedCharge": "1.554,00 €",
115
+ "modifiers": [
116
+ {
117
+ "label": "Frühbucher/Last-Minute",
118
+ "amount": "-140,00 €"
119
+ }
120
+ ],
121
+ "totalBeforeModifiers": "1.694,00 €"
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ ],
127
+ "total": "1.596,70 €",
128
+ "totalBeforeModifiers": "1.736,70 €"
129
+ }
130
+ }
131
+ ```
132
+
133
+ Do not assume a voucher appears as its own section line. Use
134
+ `quote.voucher.status` for voucher application status and the booking-card fields
135
+ for price presentation. To keep price arithmetic visible, render the pre-modifier
136
+ amount, modifier rows, and final amount separately. Whether to display or strike
137
+ through a reference price remains the consuming site's product and legal
138
+ decision.
139
+
140
+ ## 6. Keep Flexible Search Disabled on v9
141
+
142
+ No configuration or supported request migration is required. Legacy v9 now rejects
143
+ the unsupported flexible-period keys `month`, `dates`, `nights`, and `weekend`
144
+ before transport instead of silently returning an unpriced item list. Keep
145
+ flexible search unavailable on v9 sites and use fixed `start`/`end` period
146
+ queries. v10 flexible search is unchanged.
147
+
148
+ The rejection is a `CoreSDKError` with operation `v9.search` and occurs before a
149
+ GraphQL request is sent. The public `SearchSearchInput` type remains unchanged
150
+ because its `query` field is an opaque query string.
151
+
152
+ This release enriches v9 search output when its existing response contains
153
+ sufficient discount data, removes empty quote breakdown rows from both backends,
154
+ and can return the existing optional card-level `totalBeforeModifiers` in
155
+ additional v10 cases.
156
+
157
+ ## 7. Remove Dummy Occupancy from Empty v9 Searches
158
+
159
+ Legacy v9 now sends an empty backend-filter set as GraphQL `data: null` instead of
160
+ `data: []`. An empty query can therefore browse the first page of searchable
161
+ inventory under the configured rental scope:
162
+
163
+ ```ts
164
+ await sdk.live.search.search({
165
+ locale: "de-DE",
166
+ query: "",
167
+ });
168
+ ```
169
+
170
+ Remove workarounds that inject `adults=1` only to make an empty query return
171
+ results. Real occupancy, period, and non-empty backend filters keep their existing
172
+ mapping. Pagination and `limit` still apply, and an undated result does not assert
173
+ availability for a particular stay.
174
+
175
+ ## Recommended Verification
176
+
177
+ 1. Run a priced v9 exact-period search where the original total exceeds the final
178
+ total and verify the formatted values and label.
179
+ 2. Verify discounted v9 alternative periods independently.
180
+ 3. Run a v9 search without a discount and confirm existing rendering is unchanged.
181
+ 4. Verify a missing v9 discount name produces an empty `applied` array.
182
+ 5. Verify v9 rejects `month`, `dates`, `nights`, and `weekend` before transport.
183
+ 6. Run an empty v9 query and confirm it returns searchable inventory without a
184
+ dummy occupancy value.
185
+ 7. Recheck a discounted v10 search and confirm its existing multi-entry behavior
186
+ remains unchanged.
187
+ 8. Quote a v9 and v10 rental with a zero-value `other` service and confirm the
188
+ empty section is absent.
189
+ 9. Confirm a mixed `other` section retains only its non-zero lines.
190
+ 10. Quote a discounted v10 rental and render `item.modifiers`, item-level
191
+ `totalBeforeModifiers`, and card-level `totalBeforeModifiers`.
192
+ 11. Confirm a v9 quote continues to omit the modifier fields.
193
+ 12. Verify a v10 modifier rendered as a dedicated line still contributes to the
194
+ card-level `totalBeforeModifiers`.
@@ -121,6 +121,12 @@ The public output type is unchanged, but v10 search cards now reflect the REST p
121
121
  - `property` is the minimal `{ id, nameOrLabel }` shape. Hydrate `property.location`, `property.images`, or `property.address` from `sdk.static.rentals.getRentals(...)` when a search card needs them.
122
122
  - Exact-period matches are returned in `items` with `formattedTotal`; nearby suggestions are returned in root-level `alternatives`, unchanged.
123
123
 
124
+ Starting with 2.11.0, priced v10 items and alternative periods may also include
125
+ optional localized `discount` details. See `../../search.md`.
126
+
127
+ Starting with 2.12.0, legacy v9 maps the same optional shape from its aggregated
128
+ original total and discount name when the original total exceeds the final total.
129
+
124
130
  ## Backend Behavior
125
131
 
126
132
  - Fixed-period and flexible searches are priced by the REST backend; occupancy is required for priced searches.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v-office/website-sdk",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "Website-facing SDK facade backed by @v-office/sdk-core",
5
5
  "bin": {
6
6
  "website-sdk": "./dist/cli.mjs"
@@ -41,21 +41,23 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@graphql-typed-document-node/core": "3.2.0",
44
- "@v-office/sdk-core": "^1.10.0",
44
+ "@v-office/sdk-core": "^1.12.0",
45
45
  "effect": "4.0.0-beta.85",
46
- "graphql": "16.14.2",
46
+ "graphql": "17.0.2",
47
47
  "yaml": "^2.9.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@effect/language-service": "0.86.2",
51
- "@graphql-codegen/cli": "7.1.3",
52
- "@graphql-codegen/client-preset": "6.0.1",
53
- "@types/node": "26.0.0",
54
- "@typescript/native-preview": "7.0.0-dev.20260622.1",
55
- "oxfmt": "0.55.0",
56
- "oxlint": "1.70.0",
57
- "tsdown": "0.22.3",
58
- "typescript": "6.0.3"
50
+ "@effect/tsgo": "0.31.0",
51
+ "@graphql-codegen/cli": "7.2.0",
52
+ "@graphql-codegen/client-preset": "6.1.1",
53
+ "@types/node": "26.1.2",
54
+ "oxfmt": "0.62.0",
55
+ "oxlint": "1.77.0",
56
+ "tsdown": "0.22.14",
57
+ "typescript": "7.0.2"
58
+ },
59
+ "engines": {
60
+ "node": "^22.0.0 || ^24.0.0 || ^25.0.0 || >=26.0.0"
59
61
  },
60
62
  "scripts": {
61
63
  "p": "pnpm run playground:json",
@@ -72,7 +74,7 @@
72
74
  "lint:fix": "oxlint --fix .",
73
75
  "fmt": "oxfmt",
74
76
  "fmt:check": "oxfmt --check",
75
- "check": "pnpm run typecheck && pnpm run lint",
77
+ "check": "pnpm run typecheck && pnpm run lint && pnpm run fmt:check",
76
78
  "test": "pnpm run build && node --test test/*.test.mjs",
77
79
  "playground:custom-attributes": "pnpm run build && node --env-file=.env playground/custom-attributes.ts"
78
80
  }