@v-office/website-sdk 2.1.1 → 2.3.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,15 +1,30 @@
1
1
  #!/usr/bin/env node
2
- import { Pt as defineWebsiteSDKOptions, t as createWebsiteSDK } from "./client-xkXV7Nf-.mjs";
3
- import { Console, Effect, FileSystem, Layer, Option, Path, Stdio, Terminal } from "effect";
2
+ import { Pt as defineWebsiteSDKOptions, t as createWebsiteSDK } from "./client-DcBxVHpl.mjs";
3
+ import { Console, Effect, FileSystem, Layer, Option, Path, Schema, Stdio, Terminal } from "effect";
4
4
  import { Command, Flag } from "effect/unstable/cli";
5
5
  import { inspect } from "node:util";
6
6
  import { ChildProcessSpawner } from "effect/unstable/process";
7
7
  import { access, stat } from "node:fs/promises";
8
+ //#region src/cli/error.ts
9
+ var CLICheckFailed = class extends Error {
10
+ name = "CLICheckFailed";
11
+ constructor(message, options) {
12
+ super(message, options);
13
+ }
14
+ };
15
+ const toCLIError = (message, cause) => cause instanceof Error ? new CLICheckFailed(`${message}: ${cause.message}`, { cause }) : new CLICheckFailed(message, { cause });
16
+ //#endregion
17
+ //#region package.json
18
+ var version = "2.3.0";
19
+ //#endregion
8
20
  //#region src/cli/output.ts
9
- const toJson = (value) => JSON.stringify(value, (_key, item) => typeof item === "bigint" ? item.toString() : item, 2);
21
+ const toJson = (value) => Effect.try({
22
+ try: () => JSON.stringify(value, (_key, item) => typeof item === "bigint" ? item.toString() : item, 2) ?? "null",
23
+ catch: (cause) => toCLIError("Failed to serialize JSON output", cause)
24
+ });
10
25
  const printOutput = (root, value) => {
11
26
  switch (root.output) {
12
- case "json": return Console.log(toJson(value));
27
+ case "json": return toJson(value).pipe(Effect.flatMap(Console.log));
13
28
  case "pretty": return Console.log(inspect(value, {
14
29
  depth: null,
15
30
  colors: process.stdout.isTTY
@@ -30,15 +45,6 @@ const websiteSdkCommand = Command.make("website-sdk").pipe(Command.withDescripti
30
45
  output: Flag.choice("output", ["json", "pretty"]).pipe(Flag.withDescription("Output format."), Flag.withDefault("json"))
31
46
  }));
32
47
  //#endregion
33
- //#region src/cli/error.ts
34
- var CLICheckFailed = class extends Error {
35
- name = "CLICheckFailed";
36
- constructor(message, options) {
37
- super(message, options);
38
- }
39
- };
40
- const toCLIError = (message, cause) => cause instanceof Error ? new CLICheckFailed(`${message}: ${cause.message}`, { cause }) : new CLICheckFailed(message, { cause });
41
- //#endregion
42
48
  //#region src/cli/json.ts
43
49
  const parseJson = (text, source) => Effect.try({
44
50
  try: () => JSON.parse(text),
@@ -53,15 +59,37 @@ const readJsonFile = (path, label) => Effect.tryPromise({
53
59
  }).pipe(Effect.flatMap((text) => parseJson(text, path)));
54
60
  //#endregion
55
61
  //#region src/cli/config.ts
56
- const getRequiredEnv = (name) => Effect.sync(() => process.env[name]).pipe(Effect.flatMap((value) => value === void 0 || value.length === 0 ? Effect.fail(new CLICheckFailed(`Missing required environment variable ${name}.`)) : Effect.succeed(value)));
62
+ const NonBlankStringSchema = Schema.String.check(Schema.makeFilter((value) => value.trim().length > 0, { expected: "a non-blank string" }));
63
+ const WebsiteV9CLIConfigSchema = Schema.Struct({
64
+ backend: Schema.Literal("v9"),
65
+ graphqlUrl: NonBlankStringSchema,
66
+ apiKey: NonBlankStringSchema,
67
+ imageProxyBaseUrl: NonBlankStringSchema,
68
+ v0ApiBaseUrl: Schema.optionalKey(NonBlankStringSchema),
69
+ v1ApiBaseUrl: Schema.optionalKey(NonBlankStringSchema),
70
+ rentalDataAttributes: Schema.optionalKey(Schema.Array(NonBlankStringSchema))
71
+ });
72
+ const WebsiteV10CLIConfigSchema = Schema.Struct({
73
+ backend: Schema.optionalKey(Schema.Literal("v10")),
74
+ apiEndpoint: NonBlankStringSchema,
75
+ accessToken: NonBlankStringSchema,
76
+ imageBaseUrl: NonBlankStringSchema
77
+ });
78
+ const WebsiteSDKCLIConfigSchema = Schema.Union([WebsiteV9CLIConfigSchema, WebsiteV10CLIConfigSchema]);
79
+ const decodeCLIConfig = (input, path) => Schema.decodeUnknownEffect(WebsiteSDKCLIConfigSchema)(input).pipe(Effect.mapError((cause) => toCLIError(`Invalid Website SDK config file at ${path}. Expected a complete v9 or v10 config`, cause)));
80
+ const getRequiredEnv = (name) => Effect.sync(() => process.env[name]).pipe(Effect.flatMap((value) => value === void 0 || value.trim().length === 0 ? Effect.fail(new CLICheckFailed(`Missing required environment variable ${name}.`)) : Effect.succeed(value)));
57
81
  const readOptions = (root, fallback) => Option.isSome(root.options) ? readJsonFile(root.options.value, "Website SDK options").pipe(Effect.map(defineWebsiteSDKOptions)) : Effect.succeed(fallback);
58
- const fromConfigFile = (root) => Option.isSome(root.config) ? readJsonFile(root.config.value, "Website SDK config").pipe(Effect.flatMap((config) => {
59
- const configBackend = config.backend ?? "v10";
60
- return configBackend !== root.backend ? Effect.fail(new CLICheckFailed(`Config file backend "${configBackend}" does not match --backend ${root.backend}.`)) : readOptions(root, void 0).pipe(Effect.map((options) => ({
61
- config,
62
- options
63
- })));
64
- })) : fromEnvironment(root);
82
+ const fromConfigFile = (root) => {
83
+ if (Option.isNone(root.config)) return fromEnvironment(root);
84
+ const path = root.config.value;
85
+ return readJsonFile(path, "Website SDK config").pipe(Effect.flatMap((input) => decodeCLIConfig(input, path)), Effect.flatMap((config) => {
86
+ const configBackend = config.backend ?? "v10";
87
+ return configBackend !== root.backend ? Effect.fail(new CLICheckFailed(`Config file backend "${configBackend}" does not match --backend ${root.backend}.`)) : readOptions(root, void 0).pipe(Effect.map((options) => ({
88
+ config,
89
+ options
90
+ })));
91
+ }));
92
+ };
65
93
  const fromEnvironment = (root) => Effect.gen(function* () {
66
94
  const options = yield* readOptions(root, void 0);
67
95
  if (root.backend === "v9") {
@@ -107,13 +135,17 @@ const loadCLIConfig = fromConfigFile;
107
135
  //#region src/cli/sdk.ts
108
136
  const withSDK = (root, run) => Effect.gen(function* () {
109
137
  const { config, options } = yield* loadCLIConfig(root);
110
- return yield* Effect.tryPromise({
111
- try: () => run(createWebsiteSDK({
138
+ const sdk = yield* Effect.try({
139
+ try: () => createWebsiteSDK({
112
140
  config,
113
141
  ...options === void 0 ? {} : { options }
114
- })),
115
- catch: (cause) => toCLIError("SDK operation failed", cause)
142
+ }),
143
+ catch: (cause) => toCLIError("Failed to create SDK", cause)
116
144
  });
145
+ return yield* Effect.tryPromise({
146
+ try: () => run(sdk),
147
+ catch: (cause) => toCLIError("SDK operation failed", cause)
148
+ }).pipe(Effect.ensuring(Effect.promise(() => sdk.dispose())));
117
149
  });
118
150
  //#endregion
119
151
  //#region src/cli/commands/availability.ts
@@ -170,7 +202,7 @@ const env = Command.make("env", {}, Effect.fn(function* () {
170
202
  const configCommand = Command.make("config").pipe(Command.withDescription("Inspect CLI configuration."), Command.withSubcommands([show, env]));
171
203
  //#endregion
172
204
  //#region src/cli/commands/shared.ts
173
- const requireConfirmation = (root, confirmed, commandName) => confirmed ? Effect.void : Effect.fail(/* @__PURE__ */ new Error(`${commandName} can submit data to the configured backend. Re-run with --yes to confirm.`));
205
+ const requireConfirmation = (root, confirmed, commandName) => confirmed ? Effect.void : Effect.fail(new CLICheckFailed(`${commandName} can submit data to the configured backend. Re-run with --yes to confirm.`));
174
206
  //#endregion
175
207
  //#region src/cli/commands/live.ts
176
208
  const quoteInputFileFlag = Flag.file("quote-input", { mustExist: true }).pipe(Flag.withDescription("Path to a JSON QuoteQuoteInput file."));
@@ -200,13 +232,16 @@ const bookingBook = Command.make("book", {
200
232
  }, ({ contactInput, quoteInput, relativeRedirectUrl, yes }) => websiteSdkCommand.pipe(Effect.flatMap((root) => Effect.gen(function* () {
201
233
  yield* requireConfirmation(root, yes, "booking book");
202
234
  const [quoteRequest, contact] = yield* Effect.all([readJsonFile(quoteInput, "quote input"), readJsonFile(contactInput, "booking contact input")]);
203
- const quoteResult = yield* withSDK(root, (sdk) => sdk.live.quote.quote(quoteRequest));
204
- if (quoteResult.status !== "available") return yield* Effect.fail(new CLICheckFailed("Cannot create a booking because the quote is unavailable."));
205
- yield* printOutput(root, yield* withSDK(root, (sdk) => sdk.live.booking.book({
206
- quote: quoteResult.quote,
207
- contact,
208
- relativeRedirectUrl
209
- })));
235
+ const booking = yield* withSDK(root, async (sdk) => {
236
+ const quoteResult = await sdk.live.quote.quote(quoteRequest);
237
+ return quoteResult.status === "available" ? sdk.live.booking.book({
238
+ quote: quoteResult.quote,
239
+ contact,
240
+ relativeRedirectUrl
241
+ }) : void 0;
242
+ });
243
+ if (booking === void 0) return yield* Effect.fail(new CLICheckFailed("Cannot create a booking because the quote is unavailable."));
244
+ yield* printOutput(root, booking);
210
245
  })))).pipe(Command.withDescription("Create a booking from quote/contact JSON files after confirmation."), Command.withExamples([{
211
246
  command: "website-sdk --backend v10 booking book --quote-input ./quote-input.json --contact-input ./booking-contact.json --relative-redirect-url https://example.test/payment --yes",
212
247
  description: "Create a booking from a reusable quote input and booking contact fixture."
@@ -256,7 +291,7 @@ const cliCommand = websiteSdkCommand.pipe(Command.withSubcommands([
256
291
  availabilityCommand,
257
292
  ...liveCommands
258
293
  ]));
259
- const runCLI = Command.run(cliCommand, { version: "2.1.0" });
294
+ const runCLI = Command.run(cliCommand, { version });
260
295
  //#endregion
261
296
  //#region src/cli/node-services.ts
262
297
  const unsupported = (operation) => Effect.die(`Unsupported CLI platform operation: ${operation}`);
@@ -338,7 +373,7 @@ const terminal = Terminal.make({
338
373
  display: (text) => Effect.tryPromise({
339
374
  try: async () => {
340
375
  await new Promise((resolve, reject) => {
341
- process.stdout.write(text, (error) => error === void 0 ? resolve() : reject(error));
376
+ process.stdout.write(text, (error) => error == null ? resolve() : reject(error));
342
377
  });
343
378
  },
344
379
  catch: (cause) => cause
@@ -351,7 +386,7 @@ const NodeCLIServicesLive = Layer.mergeAll(FileSystemLive, Path.layer, TerminalL
351
386
  //#endregion
352
387
  //#region src/cli/main.ts
353
388
  Effect.runPromise(runCLI.pipe(Effect.provide(NodeCLIServicesLive))).catch((cause) => {
354
- console.error(cause);
389
+ console.error(cause instanceof CLICheckFailed ? cause.message : cause);
355
390
  process.exitCode = 1;
356
391
  });
357
392
  //#endregion
@@ -45,6 +45,12 @@ const submitFormPost = (option) => Effect.gen(function* () {
45
45
  form.method = option.method;
46
46
  form.action = option.action;
47
47
  if (form.style !== void 0) form.style.display = "none";
48
+ const submit = form.submit;
49
+ if (typeof submit !== "function") throw new CoreSDKError({
50
+ source: "core",
51
+ operation: "paymentSubmission",
52
+ message: "Form payment submission is unavailable in this browser environment."
53
+ });
48
54
  for (const [name, value] of Object.entries(option.fields)) {
49
55
  const input = document.createElement("input");
50
56
  input.type = "hidden";
@@ -53,7 +59,7 @@ const submitFormPost = (option) => Effect.gen(function* () {
53
59
  form.appendChild(input);
54
60
  }
55
61
  document.body.appendChild(form);
56
- form.submit?.();
62
+ submit.call(form);
57
63
  document.body.removeChild(form);
58
64
  },
59
65
  catch: toPaymentSubmissionError
@@ -79,6 +85,14 @@ const submitPaymentOptionEffect = (option) => {
79
85
  operation: "paymentSubmission",
80
86
  message: "Stripe Checkout requires a checkout session URL. The current payment option only contains session metadata."
81
87
  }));
88
+ default: {
89
+ const runtimeKind = option.kind;
90
+ return Effect.fail(new CoreSDKError({
91
+ source: "core",
92
+ operation: "paymentSubmission",
93
+ message: `Unsupported payment option kind "${String(runtimeKind)}".`
94
+ }));
95
+ }
82
96
  }
83
97
  };
84
98
  const submitPaymentOption = (option) => Effect.runPromise(submitPaymentOptionEffect(option));
@@ -937,6 +951,25 @@ const decodeV1OperationResponse = (operationId, raw) => {
937
951
  });
938
952
  };
939
953
  //#endregion
954
+ //#region src/legacy-v9/openapi/response-body.ts
955
+ const MAX_ERROR_BODY_PREVIEW_LENGTH = 8e3;
956
+ const readOpenApiResponseBody = (response, contentType) => {
957
+ if (contentType === void 0) return Effect.succeed(void 0);
958
+ return contentType.includes("application/json") ? response.json.pipe(Effect.catch(() => response.text)) : response.text;
959
+ };
960
+ const toTextErrorPreview = (body) => {
961
+ const withoutNoise = body.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<svg[\s\S]*?<\/svg>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&quot;/g, "\"").replace(/&#039;|&apos;/g, "'").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/\s+/g, " ").trim();
962
+ return withoutNoise.length === 0 ? body.slice(0, MAX_ERROR_BODY_PREVIEW_LENGTH) : withoutNoise;
963
+ };
964
+ const toOpenApiErrorRaw = (raw) => {
965
+ if (typeof raw !== "string" || raw.length <= MAX_ERROR_BODY_PREVIEW_LENGTH) return raw;
966
+ return {
967
+ preview: toTextErrorPreview(raw).slice(0, MAX_ERROR_BODY_PREVIEW_LENGTH),
968
+ truncated: true,
969
+ originalLength: raw.length
970
+ };
971
+ };
972
+ //#endregion
940
973
  //#region src/legacy-v9/openapi/v1-client.ts
941
974
  const V1OpenApiClientErrorBase = Data.TaggedError("V1OpenApiClientError");
942
975
  var V1OpenApiClientError = class extends V1OpenApiClientErrorBase {};
@@ -986,26 +1019,12 @@ const makeRequest$1 = (options, operationId, request) => Effect.gen(function* ()
986
1019
  })));
987
1020
  });
988
1021
  const readResponseBody$1 = (operationId, response, contentType) => {
989
- if (contentType === void 0) return Effect.succeed(void 0);
990
- return (contentType.includes("application/json") ? response.json.pipe(Effect.catch(() => response.text)) : response.text).pipe(Effect.mapError((cause) => new V1OpenApiClientError({
1022
+ return readOpenApiResponseBody(response, contentType).pipe(Effect.mapError((cause) => new V1OpenApiClientError({
991
1023
  operationId,
992
1024
  message: `Could not read response body for v1 operation "${operationId}".`,
993
1025
  cause
994
1026
  })));
995
1027
  };
996
- const MAX_ERROR_BODY_PREVIEW_LENGTH = 8e3;
997
- const toTextErrorPreview = (body) => {
998
- const withoutNoise = body.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<svg[\s\S]*?<\/svg>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&quot;/g, "\"").replace(/&#039;|&apos;/g, "'").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/\s+/g, " ").trim();
999
- return withoutNoise.length === 0 ? body.slice(0, MAX_ERROR_BODY_PREVIEW_LENGTH) : withoutNoise;
1000
- };
1001
- const toErrorRaw = (raw) => {
1002
- if (typeof raw !== "string" || raw.length <= MAX_ERROR_BODY_PREVIEW_LENGTH) return raw;
1003
- return {
1004
- preview: toTextErrorPreview(raw).slice(0, MAX_ERROR_BODY_PREVIEW_LENGTH),
1005
- truncated: true,
1006
- originalLength: raw.length
1007
- };
1008
- };
1009
1028
  var V1OpenApiClient = class extends Context.Service()("@v-office/website-sdk/legacy-v9/V1OpenApiClient") {};
1010
1029
  const makeV1OpenApiClientLive = (options) => Layer.effect(V1OpenApiClient, Effect.gen(function* () {
1011
1030
  const client = yield* HttpClient.HttpClient;
@@ -1023,7 +1042,7 @@ const makeV1OpenApiClientLive = (options) => Layer.effect(V1OpenApiClient, Effec
1023
1042
  operationId,
1024
1043
  message: `HTTP request failed for v1 operation "${operationId}" with status ${response.status}.`,
1025
1044
  status: response.status,
1026
- raw: toErrorRaw(raw)
1045
+ raw: toOpenApiErrorRaw(raw)
1027
1046
  }));
1028
1047
  return yield* decodeV1OperationResponse(operationId, raw).pipe(Effect.map((decoded) => ({
1029
1048
  data: decoded.data,
@@ -1078,7 +1097,7 @@ const toAvailabilityRestrictionsByDate = ({ availability }) => {
1078
1097
  //#region src/legacy-v9/parser/availability/to-first-calculation-date.ts
1079
1098
  const toFirstCalculationDate = ({ availability, now }) => {
1080
1099
  const today = DateTime.formatIsoDateUtc(now);
1081
- return [Object.keys(availability.caldata_beon).toSorted()[0], today].filter((date) => date != null).toSorted()[0];
1100
+ return [Object.keys(availability.caldata_beon).toSorted()[0], today].filter((date) => date != null).toSorted().at(-1);
1082
1101
  };
1083
1102
  //#endregion
1084
1103
  //#region translations/v9/de-DE/core.json
@@ -2112,9 +2131,9 @@ const V9_TRANSLATION_CATALOGS = {
2112
2131
  ]
2113
2132
  };
2114
2133
  const makeV9TranslationService = (overrides = {}) => {
2115
- const coreTranslation = Effect.gen(function* () {
2134
+ const coreTranslation = Effect.runSync(Effect.gen(function* () {
2116
2135
  return yield* TranslationService;
2117
- }).pipe(Effect.provide(makeTranslationLive(overrides)));
2136
+ }).pipe(Effect.provide(makeTranslationLive(overrides))));
2118
2137
  const mergedV9Catalogs = {
2119
2138
  "de-DE": Object.assign({}, ...V9_TRANSLATION_CATALOGS["de-DE"], overrides["de-DE"]),
2120
2139
  "en-US": Object.assign({}, ...V9_TRANSLATION_CATALOGS["en-US"], overrides["en-US"])
@@ -2122,7 +2141,7 @@ const makeV9TranslationService = (overrides = {}) => {
2122
2141
  return { translate: (locale, key, fallback = key) => {
2123
2142
  const v9Value = mergedV9Catalogs[locale][key];
2124
2143
  if (v9Value != null) return Effect.succeed(v9Value);
2125
- return coreTranslation.pipe(Effect.flatMap((core) => core.translate(locale, key, fallback)));
2144
+ return coreTranslation.translate(locale, key, fallback);
2126
2145
  } };
2127
2146
  };
2128
2147
  //#endregion
@@ -3161,8 +3180,7 @@ const makeRequest = (options, operationId, request) => Effect.gen(function* () {
3161
3180
  })));
3162
3181
  });
3163
3182
  const readResponseBody = (operationId, response, contentType) => {
3164
- if (contentType === void 0) return Effect.succeed(void 0);
3165
- return (contentType === "application/json" ? response.json : response.text).pipe(Effect.mapError((cause) => new V0OpenApiClientError({
3183
+ return readOpenApiResponseBody(response, contentType).pipe(Effect.mapError((cause) => new V0OpenApiClientError({
3166
3184
  operationId,
3167
3185
  message: `Could not read response body for v0 operation "${operationId}".`,
3168
3186
  cause
@@ -3185,7 +3203,7 @@ const makeV0OpenApiClientLive = (options) => Layer.effect(V0OpenApiClient, Effec
3185
3203
  operationId,
3186
3204
  message: `HTTP request failed for v0 operation "${operationId}" with status ${response.status}.`,
3187
3205
  status: response.status,
3188
- raw
3206
+ raw: toOpenApiErrorRaw(raw)
3189
3207
  }));
3190
3208
  return yield* decodeV0OperationResponse(operationId, raw).pipe(Effect.map((decoded) => ({
3191
3209
  data: decoded.data,
@@ -4256,7 +4274,7 @@ const refreshUrvInsuranceOptions = ({ quote, mode, translations, v0Client }) =>
4256
4274
  const result = yield* v0Client.execute("proxyVofficeAction", { query: {
4257
4275
  actionName: "getTravelInsurancePlans",
4258
4276
  data: JSON.stringify(data),
4259
- lang: input.locale
4277
+ lang: localeToLanguage(input.locale)
4260
4278
  } }).pipe(Effect.mapError(toInsuranceError("Failed to load URV insurance plans.")));
4261
4279
  const noInsuranceOption = yield* toNoInsuranceOptionFromTranslations({
4262
4280
  locale: input.locale,
@@ -4397,7 +4415,7 @@ const bookV9Insurance = ({ quote, bookingNumber, guestToken, v1Client }) => Effe
4397
4415
  //#region src/legacy-v9/live/quote.ts
4398
4416
  const loadQuoteRuntime = Effect.tryPromise({
4399
4417
  try: async () => {
4400
- return { toGuestQuote: (await import("./quote--25SMlYS.mjs")).toGuestQuote };
4418
+ return { toGuestQuote: (await import("./quote-_lvxNgiO.mjs")).toGuestQuote };
4401
4419
  },
4402
4420
  catch: (cause) => new CoreSDKError({
4403
4421
  source: "v10",
@@ -4415,17 +4433,9 @@ const toVofficeUnitId = (input) => {
4415
4433
  message: `Expected rentalId to be a vOffice unit ID, received "${input.rentalId}".`
4416
4434
  }));
4417
4435
  };
4418
- const quote = (client, v0Client, translations, input) => Effect.gen(function* () {
4436
+ const quote = (client, v0Client, translations, limitQuote, input) => Effect.gen(function* () {
4419
4437
  const unitId = yield* toVofficeUnitId(input);
4420
- const result = yield* (yield* makeMinIntervalLimiter({
4421
- interval: "1 second",
4422
- maxQueueSize: 5,
4423
- onQueueFull: (maxQueueSize) => new CoreSDKError({
4424
- source: "v10",
4425
- operation: "v9.quote",
4426
- message: `v9 quote rate limit queue is full (${maxQueueSize} total request(s)).`
4427
- })
4428
- }))(client.execute("getUnitQuotePrices", {
4438
+ const result = yield* limitQuote(client.execute("getUnitQuotePrices", {
4429
4439
  path: { voffice_unit: unitId },
4430
4440
  query: {
4431
4441
  lang: localeToLanguage(input.locale),
@@ -4435,6 +4445,7 @@ const quote = (client, v0Client, translations, input) => Effect.gen(function* ()
4435
4445
  children: input.occupancy.children,
4436
4446
  babies: input.occupancy.babies,
4437
4447
  pets: input.occupancy.pets,
4448
+ ...input.occupancy.childrenAges === void 0 ? {} : { childrenAges: input.occupancy.childrenAges.join(",") },
4438
4449
  ...input.voucher === void 0 ? {} : { voucherCode: input.voucher }
4439
4450
  }
4440
4451
  }).pipe(Effect.mapError((cause) => new CoreSDKError({
@@ -4459,6 +4470,15 @@ const quote = (client, v0Client, translations, input) => Effect.gen(function* ()
4459
4470
  });
4460
4471
  const makeV9QuoteApi = ({ config, options }) => {
4461
4472
  const translations = makeV9TranslationService(options.translationOverrides);
4473
+ const limitQuote = Effect.runSync(makeMinIntervalLimiter({
4474
+ interval: "1 second",
4475
+ maxQueueSize: 5,
4476
+ onQueueFull: (maxQueueSize) => new CoreSDKError({
4477
+ source: "v10",
4478
+ operation: "v9.quote",
4479
+ message: `v9 quote rate limit queue is full (${maxQueueSize} total request(s)).`
4480
+ })
4481
+ }));
4462
4482
  const openApiClientsLive = Layer.mergeAll(makeV0OpenApiClientFetchLive({
4463
4483
  apiKey: config.apiKey,
4464
4484
  ...config.v0ApiBaseUrl === void 0 ? {} : { baseUrl: config.v0ApiBaseUrl }
@@ -4479,7 +4499,7 @@ const makeV9QuoteApi = ({ config, options }) => {
4479
4499
  v1Client: clients.v1Client
4480
4500
  });
4481
4501
  return {
4482
- quote: (input) => withClients(({ v0Client, v1Client }) => quote(v1Client, v0Client, translations, input)),
4502
+ quote: (input) => withClients(({ v0Client, v1Client }) => quote(v1Client, v0Client, translations, limitQuote, input)),
4483
4503
  addAdditionalService: ({ quote, id }) => withClients((clients) => withGuestQuoteInsuranceRefresh({
4484
4504
  result: addGuestQuoteAdditionalServiceSelection({
4485
4505
  quote,
@@ -4591,26 +4611,41 @@ const makeV9GraphQLClient = (config) => ({ execute: (document, variables) => Eff
4591
4611
  const toCustomAttributeRentalDataAttributes = (definitions) => definitions.flatMap((definition) => definition.source === "customAttribute" && definition.key.startsWith("p_") ? [definition.key] : []);
4592
4612
  //#endregion
4593
4613
  //#region src/legacy-v9/rental-scope.ts
4594
- const toV9PropertyId = (scope) => {
4595
- if (scope.propertyId == null) return void 0;
4596
- const propertyId = Number(scope.propertyId);
4597
- return Number.isInteger(propertyId) ? propertyId : void 0;
4614
+ const toV9PropertyScope = (scope) => {
4615
+ if (scope.propertyId == null) return { kind: "absent" };
4616
+ const configuredPropertyId = scope.propertyId.trim();
4617
+ if (configuredPropertyId.length === 0) return { kind: "invalid" };
4618
+ const propertyId = Number(configuredPropertyId);
4619
+ return Number.isInteger(propertyId) ? {
4620
+ kind: "valid",
4621
+ propertyId
4622
+ } : { kind: "invalid" };
4623
+ };
4624
+ const validateV9RentalScope = (scope) => {
4625
+ if (toV9PropertyScope(scope).kind !== "invalid") return;
4626
+ throw new CoreSDKError({
4627
+ source: "v10",
4628
+ operation: "v9.config",
4629
+ message: `Expected rentalScope.propertyId to be a vOffice property ID, received "${scope.propertyId}".`
4630
+ });
4598
4631
  };
4599
4632
  const filterV9RentalsByScope = (rentals, scope) => {
4600
- const propertyId = toV9PropertyId(scope);
4601
- if (propertyId == null) return rentals;
4602
- return rentals.filter((rental) => rental.voffice_facility_id === propertyId);
4633
+ const propertyScope = toV9PropertyScope(scope);
4634
+ if (propertyScope.kind === "absent") return rentals;
4635
+ if (propertyScope.kind === "invalid") return [];
4636
+ return rentals.filter((rental) => rental.voffice_facility_id === propertyScope.propertyId);
4603
4637
  };
4604
4638
  const applyV9RentalScopeToSearchQueryInput = (input, scope) => {
4605
- const propertyId = toV9PropertyId(scope);
4606
- if (propertyId == null) return input;
4639
+ const propertyScope = toV9PropertyScope(scope);
4640
+ if (propertyScope.kind === "absent") return input;
4641
+ if (propertyScope.kind === "invalid") return void 0;
4607
4642
  return {
4608
4643
  ...input,
4609
4644
  vofficeData: {
4610
4645
  ...input.vofficeData,
4611
4646
  filter: {
4612
4647
  ...input.vofficeData?.filter,
4613
- falicityid: propertyId
4648
+ falicityid: propertyScope.propertyId
4614
4649
  }
4615
4650
  }
4616
4651
  };
@@ -4635,7 +4670,7 @@ const parseV9SearchCursor = (cursor) => Effect.gen(function* () {
4635
4670
  return page;
4636
4671
  });
4637
4672
  const loadV9SearchRuntime = Effect.tryPromise({
4638
- try: () => import("./search-8iCC0Nel.mjs"),
4673
+ try: () => import("./search-CnE272WG.mjs"),
4639
4674
  catch: (cause) => new CoreSDKError({
4640
4675
  source: "v10",
4641
4676
  operation: "v9.search.runtime",
@@ -4671,6 +4706,12 @@ const makeV9SearchApi = ({ config, options }) => {
4671
4706
  query: input.query
4672
4707
  });
4673
4708
  const scopedQueryInput = applyV9RentalScopeToSearchQueryInput(queryInput, options.rentalScope);
4709
+ if (scopedQueryInput === void 0) return {
4710
+ items: [],
4711
+ appliedFilters,
4712
+ unusedFilterKeys,
4713
+ pageInfo: { hasNextPage: false }
4714
+ };
4674
4715
  const page = input.cursor === void 0 ? 1 : yield* parseV9SearchCursor(input.cursor);
4675
4716
  const data = yield* graphql.execute(searchQuery, {
4676
4717
  first: input.limit ?? DEFAULT_SEARCH_LIMIT,
@@ -4977,7 +5018,7 @@ const DEFAULT_RENTAL_FEEDBACK_DATA_ATTRIBUTES = [
4977
5018
  "avgRating"
4978
5019
  ];
4979
5020
  const loadV9RentalsRuntime = Effect.tryPromise({
4980
- try: () => import("./rentals-DCKUaLnB.mjs"),
5021
+ try: () => import("./rentals-Lw1qUKIj.mjs"),
4981
5022
  catch: (cause) => new CoreSDKError({
4982
5023
  source: "v10",
4983
5024
  operation: "v9.rentals.runtime",
@@ -5029,30 +5070,32 @@ const makeV9RentalsApi = ({ config, options }) => {
5029
5070
  function createWebsiteSDK({ config, options }) {
5030
5071
  const normalizedOptions = normalizeWebsiteSDKOptions(options);
5031
5072
  if (config.backend === "v9") {
5073
+ const v9Options = toV9Options(normalizedOptions);
5074
+ validateV9RentalScope(v9Options.rentalScope);
5032
5075
  const rentals = makeV9RentalsApi({
5033
5076
  config,
5034
- options: toV9Options(normalizedOptions)
5077
+ options: v9Options
5035
5078
  });
5036
- const filter = makeV9FilterApi({ options: toV9Options(normalizedOptions) });
5079
+ const filter = makeV9FilterApi({ options: v9Options });
5037
5080
  const search = makeV9SearchApi({
5038
5081
  config,
5039
- options: toV9Options(normalizedOptions)
5082
+ options: v9Options
5040
5083
  });
5041
5084
  const availability = makeV9AvailabilityApi({
5042
5085
  config,
5043
- options: toV9Options(normalizedOptions)
5086
+ options: v9Options
5044
5087
  });
5045
5088
  const quote = makeV9QuoteApi({
5046
5089
  config,
5047
- options: toV9Options(normalizedOptions)
5090
+ options: v9Options
5048
5091
  });
5049
5092
  const booking = makeV9BookingApi({
5050
5093
  config,
5051
- options: toV9Options(normalizedOptions)
5094
+ options: v9Options
5052
5095
  });
5053
5096
  const contact = makeV9ContactApi({
5054
5097
  config,
5055
- options: toV9Options(normalizedOptions)
5098
+ options: v9Options
5056
5099
  });
5057
5100
  return {
5058
5101
  backend: "v9",
package/dist/index.d.mts CHANGED
@@ -6419,9 +6419,7 @@ type OperationParameters<TOperation extends V1OpenApiOperationId> = operations[T
6419
6419
  type OperationPathParameters<TOperation extends V1OpenApiOperationId> = OperationParameters<TOperation> extends {
6420
6420
  readonly path: infer Path;
6421
6421
  } ? Path : never;
6422
- type OperationQueryParameters<TOperation extends V1OpenApiOperationId> = OperationParameters<TOperation> extends {
6423
- readonly query: infer Query;
6424
- } ? Query : never;
6422
+ type OperationQueryParameters<TOperation extends V1OpenApiOperationId> = "query" extends keyof OperationParameters<TOperation> ? NonNullable<OperationParameters<TOperation>["query"]> : never;
6425
6423
  type OperationJsonBody<TOperation extends V1OpenApiOperationId> = operations[TOperation] extends {
6426
6424
  readonly requestBody: {
6427
6425
  readonly content: {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as SetupResponseSchema, A as ErgoPolicyNumberRequestSchema, At as selectInsurancePaymentEffect, B as QuotePricesResponseSchema, C as ErgoAddressSchema, Ct as getStartDateSelectedAvailabilityEffect, D as ErgoCreatePreContractRequestSchema, Dt as searchEffect, E as ErgoCommonFieldsSchema, Et as removeAdditionalServiceEffect, F as OnOfficeUnitSchema, G as RegionListResponseSchema, H as QuoteServiceSchema, I as PaymentScheduleItemSchema, J as ServiceBeonDataSchema, K as RoomImageSchema, L as PaymentScheduleSchema, M as ErgoTripAndCustomerRequestSchema, Mt as submitPaymentOption, N as FacilityListResponseSchema, Nt as submitPaymentOptionEffect, O as ErgoPersonSchema, Ot as selectCancellationPolicyEffect, P as OnOfficeUnitCollectionResponseSchema, Pt as defineWebsiteSDKOptions, Q as SetupDataSchema, R as QuoteLineSchema, S as DocumentTypeSchema, St as getRentalsEffect, T as ErgoBookRequestSchema, Tt as quoteEffect, U as RawObjectResponseSchema, V as QuoteSchema, W as RawVofficeObjectSchema, X as ServiceLimitSchema, Y as ServiceImageSchema, Z as ServiceListResponseSchema, _ as DocumentResourceResponseSchema, _t as bookInsuranceEffect, a as makeV0OpenApiClientFetchLive, at as UnitIdsResponseSchema, b as DocumentStatusUpdateRequestSchema, bt as getFiltersEffect, c as V1OpenApiClientError, ct as UnitOfferSchema, d as ApiEnvelopeBaseSchema, dt as V1_BASE_URL, et as TileCollectionResponseSchema, f as CalendarDaySchema, ft as V1_OPERATIONS, g as DocumentCollectionResponseSchema, gt as bookEffect, h as CustomerUnitSummarySchema, ht as addAdditionalServiceEffect, i as V0OpenApiClientError, it as TravelInsuranceBookingStoreRequestSchema, j as ErgoReadPreContractRequestSchema, jt as submitContactEffect, k as ErgoPlanSearchRequestSchema, kt as selectInsuranceEffect, l as makeV1OpenApiClientFetchLive, lt as UnitResponseSchema, m as CurrentMemberResponseSchema, mt as decodeV1OperationResponse, nt as TileTagSchema, o as makeV0OpenApiClientLive, ot as UnitListItemSchema, p as CalendarResponseSchema, pt as VideoResponseSchema, q as SearchPropertiesResponseSchema, r as V0OpenApiClient, rt as TravelInsuranceBookingSchema, s as V1OpenApiClient, st as UnitListResponseSchema, t as createWebsiteSDK, tt as TileSchema, u as makeV1OpenApiClientLive, ut as UnitServicePriceSchema, v as DocumentResourceSchema, vt as clearAdditionalServicesEffect, w as ErgoBankSchema, wt as getTermsAndPrivacyPolicyEffect, x as DocumentSummarySchema, xt as getInitialAvailabilityEffect, y as DocumentStatusSchema, yt as createInsurancePreContractEffect, z as QuotePricesPayloadSchema } from "./client-xkXV7Nf-.mjs";
1
+ import { $ as SetupResponseSchema, A as ErgoPolicyNumberRequestSchema, At as selectInsurancePaymentEffect, B as QuotePricesResponseSchema, C as ErgoAddressSchema, Ct as getStartDateSelectedAvailabilityEffect, D as ErgoCreatePreContractRequestSchema, Dt as searchEffect, E as ErgoCommonFieldsSchema, Et as removeAdditionalServiceEffect, F as OnOfficeUnitSchema, G as RegionListResponseSchema, H as QuoteServiceSchema, I as PaymentScheduleItemSchema, J as ServiceBeonDataSchema, K as RoomImageSchema, L as PaymentScheduleSchema, M as ErgoTripAndCustomerRequestSchema, Mt as submitPaymentOption, N as FacilityListResponseSchema, Nt as submitPaymentOptionEffect, O as ErgoPersonSchema, Ot as selectCancellationPolicyEffect, P as OnOfficeUnitCollectionResponseSchema, Pt as defineWebsiteSDKOptions, Q as SetupDataSchema, R as QuoteLineSchema, S as DocumentTypeSchema, St as getRentalsEffect, T as ErgoBookRequestSchema, Tt as quoteEffect, U as RawObjectResponseSchema, V as QuoteSchema, W as RawVofficeObjectSchema, X as ServiceLimitSchema, Y as ServiceImageSchema, Z as ServiceListResponseSchema, _ as DocumentResourceResponseSchema, _t as bookInsuranceEffect, a as makeV0OpenApiClientFetchLive, at as UnitIdsResponseSchema, b as DocumentStatusUpdateRequestSchema, bt as getFiltersEffect, c as V1OpenApiClientError, ct as UnitOfferSchema, d as ApiEnvelopeBaseSchema, dt as V1_BASE_URL, et as TileCollectionResponseSchema, f as CalendarDaySchema, ft as V1_OPERATIONS, g as DocumentCollectionResponseSchema, gt as bookEffect, h as CustomerUnitSummarySchema, ht as addAdditionalServiceEffect, i as V0OpenApiClientError, it as TravelInsuranceBookingStoreRequestSchema, j as ErgoReadPreContractRequestSchema, jt as submitContactEffect, k as ErgoPlanSearchRequestSchema, kt as selectInsuranceEffect, l as makeV1OpenApiClientFetchLive, lt as UnitResponseSchema, m as CurrentMemberResponseSchema, mt as decodeV1OperationResponse, nt as TileTagSchema, o as makeV0OpenApiClientLive, ot as UnitListItemSchema, p as CalendarResponseSchema, pt as VideoResponseSchema, q as SearchPropertiesResponseSchema, r as V0OpenApiClient, rt as TravelInsuranceBookingSchema, s as V1OpenApiClient, st as UnitListResponseSchema, t as createWebsiteSDK, tt as TileSchema, u as makeV1OpenApiClientLive, ut as UnitServicePriceSchema, v as DocumentResourceSchema, vt as clearAdditionalServicesEffect, w as ErgoBankSchema, wt as getTermsAndPrivacyPolicyEffect, x as DocumentSummarySchema, xt as getInitialAvailabilityEffect, y as DocumentStatusSchema, yt as createInsurancePreContractEffect, z as QuotePricesPayloadSchema } from "./client-DcBxVHpl.mjs";
2
2
  import { AdditionalServiceLimitExceeded, CoreSDKError, CoreSDKError as CMSError, GuestQuoteSchema, InvalidAdditionalServiceQuantity, LocaleSchema, SearchSearchInputSchema, SearchSearchOutputSchema, UnknownAdditionalService, validateContactSubmitInput } from "@v-office/sdk-core";
3
3
  //#region codegen/v9/heuristic-generation/public-api.ts
4
4
  const customDataAttribute = (name) => name;
@@ -163,15 +163,19 @@ const updateV9QuoteBackendContext = (context, selections) => {
163
163
  };
164
164
  };
165
165
  //#endregion
166
+ //#region src/legacy-v9/parser/quote/section-line-predicates.ts
167
+ const INCLUSIVE_SERVICE_SUMMARIES = /* @__PURE__ */ new Set(["SHOW", "ADD_NO_SHOW"]);
168
+ const isV9InclusiveQuoteLine = (line) => !isTaxLine(line) && (line.service?.type === "RENT" || INCLUSIVE_SERVICE_SUMMARIES.has(line.service?.summary ?? ""));
169
+ const isV9OtherQuoteLine = (line) => !isTaxLine(line) && !isV9InclusiveQuoteLine(line);
170
+ //#endregion
166
171
  //#region src/legacy-v9/parser/quote/to-sections-included.ts
167
- const isIncludedSubItem = (line) => line.service?.type === "RENT" || line.service?.summary === "SHOW";
168
172
  const toSectionsIncluded = ({ input: _input, guestQuoteResult, locale, translations }) => Effect.gen(function* () {
169
173
  const subItems = [];
170
174
  let total = 0;
171
175
  for (const line of guestQuoteResult?.mandatory ?? []) {
172
- if (isTaxLine(line)) continue;
176
+ if (!isV9InclusiveQuoteLine(line)) continue;
173
177
  total += getTotal(line);
174
- if (isIncludedSubItem(line)) {
178
+ if (line.service?.type === "RENT" || line.service?.summary === "SHOW") {
175
179
  const position = yield* toServiceLineLabel({
176
180
  serviceLine: line,
177
181
  locale,
@@ -193,11 +197,10 @@ const toSectionsIncluded = ({ input: _input, guestQuoteResult, locale, translati
193
197
  });
194
198
  //#endregion
195
199
  //#region src/legacy-v9/parser/quote/to-sections-other.ts
196
- const isOther = (line) => line.service?.type !== "RENT" && !isTaxLine(line) && line.service?.summary !== "ADD_NO_SHOW";
197
200
  const toSectionsOther = ({ input: _input, guestQuoteResult, locale, translations }) => Effect.gen(function* () {
198
201
  const lines = [];
199
202
  for (const line of guestQuoteResult?.mandatory ?? []) {
200
- if (!isOther(line)) continue;
203
+ if (!isV9OtherQuoteLine(line)) continue;
201
204
  const position = yield* toServiceLineLabel({
202
205
  serviceLine: line,
203
206
  locale,
@@ -1,4 +1,4 @@
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-CZYJeR1D.mjs";
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-CxWlq76f.mjs";
2
2
  import { makeTranslate, renderCustomAttributeHighlight, renderLabeledAttributeValue } from "@v-office/sdk-core";
3
3
  import { Effect } from "effect";
4
4
  //#region src/legacy-v9/parser/rentals/to-description.ts
@@ -1,5 +1,5 @@
1
- import { n as stable_filters_default } from "./client-xkXV7Nf-.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-CZYJeR1D.mjs";
1
+ import { n as stable_filters_default } from "./client-DcBxVHpl.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-CxWlq76f.mjs";
3
3
  import { CoreSDKError, STABLE_SEARCH_INPUTS, collectQueryParameters, daysBetweenLocalDates, expandCustomAttributeFilterCompositions, parseChildrenAges, parseOccupancyCount, parseQueryParameters, toCustomAttributeFilterLabel, toFormattedSearchPrice, toIsoDateFromPeriodQueryDate, toQueryString, toStableSearchInputBackendQueryKeys, toStableSearchInputParameterValues, toStableSearchInputQueryKeys, toUnusedFilterKeys } from "@v-office/sdk-core";
4
4
  import { Effect } from "effect";
5
5
  //#region src/legacy-v9/parser/search/input/filter/apply-voffice-filter-derived-basic-query-inputs.ts
@@ -128,6 +128,13 @@ const toBasicQueryInputs = ({ query, customAttributeFilterDefinitions, locale, t
128
128
  };
129
129
  };
130
130
  //#endregion
131
+ //#region src/legacy-v9/parser/search/input/search-input-error.ts
132
+ const failInvalidV9SearchInput = (message) => Effect.fail(new CoreSDKError({
133
+ source: "v10",
134
+ operation: "v9.search",
135
+ message
136
+ }));
137
+ //#endregion
131
138
  //#region src/legacy-v9/parser/search/input/occupancy/occupancy-query-keys.ts
132
139
  const OCCUPANCY_QUERY_KEYS = toStableSearchInputQueryKeys(STABLE_SEARCH_INPUTS.occupancy);
133
140
  //#endregion
@@ -145,17 +152,28 @@ const collectOccupancyQueryParameters = ({ query }) => {
145
152
  };
146
153
  //#endregion
147
154
  //#region src/legacy-v9/parser/search/input/occupancy/to-occupancy-input.ts
148
- const parseStableOccupancyCount = ({ key, occupancyParameters }) => Effect.gen(function* () {
149
- const values = toStableSearchInputParameterValues({
150
- key,
151
- group: STABLE_SEARCH_INPUTS.occupancy,
152
- parameters: occupancyParameters
155
+ const parsePetsValue = ({ key, values }) => Effect.gen(function* () {
156
+ if (values.length > 1) return yield* failInvalidV9SearchInput(`Expected at most one "${key}" query parameter.`);
157
+ const value = values[0];
158
+ if (value === void 0) return void 0;
159
+ const normalizedValue = value.toLowerCase();
160
+ if (normalizedValue === "" || normalizedValue === "true") return 1;
161
+ if (normalizedValue === "false") return 0;
162
+ const count = Number(value);
163
+ if (Number.isInteger(count) && count >= 0) return count;
164
+ return yield* failInvalidV9SearchInput(`Expected "${key}" to be a boolean flag or non-negative integer.`);
165
+ });
166
+ const parsePetsOccupancyCount = ({ occupancyParameters }) => Effect.gen(function* () {
167
+ const pets = yield* parsePetsValue({
168
+ key: "pets",
169
+ values: occupancyParameters.get("pets") ?? []
153
170
  });
154
- if (values.length === 0) return;
155
- return yield* parseOccupancyCount({
156
- key,
157
- values
171
+ const petsCount = yield* parsePetsValue({
172
+ key: "petsCount",
173
+ values: occupancyParameters.get("petsCount") ?? []
158
174
  });
175
+ if (pets != null && pets > 0 && petsCount != null && petsCount > 0) return yield* failInvalidV9SearchInput("Expected either \"pets\" or \"petsCount\", not both.");
176
+ return pets != null && pets > 0 ? pets : petsCount;
159
177
  });
160
178
  const toOccupancyInput = ({ query }) => Effect.gen(function* () {
161
179
  const { occupancyParameters, remainingParameters } = collectOccupancyQueryParameters({ query });
@@ -175,22 +193,13 @@ const toOccupancyInput = ({ query }) => Effect.gen(function* () {
175
193
  key: "babies",
176
194
  values: occupancyParameters.get("babies") ?? []
177
195
  })) ?? 0,
178
- petsCount: (yield* parseStableOccupancyCount({
179
- key: "petsCount",
180
- occupancyParameters
181
- })) ?? 0
196
+ petsCount: (yield* parsePetsOccupancyCount({ occupancyParameters })) ?? 0
182
197
  },
183
- remainingQuery: toQueryString(remainingParameters)
198
+ remainingQuery: toQueryString(remainingParameters),
199
+ unusedFilterKeys: childrenAges === void 0 ? [] : ["childrenAges"]
184
200
  };
185
201
  });
186
202
  //#endregion
187
- //#region src/legacy-v9/parser/search/input/search-input-error.ts
188
- const failInvalidV9SearchInput = (message) => Effect.fail(new CoreSDKError({
189
- source: "v10",
190
- operation: "v9.search",
191
- message
192
- }));
193
- //#endregion
194
203
  //#region src/legacy-v9/parser/search/input/period/period-query-keys.ts
195
204
  const PERIOD_QUERY_KEYS = toStableSearchInputBackendQueryKeys({
196
205
  backend: "v9",
@@ -320,7 +329,7 @@ const toQueryInput = ({ query, customAttributeFilterDefinitions, locale, transla
320
329
  },
321
330
  basicQueryInputs
322
331
  },
323
- unusedFilterKeys: toUnusedFilterKeys(basicQueryResult.remainingQuery)
332
+ unusedFilterKeys: [...occupancyResult?.unusedFilterKeys ?? [], ...toUnusedFilterKeys(basicQueryResult.remainingQuery)]
324
333
  };
325
334
  });
326
335
  //#endregion
@@ -5451,13 +5451,13 @@ const getDataImageFileName = (dataImage) => {
5451
5451
  if (name != null) return name;
5452
5452
  return dataImage.id != null ? `${dataImage.id}.jpg` : void 0;
5453
5453
  };
5454
- const normalizeDataImagePath = (dataImage, vofficeImages) => {
5454
+ const normalizeDataImagePath = (dataImage, referenceImages) => {
5455
5455
  const fileName = getDataImageFileName(dataImage);
5456
5456
  if (fileName == null) return void 0;
5457
- const matchingPath = vofficeImages.find((image) => getFileName(image.path ?? void 0) === fileName)?.path;
5457
+ const matchingPath = referenceImages.find((image) => getFileName(image.path ?? void 0) === fileName)?.path;
5458
5458
  if (matchingPath != null) return matchingPath;
5459
- const directoryName = vofficeImages.map((image) => image.path != null ? getDirectoryName(image.path) : void 0).find((path) => path != null);
5460
- return directoryName != null ? `${directoryName}/${fileName}` : void 0;
5459
+ const directoryName = referenceImages.map((image) => image.path != null ? getDirectoryName(image.path) : void 0).find((path) => path != null);
5460
+ return directoryName != null ? `${directoryName}/${fileName}` : fileName;
5461
5461
  };
5462
5462
  const pathMatchesName = (path, name) => path != null && name != null && (path === name || path.endsWith(`/${name}`));
5463
5463
  const entriesShareId = (left, right) => {
@@ -5497,17 +5497,19 @@ const mergeImageEntries = (entries) => {
5497
5497
  };
5498
5498
  const getImageEntries = (rental, data) => {
5499
5499
  const vofficeImages = rental.voffice_images ?? [];
5500
+ const vofficeRoomImages = rental.voffice_room_images ?? [];
5501
+ const referenceImages = [...vofficeImages, ...vofficeRoomImages];
5500
5502
  return [
5501
5503
  ...vofficeImages.map((image) => ({
5502
5504
  source: "voffice_images",
5503
5505
  image
5504
5506
  })),
5505
- ...(rental.voffice_room_images ?? []).map((image) => ({
5507
+ ...vofficeRoomImages.map((image) => ({
5506
5508
  source: "voffice_room_images",
5507
5509
  image
5508
5510
  })),
5509
5511
  ...(data.known.images ?? []).flatMap((dataImage) => {
5510
- const normalizedPath = normalizeDataImagePath(dataImage, vofficeImages);
5512
+ const normalizedPath = normalizeDataImagePath(dataImage, referenceImages);
5511
5513
  if (normalizedPath == null) return [];
5512
5514
  return [{
5513
5515
  source: "data_images",
@@ -5537,7 +5539,6 @@ const toImage = (imageProxyBaseUrl, entry, locale) => {
5537
5539
  return image;
5538
5540
  };
5539
5541
  const toImages = (imageProxyBaseUrl, rental, locale, data) => {
5540
- if (rental.voffice_images == null || rental.voffice_images.length === 0) return [];
5541
5542
  return mergeImageEntries(getImageEntries(rental, data)).map((entry) => toImage(imageProxyBaseUrl, entry, locale));
5542
5543
  };
5543
5544
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v-office/website-sdk",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "Website-facing SDK facade backed by @v-office/sdk-core",
5
5
  "bin": {
6
6
  "website-sdk": "./dist/cli.mjs"
@@ -37,11 +37,11 @@
37
37
  "./package.json": "./package.json"
38
38
  },
39
39
  "publishConfig": {
40
- "access": "public"
40
+ "access": "restricted"
41
41
  },
42
42
  "dependencies": {
43
43
  "@graphql-typed-document-node/core": "3.2.0",
44
- "@v-office/sdk-core": "^1.2.1",
44
+ "@v-office/sdk-core": "^1.4.0",
45
45
  "effect": "4.0.0-beta.85",
46
46
  "graphql": "16.14.2",
47
47
  "yaml": "^2.9.0"