@v-office/website-sdk 2.16.2 → 2.17.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/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as createWebsiteSDK, zt as defineWebsiteSDKOptions } from "./client-CaZZGJAW.mjs";
2
+ import { t as createWebsiteSDK, zt as defineWebsiteSDKOptions } from "./client-ScO68LGg.mjs";
3
3
  import { SearchSearchSortSchema, defineCustomAttributesFromUnknown } from "@v-office/sdk-core";
4
4
  import { Console, Effect, FileSystem, Layer, Option, Path, Schema, Stdio, Terminal } from "effect";
5
5
  import { Command, Flag } from "effect/unstable/cli";
@@ -16,7 +16,7 @@ var CLICheckFailed = class extends Error {
16
16
  const toCLIError = (message, cause) => cause instanceof Error ? new CLICheckFailed(`${message}: ${cause.message}`, { cause }) : new CLICheckFailed(message, { cause });
17
17
  //#endregion
18
18
  //#region package.json
19
- var version = "2.16.2";
19
+ var version = "2.17.0";
20
20
  //#endregion
21
21
  //#region src/cli/output.ts
22
22
  const toJson = (value) => Effect.try({
@@ -1370,6 +1370,25 @@ const toFirstCalculationDate = ({ availability, now }) => {
1370
1370
  return [Object.keys(availability.caldata_beon).toSorted()[0], today].filter((date) => date != null).toSorted().at(-1);
1371
1371
  };
1372
1372
  //#endregion
1373
+ //#region src/legacy-v9/parser/availability/to-initial-availability-calendar-days.ts
1374
+ const applyV9CalendarPrices = ({ availability, calendarDays, locale, currency }) => {
1375
+ const result = { ...calendarDays };
1376
+ for (const [date, day] of Object.entries(calendarDays)) {
1377
+ const price = availability.caldata_beon[date]?.price;
1378
+ if (day.canBeStartDate && typeof price === "number" && currency !== void 0) result[date] = {
1379
+ ...day,
1380
+ formattedPrice: formatCurrency(price, locale, currency)
1381
+ };
1382
+ }
1383
+ return result;
1384
+ };
1385
+ const toInitialAvailabilityCalendarDays$1 = ({ availability, currency, ...input }) => toInitialAvailabilityCalendarDays(input).pipe(Effect.map((calendarDays) => applyV9CalendarPrices({
1386
+ availability,
1387
+ calendarDays,
1388
+ locale: input.input.locale,
1389
+ ...currency === void 0 ? {} : { currency }
1390
+ })));
1391
+ //#endregion
1373
1392
  //#region translations/v9/de-DE/core.json
1374
1393
  var core_default$1 = {
1375
1394
  "Rental.rentalType.option.HOUSE": "Haus",
@@ -2885,6 +2904,7 @@ const makeV9AvailabilityApi = ({ config, options }) => {
2885
2904
  apiKey: config.apiKey,
2886
2905
  ...config.v1ApiBaseUrl === void 0 ? {} : { baseUrl: config.v1ApiBaseUrl }
2887
2906
  });
2907
+ const bookingCurrencyByUnitId = /* @__PURE__ */ new Map();
2888
2908
  const loadAvailability = (input) => Effect.gen(function* () {
2889
2909
  const client = yield* V1OpenApiClient;
2890
2910
  const unitId = yield* toVofficeUnitId$2(input);
@@ -2898,21 +2918,36 @@ const makeV9AvailabilityApi = ({ config, options }) => {
2898
2918
  cause
2899
2919
  })))).data;
2900
2920
  }).pipe(Effect.provide(openApiClientLive));
2921
+ const loadBookingCurrency = (input) => Effect.gen(function* () {
2922
+ const client = yield* V1OpenApiClient;
2923
+ const unitId = yield* toVofficeUnitId$2(input);
2924
+ if (bookingCurrencyByUnitId.has(unitId)) return bookingCurrencyByUnitId.get(unitId);
2925
+ const result = yield* client.execute("getUnit", { path: { voffice_unit: unitId } }).pipe(Effect.match({
2926
+ onFailure: () => void 0,
2927
+ onSuccess: (result) => result
2928
+ }));
2929
+ if (result === void 0) return void 0;
2930
+ const currency = firstString(result.data.data.currency);
2931
+ bookingCurrencyByUnitId.set(unitId, currency);
2932
+ return currency;
2933
+ }).pipe(Effect.provide(openApiClientLive));
2901
2934
  return {
2902
2935
  getInitialAvailability: (input) => Effect.runPromise(Effect.gen(function* () {
2903
2936
  const now = yield* DateTime.now;
2904
- const availability = yield* loadAvailability(input);
2937
+ const [availability, currency] = yield* Effect.all([loadAvailability(input), loadBookingCurrency(input)]);
2905
2938
  const firstCalculationDate = toFirstCalculationDate({
2906
2939
  availability,
2907
2940
  now
2908
2941
  });
2909
2942
  const availabilityRestrictionsByDate = toAvailabilityRestrictionsByDate({ availability });
2910
2943
  return {
2911
- calendarDays: yield* toInitialAvailabilityCalendarDays({
2944
+ calendarDays: yield* toInitialAvailabilityCalendarDays$1({
2945
+ availability,
2912
2946
  input,
2913
2947
  firstCalculationDate,
2914
2948
  availabilityRestrictionsByDate,
2915
- translations
2949
+ translations,
2950
+ ...currency === void 0 ? {} : { currency }
2916
2951
  }),
2917
2952
  minPersons: null,
2918
2953
  maxPersons: null,
@@ -5477,7 +5512,7 @@ const parseV9SearchCursor = (cursor) => Effect.gen(function* () {
5477
5512
  return page;
5478
5513
  });
5479
5514
  const loadV9SearchRuntime = Effect.tryPromise({
5480
- try: () => import("./search-Dqiou4mc.mjs"),
5515
+ try: () => import("./search-zsnAfUtc.mjs"),
5481
5516
  catch: (cause) => new CoreSDKError({
5482
5517
  source: "v10",
5483
5518
  operation: "v9.search.runtime",
@@ -5844,7 +5879,7 @@ const DEFAULT_RENTAL_FEEDBACK_DATA_ATTRIBUTES = [
5844
5879
  "avgRating"
5845
5880
  ];
5846
5881
  const loadV9RentalsRuntime = Effect.tryPromise({
5847
- try: () => import("./rentals--cnnFS4I.mjs"),
5882
+ try: () => import("./rentals-BokBV-ze.mjs"),
5848
5883
  catch: (cause) => new CoreSDKError({
5849
5884
  source: "v10",
5850
5885
  operation: "v9.rentals.runtime",
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as ServiceBeonDataSchema, A as ErgoBookRequestSchema, At as quoteEffect, B as OnOfficeUnitSchema, C as DocumentResourceSchema, Ct as clearAdditionalServicesEffect, D as DocumentTypeSchema, Dt as getRentalsEffect, E as DocumentSummarySchema, Et as getInitialAvailabilityEffect, F as ErgoPolicyNumberRequestSchema, Ft as selectInsurancePaymentEffect, G as QuotePricesResponseSchema, H as PaymentScheduleSchema, I as ErgoReadPreContractRequestSchema, It as submitContactEffect, J as RawObjectResponseSchema, K as QuoteSchema, L as ErgoTripAndCustomerRequestSchema, Lt as submitPaymentOption, M as ErgoCreatePreContractRequestSchema, Mt as searchEffect, N as ErgoPersonSchema, Nt as selectCancellationPolicyEffect, O as ErgoAddressSchema, Ot as getStartDateSelectedAvailabilityEffect, P as ErgoPlanSearchRequestSchema, Pt as selectInsuranceEffect, Q as SearchPropertiesResponseSchema, R as FacilityListResponseSchema, Rt as submitPaymentOptionEffect, S as DocumentResourceResponseSchema, St as bookInsuranceEffect, T as DocumentStatusUpdateRequestSchema, Tt as getFiltersEffect, U as QuoteLineSchema, V as PaymentScheduleItemSchema, W as QuotePricesPayloadSchema, X as RegionListResponseSchema, Y as RawVofficeObjectSchema, Z as RoomImageSchema, _ as CalendarDaySchema, _t as V1_OPERATIONS, at as TileCollectionResponseSchema, b as CustomerUnitSummarySchema, bt as addAdditionalServiceEffect, c as V0OpenApiClient, ct as TravelInsuranceBookingSchema, d as makeV0OpenApiClientLive, dt as UnitListItemSchema, et as ServiceImageSchema, f as V1OpenApiClient, ft as UnitListResponseSchema, g as ApiEnvelopeBaseSchema, gt as V1_BASE_URL, h as makeV1OpenApiClientLive, ht as UnitServicePriceSchema, it as SetupResponseSchema, j as ErgoCommonFieldsSchema, jt as removeAdditionalServiceEffect, k as ErgoBankSchema, kt as getTermsAndPrivacyPolicyEffect, l as V0OpenApiClientError, lt as TravelInsuranceBookingStoreRequestSchema, m as makeV1OpenApiClientFetchLive, mt as UnitResponseSchema, nt as ServiceListResponseSchema, ot as TileSchema, p as V1OpenApiClientError, pt as UnitOfferSchema, q as QuoteServiceSchema, rt as SetupDataSchema, st as TileTagSchema, t as createWebsiteSDK, tt as ServiceLimitSchema, u as makeV0OpenApiClientFetchLive, ut as UnitIdsResponseSchema, v as CalendarResponseSchema, vt as VideoResponseSchema, w as DocumentStatusSchema, wt as createInsurancePreContractEffect, x as DocumentCollectionResponseSchema, xt as bookEffect, y as CurrentMemberResponseSchema, yt as decodeV1OperationResponse, z as OnOfficeUnitCollectionResponseSchema, zt as defineWebsiteSDKOptions } from "./client-CaZZGJAW.mjs";
1
+ import { $ as ServiceBeonDataSchema, A as ErgoBookRequestSchema, At as quoteEffect, B as OnOfficeUnitSchema, C as DocumentResourceSchema, Ct as clearAdditionalServicesEffect, D as DocumentTypeSchema, Dt as getRentalsEffect, E as DocumentSummarySchema, Et as getInitialAvailabilityEffect, F as ErgoPolicyNumberRequestSchema, Ft as selectInsurancePaymentEffect, G as QuotePricesResponseSchema, H as PaymentScheduleSchema, I as ErgoReadPreContractRequestSchema, It as submitContactEffect, J as RawObjectResponseSchema, K as QuoteSchema, L as ErgoTripAndCustomerRequestSchema, Lt as submitPaymentOption, M as ErgoCreatePreContractRequestSchema, Mt as searchEffect, N as ErgoPersonSchema, Nt as selectCancellationPolicyEffect, O as ErgoAddressSchema, Ot as getStartDateSelectedAvailabilityEffect, P as ErgoPlanSearchRequestSchema, Pt as selectInsuranceEffect, Q as SearchPropertiesResponseSchema, R as FacilityListResponseSchema, Rt as submitPaymentOptionEffect, S as DocumentResourceResponseSchema, St as bookInsuranceEffect, T as DocumentStatusUpdateRequestSchema, Tt as getFiltersEffect, U as QuoteLineSchema, V as PaymentScheduleItemSchema, W as QuotePricesPayloadSchema, X as RegionListResponseSchema, Y as RawVofficeObjectSchema, Z as RoomImageSchema, _ as CalendarDaySchema, _t as V1_OPERATIONS, at as TileCollectionResponseSchema, b as CustomerUnitSummarySchema, bt as addAdditionalServiceEffect, c as V0OpenApiClient, ct as TravelInsuranceBookingSchema, d as makeV0OpenApiClientLive, dt as UnitListItemSchema, et as ServiceImageSchema, f as V1OpenApiClient, ft as UnitListResponseSchema, g as ApiEnvelopeBaseSchema, gt as V1_BASE_URL, h as makeV1OpenApiClientLive, ht as UnitServicePriceSchema, it as SetupResponseSchema, j as ErgoCommonFieldsSchema, jt as removeAdditionalServiceEffect, k as ErgoBankSchema, kt as getTermsAndPrivacyPolicyEffect, l as V0OpenApiClientError, lt as TravelInsuranceBookingStoreRequestSchema, m as makeV1OpenApiClientFetchLive, mt as UnitResponseSchema, nt as ServiceListResponseSchema, ot as TileSchema, p as V1OpenApiClientError, pt as UnitOfferSchema, q as QuoteServiceSchema, rt as SetupDataSchema, st as TileTagSchema, t as createWebsiteSDK, tt as ServiceLimitSchema, u as makeV0OpenApiClientFetchLive, ut as UnitIdsResponseSchema, v as CalendarResponseSchema, vt as VideoResponseSchema, w as DocumentStatusSchema, wt as createInsurancePreContractEffect, x as DocumentCollectionResponseSchema, xt as bookEffect, y as CurrentMemberResponseSchema, yt as decodeV1OperationResponse, z as OnOfficeUnitCollectionResponseSchema, zt as defineWebsiteSDKOptions } from "./client-ScO68LGg.mjs";
2
2
  import { AdditionalServiceLimitExceeded, CoreSDKError, CoreSDKError as CMSError, CustomAttributeCatalogSchema, GuestQuoteSchema, InvalidAdditionalServiceQuantity, LocaleSchema, SearchSearchFieldOrderBySchema, SearchSearchFieldSortSchema, SearchSearchInputSchema, SearchSearchOutputSchema, SearchSearchPriceSortSchema, SearchSearchRandomSortSchema, SearchSearchRatingSortSchema, SearchSearchSortSchema, SearchSortDirectionSchema, UnknownAdditionalService, defineCustomAttributes, defineCustomAttributesFromUnknown, fetchCustomAttributeCatalog, parseCustomAttributeCatalog, validateContactSubmitInput } from "@v-office/sdk-core";
3
3
  //#region codegen/v9/heuristic-generation/public-api.ts
4
4
  const customDataAttribute = (name) => name;
@@ -4,6 +4,8 @@ This file is the versioned changelog index for the website SDK instructions.
4
4
 
5
5
  ## Versions
6
6
 
7
+ - `versions/2.17.0/CHANGELOG.md`: `@v-office/website-sdk` 2.17.0 release notes.
8
+ - `versions/2.16.3/CHANGELOG.md`: `@v-office/website-sdk` 2.16.3 release notes.
7
9
  - `versions/2.16.2/CHANGELOG.md`: `@v-office/website-sdk` 2.16.2 documentation release notes.
8
10
  - `versions/2.16.1/CHANGELOG.md`: `@v-office/website-sdk` 2.16.1 release notes.
9
11
  - `versions/2.16.0/CHANGELOG.md`: `@v-office/website-sdk` 2.16.0 release notes.
@@ -4,6 +4,8 @@ This file is the versioned migration index for the website SDK instructions.
4
4
 
5
5
  ## Available Guides
6
6
 
7
+ - `versions/2.17.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.16.3 to 2.17.0.
8
+ - `versions/2.16.3/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.16.2 to 2.16.3.
7
9
  - `versions/2.16.2/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.16.1 to 2.16.2.
8
10
  - `versions/2.16.1/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.16.0 to 2.16.1.
9
11
  - `versions/2.16.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.15.0 to 2.16.0.
@@ -1,7 +1,7 @@
1
1
  # Website SDK Instructions
2
2
 
3
3
  These instructions describe the current source targeted for
4
- `@v-office/website-sdk` 2.16.2. Package versions remain unchanged until the release
4
+ `@v-office/website-sdk` 2.17.0. Package versions remain unchanged until the release
5
5
  workflow performs the coordinated core and website bumps.
6
6
 
7
7
  Use this directory as the consumer-facing reference for the package:
@@ -18,6 +18,10 @@ Use this directory as the consumer-facing reference for the package:
18
18
  - `document-structured-json.md`: `sdk.static.documents.getTermsAndPrivacyPolicy` and structured document JSON rendering rules.
19
19
  - `CHANGELOG.md`: versioned changelog index.
20
20
  - `MIGRATION.md`: versioned migration index.
21
+ - `versions/2.17.0/`: 2.17.0 legacy-v9 calendar-day prices and structured
22
+ rooms, shared bed-amount expansion, and the 2.16.3-to-2.17.0 migration guide.
23
+ - `versions/2.16.3/`: 2.16.3 browser-origin resolution for relative payment
24
+ return URLs and the 2.16.2-to-2.16.3 migration guide.
21
25
  - `versions/2.16.2/`: 2.16.2 documentation release notes and migration guide.
22
26
  - `versions/2.16.1/`: 2.16.1 v10 multi-rate resolution restricted to rent rates,
23
27
  restored additional-service availability, and the 2.16.0-to-2.16.1 migration
@@ -100,5 +104,5 @@ website-sdk --backend v10 search --locale de-DE --query "adults=2" --sort '{"by"
100
104
  ```
101
105
 
102
106
  Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced
103
- in 2.0.0 and kept in 2.16.2. v10 config additionally requires `searchEndpoint` as
107
+ in 2.0.0 and kept in 2.17.0. v10 config additionally requires `searchEndpoint` as
104
108
  of 2.5.0.
@@ -96,6 +96,31 @@ Start-date-selected availability returns `Promise<StartDateSelectedAvailabilityO
96
96
 
97
97
  Common statuses include `available`, `before_today`, `check_in_not_allowed`, `no_valid_check_out_from_start`, `after_last_bookable_date`, and `unavailable`. End-date results can also return `same_day`, `not_after_selected_start`, `minimum_stay_not_met`, `check_out_not_allowed`, and range-crossing statuses.
98
98
 
99
+ ### Legacy v9 Calendar-Day Prices
100
+
101
+ From 2.17.0, v9 initial availability uses the numeric price supplied by the v1
102
+ calendar to populate `formattedPrice` on valid start dates. The value is already
103
+ localized and formatted in the rental unit's configured booking currency.
104
+ Render it directly rather than parsing or reformatting it.
105
+
106
+ `formattedPrice` remains `null` when the date cannot be used as a start date,
107
+ the date is unavailable, the v1 calendar supplies no numeric price, or the
108
+ unit's currency cannot be loaded. Start-date-selected availability does not
109
+ include calendar prices.
110
+
111
+ When no successful unit lookup is cached, a v9 initial-availability request loads
112
+ the calendar and a unit record. Successful unit responses are cached by unit ID
113
+ for the lifetime of the SDK instance, including responses without a currency.
114
+ Failed unit requests are not cached and are retried on the next call. A missing
115
+ currency or failed unit request does not fail availability; calendar prices
116
+ remain `null`.
117
+
118
+ No new configuration is required. The currency lookup uses the existing
119
+ `v1ApiBaseUrl` and `apiKey`.
120
+
121
+ See `versions/2.17.0/CHANGELOG.md` and
122
+ `versions/2.17.0/MIGRATION.md`.
123
+
99
124
  ## Configuration
100
125
 
101
126
  Use flat `WebsiteSDKConfig` files.
@@ -68,6 +68,10 @@ const booking = await sdk.live.booking.book({
68
68
  `kind: "OPTION"` creates an option booking on v10 and legacy v9. Omitting `kind`,
69
69
  or passing `"CONFIRMED"`, retains the existing confirmed-booking behavior.
70
70
  `relativeRedirectUrl` is used for online payment redirects after booking creation.
71
+ In a browser, the SDK resolves a relative value against `window.location.origin`
72
+ before initializing a v10 Adyen payment. An absolute HTTP or HTTPS URL is passed
73
+ through unchanged. Server-side callers must provide an absolute HTTP or HTTPS URL
74
+ because no browser origin is available.
71
75
 
72
76
  ## Output
73
77
 
@@ -167,7 +171,13 @@ try {
167
171
 
168
172
  ## Payment Return
169
173
 
170
- Online payment providers return the guest to a URL derived from `relativeRedirectUrl`. Stripe returns to that path with `payment=stripe&success=true` after payment and `payment=stripe&cancel=true` after cancellation, so the path must exist in your site and should read those query parameters.
174
+ Online payment providers return the guest to a URL derived from
175
+ `relativeRedirectUrl`. A relative value such as `/booking/payment-return` uses
176
+ the active browser origin, including `http://localhost:<port>` during local
177
+ development and the deployed website origin in production. Stripe returns to
178
+ that path with `payment=stripe&success=true` after payment and
179
+ `payment=stripe&cancel=true` after cancellation, so the path must exist in your
180
+ site and should read those query parameters.
171
181
 
172
182
  `relativeRedirectUrl` is supplied before the reservation exists, so the return URL cannot carry the booking number. Persist whatever the return page needs, for example in `sessionStorage`, before submitting a payment option.
173
183
 
@@ -123,6 +123,47 @@ list.
123
123
 
124
124
  See `versions/2.15.0/CHANGELOG.md` and `versions/2.15.0/MIGRATION.md`.
125
125
 
126
+ ### Structured Bed Quantities
127
+
128
+ From 2.17.0, both backends expand each source bed according to its `amount`.
129
+ Because the public bed shape has no quantity field, a source amount greater than
130
+ one is returned as that many identical entries in `rooms[].beds`. Each entry
131
+ represents one bed and must not be deduplicated by its visible value.
132
+
133
+ The v10 behavior is delivered by `@v-office/sdk-core`. Refresh the lockfile when
134
+ upgrading so the website package resolves the coordinated core version shipped
135
+ for 2.17.0.
136
+
137
+ ### Legacy v9 Structured Rooms
138
+
139
+ From 2.17.0, when vOffice supplies `roomDetails`, v9 rentals return them as
140
+ `rooms`. Room types, bed types, bed kinds, and supported room and bed attributes
141
+ are localized.
142
+
143
+ Supported per-room Boolean attributes are `hasPrivateBathroom`,
144
+ `roomDarkeningOption`, and `wardrobe`. Supported per-bed Boolean attributes are
145
+ `childrenOnly`, `extraLongBeds`, `openFootsection`, and `raisedBeds`.
146
+
147
+ Translation overrides use:
148
+
149
+ ```text
150
+ Room.type.option.<TYPE>
151
+ RoomAttributes.<attribute>.label
152
+ Bed.type.option.<TYPE>
153
+ Bed.kind.option.<KIND>
154
+ Bed.<attribute>.label
155
+ ```
156
+
157
+ Incomplete room details are handled independently: rooms without a type and beds
158
+ without a type or positive integer amount are omitted. The rental remains
159
+ available, and `rooms` is omitted when no usable room remains.
160
+
161
+ v9 rooms do not expose per-room descriptions, source `maxGuests`, a structured
162
+ bed amount, room IDs or room-image associations, or `roomSummary`.
163
+
164
+ See `versions/2.17.0/CHANGELOG.md` and
165
+ `versions/2.17.0/MIGRATION.md`.
166
+
126
167
  ### Legacy v9 Built-In Attributes
127
168
 
128
169
  From 2.14.0, built-in v9 property types and ordered option values come from the
@@ -0,0 +1,31 @@
1
+ # Changelog: 2.16.3
2
+
3
+ This release fixes v10 Adyen payment return URLs when booking is initiated with
4
+ a relative `relativeRedirectUrl`.
5
+
6
+ ## Fixed
7
+
8
+ - Relative payment return URLs are resolved against `window.location.origin`
9
+ before the SDK initializes an Adyen payment.
10
+ - Adyen receives the website's complete return URL instead of an unresolved
11
+ path that could be interpreted relative to the payment provider's origin.
12
+ - Local development can initialize test payments with return URLs such as
13
+ `http://localhost:4321/booking/payment-return`.
14
+
15
+ ## Unchanged
16
+
17
+ - `sdk.live.booking.book`, its input, and its output keep the same public types.
18
+ - Existing relative values such as `/booking/payment-return` require no code
19
+ changes.
20
+ - Absolute HTTP and HTTPS return URLs continue to be passed through unchanged.
21
+ - Legacy v9 booking and payment behavior is unchanged.
22
+
23
+ ## Compatibility
24
+
25
+ - No consumer code change is required. Upgrade the website SDK and refresh the
26
+ lockfile.
27
+ - Browser callers can keep supplying a site-relative return path. Server-side
28
+ callers must supply an absolute HTTP or HTTPS URL because no browser origin is
29
+ available.
30
+
31
+ See `versions/2.16.3/MIGRATION.md` and `../../booking.md`.
@@ -0,0 +1,51 @@
1
+ # Migration: 2.16.2 to 2.16.3
2
+
3
+ 2.16.3 fixes relative v10 Adyen payment return URLs through
4
+ `@v-office/sdk-core` 1.16.2. No public type, service call, input, or result shape
5
+ changes.
6
+
7
+ ## 1. Upgrade
8
+
9
+ ```sh
10
+ pnpm add @v-office/website-sdk@2.16.3
11
+ ```
12
+
13
+ Refresh the lockfile so the website SDK resolves `@v-office/sdk-core` 1.16.2.
14
+
15
+ ## 2. Keep the Existing Return Path
16
+
17
+ No application code change is required. Existing relative return paths continue
18
+ to work:
19
+
20
+ ```ts
21
+ const booking = await sdk.live.booking.book({
22
+ quote,
23
+ contact,
24
+ relativeRedirectUrl: "/booking/payment-return",
25
+ });
26
+ ```
27
+
28
+ In a browser, the SDK now resolves that path against `window.location.origin`.
29
+ For example:
30
+
31
+ ```text
32
+ http://localhost:4321 + /booking/payment-return
33
+ → http://localhost:4321/booking/payment-return
34
+ ```
35
+
36
+ Absolute HTTP and HTTPS return URLs remain unchanged. Server-side callers must
37
+ provide an absolute URL because `window.location.origin` is unavailable.
38
+
39
+ ## Required Consumer Work
40
+
41
+ None beyond upgrading the dependency and refreshing the lockfile.
42
+
43
+ ## Recommended Verification
44
+
45
+ 1. Start the website locally and create a deliberate v10 test booking.
46
+ 2. Confirm the Adyen initiation request contains the local website origin in its
47
+ `redirectUrl`.
48
+ 3. Complete or cancel the hosted test payment and confirm the browser returns to
49
+ the local payment-return page.
50
+ 4. Confirm a deployed website uses its own active origin for the same relative
51
+ return path.
@@ -0,0 +1,83 @@
1
+ # Changelog: 2.17.0
2
+
3
+ This release restores presentation-ready prices to legacy-v9 initial
4
+ availability calendars and exposes structured v9 room and bed data through the
5
+ shared rental contract. Bed quantities are represented consistently on v9 and
6
+ v10 by returning one public bed entry for each source bed amount.
7
+
8
+ ## Added
9
+
10
+ - Legacy-v9 static rentals expose source `roomDetails` through the existing
11
+ optional `rooms` field.
12
+ - v9 room output includes localized room types, bed types, bed kinds, and the
13
+ supported room and bed attributes supplied by vOffice.
14
+ - Supported v9 room attributes are `hasPrivateBathroom`,
15
+ `roomDarkeningOption`, and `wardrobe`. Supported bed attributes are
16
+ `childrenOnly`, `extraLongBeds`, `openFootsection`, and `raisedBeds`.
17
+
18
+ ## Fixed
19
+
20
+ - Legacy-v9 initial availability calendar days once again expose a localized
21
+ `formattedPrice` when the date is a valid start date and the v1 calendar
22
+ supplies a numeric price.
23
+ - Unavailable dates, dates that cannot be used as a start date, and dates without
24
+ a numeric source price continue to return `formattedPrice: null`.
25
+
26
+ ## Changed
27
+
28
+ - v9 calendar prices use the rental unit's configured booking currency. The SDK
29
+ loads that currency through the existing v1 unit endpoint and caches successful
30
+ unit lookups for the lifetime of the SDK instance.
31
+ - v9 calendar prices remain `null` when the unit currency is missing or cannot
32
+ be loaded. A currency lookup failure does not make the availability request
33
+ fail.
34
+ - A source bed with `amount: 3` is represented as three identical entries in
35
+ `rooms[].beds`. This applies to v9 and v10, whose shared public bed shape does
36
+ not contain a separate amount field.
37
+ - The first initial v9 availability request for a unit loads both its calendar
38
+ and unit record. Subsequent calls reuse a successfully loaded unit response,
39
+ including one that contains no currency. Failed unit requests are not cached
40
+ and are retried on the next call.
41
+ - v9 room data that does not satisfy the stricter generated heuristic schema is
42
+ read leniently from the preserved unknown data instead of being discarded as a
43
+ complete array.
44
+ - One incomplete v9 room or bed does not remove otherwise usable room data or
45
+ fail the rental.
46
+
47
+ ## Unchanged
48
+
49
+ - `sdk.live.availability.getInitialAvailability(input)` and
50
+ `sdk.static.rentals.getRentals({ locale })` keep their existing signatures and
51
+ public TypeScript contracts.
52
+ - No new v9 configuration value or endpoint is required. The existing
53
+ `v1ApiBaseUrl` and API key are used for the unit-currency lookup, and
54
+ `roomDetails` is already requested by the v9 rentals GraphQL operation.
55
+ - v10 initial-availability pricing is unchanged.
56
+ - Start-date-selected availability output does not gain calendar prices.
57
+ - v9 `rooms` remains optional and is omitted when vOffice supplies no usable
58
+ room details.
59
+ - v9 still does not expose per-room descriptions, source `maxGuests`, a
60
+ structured bed amount, room IDs or room-image associations, or `roomSummary`.
61
+ - Existing localized `attributes` and `highlights` remain available and are not
62
+ removed when structured rooms are present.
63
+
64
+ ## Compatibility
65
+
66
+ - Both features are additive for consumers that read selected fields.
67
+ - Complete v9 availability snapshots can now contain non-null `formattedPrice`
68
+ values on valid start dates.
69
+ - Complete v9 rental snapshots can now contain `rooms`.
70
+ - v9 and v10 snapshots or UIs that assumed one public bed entry per source bed
71
+ record must account for repeated entries when the source amount is greater
72
+ than one.
73
+ - Consumers must not deduplicate identical bed entries: repetition represents
74
+ the source quantity.
75
+ - The v10 bed expansion is delivered through `@v-office/sdk-core`. Refresh the
76
+ lockfile when upgrading so the website package resolves the coordinated core
77
+ version shipped for 2.17.0.
78
+ - A first initial-availability request for a v9 rental can perform one additional
79
+ v1 unit request for its currency. Applications with request-level mocks or
80
+ network assertions must account for it.
81
+
82
+ See `versions/2.17.0/MIGRATION.md`, `../../availability.md`, and
83
+ `../../rentals.md`.
@@ -0,0 +1,207 @@
1
+ # Migration: 2.16.3 to 2.17.0
2
+
3
+ 2.17.0 adds presentation-ready prices to legacy-v9 initial availability days
4
+ and structured rooms to legacy-v9 rental output. It also represents source bed
5
+ amounts consistently on v9 and v10 by returning one public entry per bed.
6
+
7
+ Service inputs, configuration, and public TypeScript shapes are unchanged.
8
+
9
+ ## 1. Render Initial Calendar Prices Directly
10
+
11
+ For v9, `getInitialAvailability` can now return a non-null `formattedPrice` on
12
+ valid start dates:
13
+
14
+ ```ts
15
+ const availability = await sdk.live.availability.getInitialAvailability(input);
16
+
17
+ for (const [date, day] of Object.entries(availability.calendarDays)) {
18
+ renderCalendarDay({
19
+ date,
20
+ status: day.status,
21
+ price: day.formattedPrice,
22
+ });
23
+ }
24
+ ```
25
+
26
+ `formattedPrice` is already localized for the input locale and formatted in the
27
+ unit's configured booking currency. Render it directly. Do not parse it for
28
+ arithmetic and do not replace its currency based on site assumptions.
29
+
30
+ The field remains `null` when:
31
+
32
+ - the day cannot be used as a start date
33
+ - the calendar marks the day unavailable
34
+ - the v1 calendar supplies no numeric price
35
+ - the unit currency is missing or cannot be loaded
36
+
37
+ ## 2. Account for the Unit-Currency Request
38
+
39
+ When no successful unit lookup is cached, a v9 initial-availability call loads
40
+ two resources:
41
+
42
+ 1. the v1 unit calendar
43
+ 2. the v1 unit record used to read its booking currency
44
+
45
+ Successful unit responses are cached by unit ID for the lifetime of the SDK
46
+ instance, including responses without a currency. Failed unit requests are not
47
+ cached and are retried by later initial-availability calls. A failed currency
48
+ request does not fail availability; calendar prices remain `null` instead.
49
+
50
+ Update HTTP mocks, request-count assertions, and service-worker fixtures that
51
+ previously expected only the calendar request.
52
+
53
+ No additional config is required. The lookup uses the existing `v1ApiBaseUrl`
54
+ and `apiKey`.
55
+
56
+ ## 3. Read Structured v9 Rooms
57
+
58
+ When vOffice supplies `roomDetails`, v9 rentals can now contain `rooms`:
59
+
60
+ ```ts
61
+ const rentals = await sdk.static.rentals.getRentals({ locale: "de-DE" });
62
+
63
+ for (const rental of rentals) {
64
+ for (const room of rental.rooms ?? []) {
65
+ renderRoomHeading(room.type);
66
+ renderRoomAttributes(room.attributes ?? []);
67
+
68
+ for (const bed of room.beds ?? []) {
69
+ renderBed({
70
+ type: bed.type,
71
+ kind: bed.kind,
72
+ attributes: bed.attributes ?? [],
73
+ });
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ Room types, bed types, bed kinds, and attributes are already localized. Render
80
+ them directly rather than comparing their visible text.
81
+
82
+ The v9 source supports these per-room Boolean attributes:
83
+
84
+ - `hasPrivateBathroom`
85
+ - `roomDarkeningOption`
86
+ - `wardrobe`
87
+
88
+ It supports these per-bed Boolean attributes:
89
+
90
+ - `childrenOnly`
91
+ - `extraLongBeds`
92
+ - `openFootsection`
93
+ - `raisedBeds`
94
+
95
+ Translation overrides use the same stable keys as v10:
96
+
97
+ ```text
98
+ Room.type.option.<TYPE>
99
+ RoomAttributes.<attribute>.label
100
+ Bed.type.option.<TYPE>
101
+ Bed.kind.option.<KIND>
102
+ Bed.<attribute>.label
103
+ ```
104
+
105
+ `rooms` remains optional. Keep an absent array valid when vOffice has no
106
+ structured room details or no usable room remains after validation.
107
+
108
+ ## 4. Treat Repeated Beds as Quantity
109
+
110
+ The public room-bed shape has no `amount` property. From 2.17.0, the SDK expands
111
+ the source amount:
112
+
113
+ ```ts
114
+ // Source
115
+ { type: "ORDINARY", kind: "SINGLE", amount: 2 }
116
+
117
+ // Public rooms[].beds
118
+ [
119
+ { type: "Standard bed", kind: "Single bed" },
120
+ { type: "Standard bed", kind: "Single bed" },
121
+ ]
122
+ ```
123
+
124
+ Each public entry represents one bed. Do not deduplicate entries merely because
125
+ their type, kind, and attributes are identical.
126
+
127
+ This behavior applies to both backends:
128
+
129
+ - v9 expands `roomDetails[].beds[].amount`
130
+ - v10 expands `rooms[].beds[].amount`
131
+
132
+ The v10 change is delivered by `@v-office/sdk-core`. Refresh the lockfile when
133
+ upgrading the website SDK so it resolves the coordinated core version shipped
134
+ for 2.17.0.
135
+
136
+ Invalid, missing, zero, negative, and fractional v9 amounts do not produce bed
137
+ entries. Other usable rooms and beds remain available.
138
+
139
+ ## 5. Keep Unsupported v9 Room Fields Optional
140
+
141
+ The v9 source does not provide every v10 room capability. In particular, public
142
+ v9 rooms do not currently expose:
143
+
144
+ - per-room descriptions
145
+ - source `maxGuests`
146
+ - a structured bed amount; source quantities are represented by repeated entries
147
+ - room IDs or room-image associations
148
+ - `roomSummary`
149
+
150
+ Do not derive these values from translated room labels or property-description
151
+ prose. Existing top-level `attributes` and `highlights` remain the supported
152
+ display sources for aggregate v9 facts such as bedrooms, bathrooms, rooms, and
153
+ sleeping accommodations.
154
+
155
+ ## 6. Update Snapshots and Complete-Object Assertions
156
+
157
+ Update expectations that previously assumed:
158
+
159
+ ```ts
160
+ day.formattedPrice === null;
161
+ rental.rooms === undefined;
162
+ room.beds?.length === sourceRoom.beds.length;
163
+ ```
164
+
165
+ New valid behavior includes:
166
+
167
+ ```ts
168
+ day.formattedPrice; // localized string on a priced, valid v9 start date
169
+ rental.rooms; // localized structured v9 rooms when roomDetails exists
170
+ room.beds?.length; // total expanded bed amount, not source record count
171
+ ```
172
+
173
+ Keep both `formattedPrice: null` and missing `rooms` valid because they still
174
+ represent legitimate backend data.
175
+
176
+ ## Required Consumer Work
177
+
178
+ Applications that use only selected fields and ignore the new output require no
179
+ code changes.
180
+
181
+ Applications that render or snapshot these areas should:
182
+
183
+ 1. Render `formattedPrice` directly when non-null.
184
+ 2. Account for the first v9 initial-availability currency request in mocks.
185
+ 3. Render `rental.rooms` as optional structured content.
186
+ 4. Treat every `rooms[].beds` entry as one bed and avoid value-based
187
+ deduplication.
188
+ 5. Refresh the lockfile so v10 resolves the coordinated core release.
189
+ 6. Update complete-output fixtures and snapshots.
190
+
191
+ ## Recommended Verification
192
+
193
+ 1. Load v9 initial availability for a non-EUR rental and confirm the configured
194
+ currency is used.
195
+ 2. Confirm a missing or failed currency lookup keeps calendar prices `null`
196
+ without failing availability.
197
+ 3. Confirm unavailable, non-start, and price-less dates retain
198
+ `formattedPrice: null`.
199
+ 4. Call initial availability twice for the same rental and confirm a successful
200
+ unit response is reused; confirm a failed unit request is retried.
201
+ 5. Fetch v9 rentals with populated `roomDetails` in both supported locales.
202
+ 6. Confirm room and bed labels are localized.
203
+ 7. Confirm a source bed amount of two produces two public bed entries on v9 and
204
+ v10.
205
+ 8. Confirm incomplete v9 rooms do not remove other usable rooms or fail the
206
+ rental.
207
+ 9. Confirm rentals without structured source rooms still omit `rooms`.