@v-office/website-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +263 -0
  2. package/dist/cli.d.mts +1 -0
  3. package/dist/cli.mjs +337 -0
  4. package/dist/client-BbAfk-qa.mjs +33672 -0
  5. package/dist/custom-attribute-ChCbJKf_.mjs +54 -0
  6. package/dist/errors-2cuUGSvi.mjs +5 -0
  7. package/dist/index.d.mts +16130 -0
  8. package/dist/index.mjs +3 -0
  9. package/dist/operations-BanW36PK.mjs +12616 -0
  10. package/dist/operations-CHxEQ3jG.mjs +904 -0
  11. package/dist/parser-D6UAf8Ld.mjs +65 -0
  12. package/dist/quote-C3HZsFua.mjs +313 -0
  13. package/dist/quote-Vl6Nutaa.mjs +513 -0
  14. package/dist/rentals-BFmmp26v.mjs +323 -0
  15. package/dist/rentals-cQAg5TTW.mjs +403 -0
  16. package/dist/search-JqA3v_Fx.mjs +342 -0
  17. package/dist/search-filter-metadata-DZP0-Udc.mjs +4294 -0
  18. package/dist/to-rental-highlights-BcRa9Odv.mjs +402 -0
  19. package/dist/translations/shared/de-DE/availability.json +15 -0
  20. package/dist/translations/shared/de-DE/booking.json +15 -0
  21. package/dist/translations/shared/de-DE/insurance.json +18 -0
  22. package/dist/translations/shared/de-DE/quote.json +8 -0
  23. package/dist/translations/shared/de-DE/reviews.json +11 -0
  24. package/dist/translations/shared/en-US/availability.json +15 -0
  25. package/dist/translations/shared/en-US/booking.json +15 -0
  26. package/dist/translations/shared/en-US/insurance.json +18 -0
  27. package/dist/translations/shared/en-US/quote.json +8 -0
  28. package/dist/translations/shared/en-US/reviews.json +11 -0
  29. package/dist/translations/v10/de-DE/core.json +7027 -0
  30. package/dist/translations/v10/en-US/core.json +7027 -0
  31. package/dist/translations/v9/de-DE/core.json +4 -0
  32. package/dist/translations/v9/de-DE/filter.json +25 -0
  33. package/dist/translations/v9/de-DE/rental-attribute-categories.json +19 -0
  34. package/dist/translations/v9/de-DE/rental-attributes.json +451 -0
  35. package/dist/translations/v9/en-US/core.json +4 -0
  36. package/dist/translations/v9/en-US/filter.json +25 -0
  37. package/dist/translations/v9/en-US/rental-attribute-categories.json +19 -0
  38. package/dist/translations/v9/en-US/rental-attributes.json +451 -0
  39. package/package.json +90 -0
package/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # tsdown-starter
2
+
3
+ A starter for creating a TypeScript package.
4
+
5
+ ## Development
6
+
7
+ - Install dependencies:
8
+
9
+ ```bash
10
+ pnpm install
11
+ ```
12
+
13
+ - Run the unit tests:
14
+
15
+ ```bash
16
+ pnpm run test
17
+ ```
18
+
19
+ - Build the library:
20
+
21
+ ```bash
22
+ pnpm run build
23
+ ```
24
+
25
+ - Playground
26
+
27
+ ```bash
28
+ pnpm run playground
29
+ ```
30
+
31
+ ## CLI
32
+
33
+ The CLI exposes common SDK operations without editing `playground.ts` for each
34
+ manual test. In local development, use `pnpm cli -- ...`; when installed as a
35
+ package binary, use `cms-sdk ...`.
36
+
37
+ The CLI reads the same environment variables as `playground.ts`. For v9:
38
+
39
+ ```bash
40
+ HUB_GRAPHQL_URL
41
+ HUB_V1_API_BASE_URL
42
+ HUB_V0_API_BASE_URL
43
+ HUB_API_KEY
44
+ IMAGE_PROXY_BASE_URL
45
+ ```
46
+
47
+ For v10:
48
+
49
+ ```bash
50
+ VOFFICE_API_ENDPOINT
51
+ VOFFICE_LOCAL_DEV_ACCESS_TOKEN
52
+ VOFFICE_IMAGE_BASE_URL
53
+ ```
54
+
55
+ You can inspect the required environment variables and resolved config:
56
+
57
+ ```bash
58
+ pnpm cli --backend v9 config env
59
+ pnpm cli --backend v10 config show --output pretty
60
+ ```
61
+
62
+ You can also pass a complete parsed config or shared SDK options file:
63
+
64
+ ```bash
65
+ pnpm cli --backend v9 --config ./cms-config.v9.json config show
66
+ pnpm cli --backend v10 --options ./cms-options.json filters --locale de-DE
67
+ ```
68
+
69
+ ### Static Services
70
+
71
+ Fetch rentals:
72
+
73
+ ```bash
74
+ pnpm cli --backend v9 rentals --locale de-DE
75
+ pnpm cli --backend v10 rentals --locale de-DE
76
+ ```
77
+
78
+ Fetch filters:
79
+
80
+ ```bash
81
+ pnpm cli --backend v9 filters --locale de-DE
82
+ pnpm cli --backend v10 filters --locale de-DE
83
+ ```
84
+
85
+ ### Search Service
86
+
87
+ Run the same query shape used in `playground.ts`:
88
+
89
+ ```bash
90
+ pnpm cli --backend v9 search \
91
+ --locale de-DE \
92
+ --limit 2 \
93
+ --query "start=20-06-2026&end=27-06-2026&adults=2&childrenAges=5%2C13&babies=1&pets=1&wifi&bedrooms=6&bbq=true&youthgroups=on_request&beachdistance=200&scope=entire_home%2Cprivate_room&reet&complexFilter"
94
+ ```
95
+
96
+ Use the returned `pageInfo.nextCursor` for the next page:
97
+
98
+ ```bash
99
+ pnpm cli --backend v10 search \
100
+ --locale de-DE \
101
+ --limit 2 \
102
+ --cursor "<nextCursor>" \
103
+ --query "start=20-06-2026&end=27-06-2026&adults=2&childrenAges=5%2C13&babies=1&pets=1"
104
+ ```
105
+
106
+ ### Availability Service
107
+
108
+ Fetch the initial availability calendar:
109
+
110
+ ```bash
111
+ pnpm cli --backend v9 availability initial \
112
+ --locale de-DE \
113
+ --rental-id 134990 \
114
+ --calculate-from-date 2026-05-01 \
115
+ --calculate-through-date 2026-08-31
116
+ ```
117
+
118
+ Fetch availability after selecting a start date:
119
+
120
+ ```bash
121
+ pnpm cli --backend v9 availability start-date-selected \
122
+ --locale de-DE \
123
+ --rental-id 134990 \
124
+ --selected-start-date 2026-06-17 \
125
+ --calculate-from-date 2026-05-01 \
126
+ --calculate-through-date 2026-08-31
127
+ ```
128
+
129
+ The v10 playground rental can be used in the same commands:
130
+
131
+ ```bash
132
+ pnpm cli --backend v10 availability initial \
133
+ --locale de-DE \
134
+ --rental-id GMB2KczZnEXkdcF2LscQFX \
135
+ --calculate-from-date 2026-07-08 \
136
+ --calculate-through-date 2026-07-11
137
+ ```
138
+
139
+ ### Quote Service
140
+
141
+ Create a JSON fixture for a quote input, for example:
142
+
143
+ ```json
144
+ {
145
+ "locale": "de-DE",
146
+ "rentalId": "159521",
147
+ "period": {
148
+ "start": "2026-07-08",
149
+ "end": "2026-07-11"
150
+ },
151
+ "occupancy": {
152
+ "adults": 1,
153
+ "children": 0,
154
+ "babies": 0,
155
+ "pets": 0
156
+ },
157
+ "destinationCountryCode": "DE"
158
+ }
159
+ ```
160
+
161
+ Then run:
162
+
163
+ ```bash
164
+ pnpm cli --backend v9 quote --input ./quote-input.v9.json
165
+ ```
166
+
167
+ For the v10 playground rental with the voucher:
168
+
169
+ ```json
170
+ {
171
+ "locale": "de-DE",
172
+ "rentalId": "GMB2KczZnEXkdcF2LscQFX",
173
+ "period": {
174
+ "start": "2026-07-08",
175
+ "end": "2026-07-11"
176
+ },
177
+ "occupancy": {
178
+ "adults": 1,
179
+ "children": 0,
180
+ "babies": 0,
181
+ "pets": 0
182
+ },
183
+ "destinationCountryCode": "DE",
184
+ "voucher": "OFFER11"
185
+ }
186
+ ```
187
+
188
+ ```bash
189
+ pnpm cli --backend v10 quote --input ./quote-input.v10.json
190
+ ```
191
+
192
+ ### Contact Service
193
+
194
+ Contact submission is guarded by `--yes` because it sends data to the backend.
195
+ Create a JSON fixture like the playground input:
196
+
197
+ ```json
198
+ {
199
+ "title": "Herr",
200
+ "professionalTitle": "Dr.",
201
+ "forename": "Max",
202
+ "surname": "Mustermann",
203
+ "address": {
204
+ "streetAndHousenumber": "Musterstraße 42",
205
+ "postalCode": "11111",
206
+ "city": "Musterstadt",
207
+ "countryCode": "DE"
208
+ },
209
+ "email": "max.mustermann@muster.de",
210
+ "phone": "+49123456789",
211
+ "message": "Muster-Hinweis\nMuster"
212
+ }
213
+ ```
214
+
215
+ Then submit it explicitly:
216
+
217
+ ```bash
218
+ pnpm cli --backend v9 contact submit --input ./contact-input.json --yes
219
+ ```
220
+
221
+ ### Booking Service
222
+
223
+ Booking and quote-selection flows still need code for now because they operate
224
+ on a live `GuestQuote` class instance returned by the quote service. Keep using
225
+ `playground.ts` for booking, additional service selection, cancellation policy
226
+ selection, insurance selection, insurance pre-contracts, insurance payment
227
+ selection, and insurance booking until those flows have a stable JSON
228
+ serialization contract.
229
+
230
+ ## TODO
231
+
232
+ ### My-Stuff
233
+
234
+ - Payment (needs to be tested)
235
+
236
+ - Zahlung vor Ort (v9)
237
+
238
+ - Insurances
239
+
240
+ - Contact-Form (v10 -> Ticket)
241
+ - Contact-Form (v9 -> sendMessage)
242
+
243
+ - Auto-Regions (v10)
244
+
245
+ ### Waiting
246
+
247
+ #### Custom Attributes
248
+
249
+ - Suche mit Filter nach Custom-Attribute (boolean)
250
+ - v10 nicht implementiert - wird bald
251
+ - v9 müsste über Hub Filter-Schema gemacht werden
252
+ - unified surface
253
+
254
+ ### Optional
255
+
256
+ #### Filter-Counts
257
+
258
+ - In v10 müsste man ganze Suche triggern - nicht gut
259
+ - In v9 müsste über Hub Filter-Schema gemacht werden
260
+
261
+ ### getRentals
262
+
263
+ - highlightsPrioritization does not correctly work with e.g. maxPersons
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.mjs ADDED
@@ -0,0 +1,337 @@
1
+ #!/usr/bin/env node
2
+ import { n as defineCMSSDKOptions, t as createCMSSDKFromParsedConfig } from "./client-BbAfk-qa.mjs";
3
+ import { Console, Effect, FileSystem, Layer, Option, Path, Stdio, Terminal } from "effect";
4
+ import { Command, Flag } from "effect/unstable/cli";
5
+ import { inspect } from "node:util";
6
+ import { ChildProcessSpawner } from "effect/unstable/process";
7
+ import { access } from "node:fs/promises";
8
+ //#region src/cli/output.ts
9
+ const toJson = (value) => JSON.stringify(value, (_key, item) => typeof item === "bigint" ? item.toString() : item, 2);
10
+ const printOutput = (root, value) => {
11
+ switch (root.output) {
12
+ case "json": return Console.log(toJson(value));
13
+ case "pretty": return Console.log(inspect(value, {
14
+ depth: null,
15
+ colors: process.stdout.isTTY
16
+ }));
17
+ }
18
+ };
19
+ const printSuccess = (root) => printOutput(root, { ok: true });
20
+ //#endregion
21
+ //#region src/cli/root.ts
22
+ const backendFlag = Flag.choice("backend", ["v9", "v10"]).pipe(Flag.withDescription("Backend to use for this command."));
23
+ const localeFlag = Flag.choice("locale", ["de-DE", "en-US"]).pipe(Flag.withDescription("Locale used for localized SDK calls."), Flag.withDefault("de-DE"));
24
+ const inputFileFlag = Flag.file("input", { mustExist: true }).pipe(Flag.withDescription("Path to a JSON input file."));
25
+ const confirmFlag = Flag.boolean("yes").pipe(Flag.withDescription("Confirm execution of commands that submit or mutate backend state."));
26
+ const cmsSdkCommand = Command.make("cms-sdk").pipe(Command.withDescription("Run @v-office/cms-sdk operations from the command line."), Command.withSharedFlags({
27
+ backend: backendFlag,
28
+ config: Flag.file("config", { mustExist: true }).pipe(Flag.optional, Flag.withDescription("Path to a JSON ParsedCMSConfig file. Defaults to environment variables.")),
29
+ options: Flag.file("options", { mustExist: true }).pipe(Flag.optional, Flag.withDescription("Path to a JSON CMSOptions file passed through defineCMSSDKOptions.")),
30
+ output: Flag.choice("output", ["json", "pretty"]).pipe(Flag.withDescription("Output format."), Flag.withDefault("json"))
31
+ }));
32
+ //#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
+ //#region src/cli/json.ts
43
+ const parseJson = (text, source) => Effect.try({
44
+ try: () => JSON.parse(text),
45
+ catch: (cause) => toCLIError(`Failed to parse JSON from ${source}`, cause)
46
+ });
47
+ const readJsonFile = (path, label) => Effect.tryPromise({
48
+ try: async () => {
49
+ const { readFile } = await import("node:fs/promises");
50
+ return await readFile(path, "utf8");
51
+ },
52
+ catch: (cause) => toCLIError(`Failed to read ${label} file at ${path}`, cause)
53
+ }).pipe(Effect.flatMap((text) => parseJson(text, path)));
54
+ //#endregion
55
+ //#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)));
57
+ const readOptions = (root, fallback) => Option.isSome(root.options) ? readJsonFile(root.options.value, "CMS options").pipe(Effect.map(defineCMSSDKOptions)) : Effect.succeed(fallback);
58
+ const withOptions = (config, options) => {
59
+ if (options === void 0) return config;
60
+ switch (config.backend) {
61
+ case "v9": return {
62
+ ...config,
63
+ options
64
+ };
65
+ case "v10": return {
66
+ ...config,
67
+ options
68
+ };
69
+ }
70
+ };
71
+ const fromConfigFile = (root) => Option.isSome(root.config) ? readJsonFile(root.config.value, "CMS config").pipe(Effect.flatMap((config) => config.backend !== root.backend ? Effect.fail(new CLICheckFailed(`Config file backend "${config.backend}" does not match --backend ${root.backend}.`)) : readOptions(root, config.options).pipe(Effect.map((options) => ({
72
+ config: withOptions(config, options),
73
+ options
74
+ }))))) : fromEnvironment(root);
75
+ const fromEnvironment = (root) => Effect.gen(function* () {
76
+ const options = yield* readOptions(root, void 0);
77
+ if (root.backend === "v9") {
78
+ const v0ApiBaseUrl = process.env.HUB_V0_API_BASE_URL;
79
+ return {
80
+ config: {
81
+ backend: "v9",
82
+ v9: {
83
+ graphqlUrl: yield* getRequiredEnv("HUB_GRAPHQL_URL"),
84
+ v1ApiBaseUrl: yield* getRequiredEnv("HUB_V1_API_BASE_URL"),
85
+ ...v0ApiBaseUrl === void 0 || v0ApiBaseUrl.length === 0 ? {} : { v0ApiBaseUrl },
86
+ apiKey: yield* getRequiredEnv("HUB_API_KEY"),
87
+ imageProxyBaseUrl: yield* getRequiredEnv("IMAGE_PROXY_BASE_URL")
88
+ },
89
+ ...options === void 0 ? {} : { options }
90
+ },
91
+ options
92
+ };
93
+ }
94
+ return {
95
+ config: {
96
+ backend: "v10",
97
+ v10: {
98
+ apiEndpoint: yield* getRequiredEnv("VOFFICE_API_ENDPOINT"),
99
+ accessToken: yield* getRequiredEnv("VOFFICE_LOCAL_DEV_ACCESS_TOKEN"),
100
+ imageBaseUrl: yield* getRequiredEnv("VOFFICE_IMAGE_BASE_URL")
101
+ },
102
+ ...options === void 0 ? {} : { options }
103
+ },
104
+ options
105
+ };
106
+ });
107
+ const redactValue = (value) => {
108
+ if (value === void 0 || value.length === 0) return value;
109
+ return value.length <= 4 ? "****" : `${value.slice(0, 2)}****${value.slice(-2)}`;
110
+ };
111
+ const redactConfig = (config) => {
112
+ switch (config.backend) {
113
+ case "v9": return {
114
+ ...config,
115
+ v9: {
116
+ ...config.v9,
117
+ apiKey: redactValue(config.v9.apiKey) ?? ""
118
+ }
119
+ };
120
+ case "v10": return {
121
+ ...config,
122
+ v10: {
123
+ ...config.v10,
124
+ accessToken: redactValue(config.v10.accessToken) ?? ""
125
+ }
126
+ };
127
+ }
128
+ };
129
+ const loadCLIConfig = fromConfigFile;
130
+ //#endregion
131
+ //#region src/cli/sdk.ts
132
+ const withSDK = (root, run) => Effect.gen(function* () {
133
+ const { config } = yield* loadCLIConfig(root);
134
+ return yield* Effect.tryPromise({
135
+ try: async () => {
136
+ const sdk = createCMSSDKFromParsedConfig(config);
137
+ try {
138
+ return await run(sdk);
139
+ } finally {
140
+ await sdk.dispose();
141
+ }
142
+ },
143
+ catch: (cause) => toCLIError("SDK operation failed", cause)
144
+ });
145
+ });
146
+ //#endregion
147
+ //#region src/cli/commands/availability.ts
148
+ const rentalIdFlag = Flag.string("rental-id").pipe(Flag.withDescription("Backend rental identifier."));
149
+ const calculateFromDateFlag = Flag.string("calculate-from-date").pipe(Flag.withDescription("First local date to calculate, formatted as YYYY-MM-DD."));
150
+ const calculateThroughDateFlag = Flag.string("calculate-through-date").pipe(Flag.withDescription("Last local date to calculate, formatted as YYYY-MM-DD."));
151
+ const initial = Command.make("initial", {
152
+ locale: localeFlag,
153
+ rentalId: rentalIdFlag,
154
+ calculateFromDate: calculateFromDateFlag,
155
+ calculateThroughDate: calculateThroughDateFlag
156
+ }, (input) => cmsSdkCommand.pipe(Effect.flatMap((root) => withSDK(root, (sdk) => sdk.live.availability.getInitialAvailability(input)).pipe(Effect.flatMap((result) => printOutput(root, result)))))).pipe(Command.withDescription("Fetch initial availability for a rental."), Command.withExamples([{
157
+ command: "cms-sdk --backend v10 availability initial --rental-id 123 --calculate-from-date 2026-07-01 --calculate-through-date 2026-08-01",
158
+ description: "Fetch an initial availability calendar."
159
+ }]));
160
+ const startDateSelected = Command.make("start-date-selected", {
161
+ locale: localeFlag,
162
+ rentalId: rentalIdFlag,
163
+ selectedStartDate: Flag.string("selected-start-date").pipe(Flag.withDescription("Selected start date, formatted as YYYY-MM-DD.")),
164
+ calculateFromDate: calculateFromDateFlag,
165
+ calculateThroughDate: calculateThroughDateFlag
166
+ }, (input) => cmsSdkCommand.pipe(Effect.flatMap((root) => withSDK(root, (sdk) => sdk.live.availability.getStartDateSelectedAvailability(input)).pipe(Effect.flatMap((result) => printOutput(root, result)))))).pipe(Command.withDescription("Fetch availability after selecting a start date."), Command.withExamples([{
167
+ command: "cms-sdk --backend v9 availability start-date-selected --rental-id 123 --selected-start-date 2026-07-08 --calculate-from-date 2026-07-01 --calculate-through-date 2026-08-01",
168
+ description: "Fetch available end dates for a selected start date."
169
+ }]));
170
+ const availabilityCommand = Command.make("availability").pipe(Command.withDescription("Run live availability operations."), Command.withSubcommands([initial, startDateSelected]));
171
+ //#endregion
172
+ //#region src/cli/commands/config.ts
173
+ const show = Command.make("show", {}, Effect.fn(function* () {
174
+ const root = yield* cmsSdkCommand;
175
+ const resolved = yield* loadCLIConfig(root);
176
+ yield* printOutput(root, {
177
+ ...resolved,
178
+ config: redactConfig(resolved.config)
179
+ });
180
+ })).pipe(Command.withDescription("Show the resolved CLI config with secrets redacted."));
181
+ const env = Command.make("env", {}, Effect.fn(function* () {
182
+ const root = yield* cmsSdkCommand;
183
+ yield* printOutput(root, {
184
+ backend: root.backend,
185
+ required: root.backend === "v9" ? [
186
+ "HUB_GRAPHQL_URL",
187
+ "HUB_V1_API_BASE_URL",
188
+ "HUB_API_KEY",
189
+ "IMAGE_PROXY_BASE_URL"
190
+ ] : [
191
+ "VOFFICE_API_ENDPOINT",
192
+ "VOFFICE_LOCAL_DEV_ACCESS_TOKEN",
193
+ "VOFFICE_IMAGE_BASE_URL"
194
+ ],
195
+ optional: root.backend === "v9" ? ["HUB_V0_API_BASE_URL"] : []
196
+ });
197
+ })).pipe(Command.withDescription("List environment variables used by the selected backend."));
198
+ const configCommand = Command.make("config").pipe(Command.withDescription("Inspect CLI configuration."), Command.withSubcommands([show, env]));
199
+ //#endregion
200
+ //#region src/cli/commands/shared.ts
201
+ 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.`));
202
+ //#endregion
203
+ //#region src/cli/commands/live.ts
204
+ const quote = Command.make("quote", { input: inputFileFlag }, ({ input }) => cmsSdkCommand.pipe(Effect.flatMap((root) => readJsonFile(input, "quote input").pipe(Effect.flatMap((quoteInput) => withSDK(root, (sdk) => sdk.live.quote.quote(quoteInput))), Effect.flatMap((result) => printOutput(root, result)))))).pipe(Command.withDescription("Create a live guest quote from a JSON GuestQuoteInput file."), Command.withExamples([{
205
+ command: "cms-sdk --backend v10 quote --input ./quote-input.json",
206
+ description: "Create a quote using a reusable JSON fixture."
207
+ }]));
208
+ const contactSubmit = Command.make("submit", {
209
+ input: inputFileFlag,
210
+ yes: confirmFlag
211
+ }, ({ input, yes }) => cmsSdkCommand.pipe(Effect.flatMap((root) => Effect.gen(function* () {
212
+ yield* requireConfirmation(root, yes, "contact submit");
213
+ const contactInput = yield* readJsonFile(input, "contact input");
214
+ yield* withSDK(root, (sdk) => sdk.live.contact.submit(contactInput));
215
+ yield* printSuccess(root);
216
+ })))).pipe(Command.withDescription("Submit a contact request from a JSON ContactInput file."), Command.withExamples([{
217
+ command: "cms-sdk --backend v9 contact submit --input ./contact-input.json --yes",
218
+ description: "Submit a contact request after explicit confirmation."
219
+ }]));
220
+ const liveCommands = [quote, Command.make("contact").pipe(Command.withDescription("Run live contact operations."), Command.withSubcommands([contactSubmit]))];
221
+ const staticCommands = [
222
+ Command.make("filters", { locale: localeFlag }, ({ locale }) => cmsSdkCommand.pipe(Effect.flatMap((root) => withSDK(root, (sdk) => sdk.static.filter.getFilters({ locale })).pipe(Effect.flatMap((result) => printOutput(root, result)))))).pipe(Command.withDescription("Fetch unified filter definitions."), Command.withExamples([{
223
+ command: "cms-sdk --backend v10 filters --locale de-DE",
224
+ description: "Fetch v10 filter definitions as JSON."
225
+ }])),
226
+ Command.make("rentals", { locale: localeFlag }, ({ locale }) => cmsSdkCommand.pipe(Effect.flatMap((root) => withSDK(root, (sdk) => sdk.static.rentals.getRentals({ locale })).pipe(Effect.flatMap((result) => printOutput(root, result)))))).pipe(Command.withDescription("Fetch rental summaries."), Command.withExamples([{
227
+ command: "cms-sdk --backend v9 rentals --locale en-US",
228
+ description: "Fetch v9 rentals in English."
229
+ }])),
230
+ Command.make("search", {
231
+ locale: localeFlag,
232
+ query: Flag.string("query").pipe(Flag.withDescription("Search query string, for example \"city=munich&adults=2\".")),
233
+ limit: Flag.integer("limit").pipe(Flag.optional, Flag.withDescription("Optional positive result limit.")),
234
+ cursor: Flag.string("cursor").pipe(Flag.optional, Flag.withDescription("Optional pagination cursor.")),
235
+ rentalIdsIn: Flag.string("rental-ids-in").pipe(Flag.optional, Flag.withDescription("Optional comma-separated rental IDs to restrict v10 search results."))
236
+ }, ({ locale, query, limit, cursor, rentalIdsIn }) => cmsSdkCommand.pipe(Effect.flatMap((root) => {
237
+ const parsedRentalIdsIn = Option.isSome(rentalIdsIn) ? rentalIdsIn.value.split(",").map((rentalId) => rentalId.trim()).filter((rentalId) => rentalId.length > 0) : [];
238
+ const input = {
239
+ locale,
240
+ query,
241
+ ...parsedRentalIdsIn.length > 0 ? { rentalIdsIn: parsedRentalIdsIn } : {},
242
+ ...Option.isSome(limit) ? { limit: limit.value } : {},
243
+ ...Option.isSome(cursor) ? { cursor: cursor.value } : {}
244
+ };
245
+ return withSDK(root, (sdk) => sdk.live.search.search(input)).pipe(Effect.flatMap((result) => printOutput(root, result)));
246
+ }))).pipe(Command.withDescription("Run a live rental search."), Command.withExamples([{
247
+ command: "cms-sdk --backend v10 search --locale de-DE --query \"city=munich&adults=2\"",
248
+ description: "Search v10 rentals with a query string."
249
+ }]))
250
+ ];
251
+ //#endregion
252
+ //#region src/cli/index.ts
253
+ const cliCommand = cmsSdkCommand.pipe(Command.withSubcommands([
254
+ configCommand,
255
+ ...staticCommands,
256
+ availabilityCommand,
257
+ ...liveCommands
258
+ ]));
259
+ const runCLI = Command.run(cliCommand, { version: "1.0.0" });
260
+ //#endregion
261
+ //#region src/cli/node-services.ts
262
+ const unsupported = (operation) => Effect.die(`Unsupported CLI platform operation: ${operation}`);
263
+ const FileSystemLive = Layer.succeed(FileSystem.FileSystem, {
264
+ access: (path) => Effect.tryPromise({
265
+ try: async () => {
266
+ await access(path);
267
+ },
268
+ catch: (cause) => cause
269
+ }),
270
+ exists: (path) => Effect.promise(async () => {
271
+ try {
272
+ await access(path);
273
+ return true;
274
+ } catch {
275
+ return false;
276
+ }
277
+ }),
278
+ readFileString: (path, encoding = "utf8") => Effect.tryPromise({
279
+ try: async () => {
280
+ const { readFile } = await import("node:fs/promises");
281
+ return await readFile(path, encoding);
282
+ },
283
+ catch: (cause) => cause
284
+ }),
285
+ copy: () => unsupported("FileSystem.copy"),
286
+ copyFile: () => unsupported("FileSystem.copyFile"),
287
+ chmod: () => unsupported("FileSystem.chmod"),
288
+ chown: () => unsupported("FileSystem.chown"),
289
+ link: () => unsupported("FileSystem.link"),
290
+ makeDirectory: () => unsupported("FileSystem.makeDirectory"),
291
+ makeTempDirectory: () => unsupported("FileSystem.makeTempDirectory"),
292
+ makeTempDirectoryScoped: () => unsupported("FileSystem.makeTempDirectoryScoped"),
293
+ makeTempFile: () => unsupported("FileSystem.makeTempFile"),
294
+ makeTempFileScoped: () => unsupported("FileSystem.makeTempFileScoped"),
295
+ open: () => unsupported("FileSystem.open"),
296
+ readDirectory: () => unsupported("FileSystem.readDirectory"),
297
+ readFile: () => unsupported("FileSystem.readFile"),
298
+ readLink: () => unsupported("FileSystem.readLink"),
299
+ realPath: () => unsupported("FileSystem.realPath"),
300
+ remove: () => unsupported("FileSystem.remove"),
301
+ rename: () => unsupported("FileSystem.rename"),
302
+ sink: () => unsupported("FileSystem.sink"),
303
+ stat: () => unsupported("FileSystem.stat"),
304
+ stream: () => unsupported("FileSystem.stream"),
305
+ symlink: () => unsupported("FileSystem.symlink"),
306
+ truncate: () => unsupported("FileSystem.truncate"),
307
+ updateFile: () => unsupported("FileSystem.updateFile"),
308
+ watch: () => unsupported("FileSystem.watch"),
309
+ writeFile: () => unsupported("FileSystem.writeFile"),
310
+ writeFileString: () => unsupported("FileSystem.writeFileString")
311
+ });
312
+ const terminal = Terminal.make({
313
+ columns: Effect.sync(() => process.stdout.columns ?? 80),
314
+ rows: Effect.sync(() => process.stdout.rows ?? 24),
315
+ readInput: unsupported("Terminal.readInput"),
316
+ readLine: unsupported("Terminal.readLine"),
317
+ display: (text) => Effect.tryPromise({
318
+ try: async () => {
319
+ await new Promise((resolve, reject) => {
320
+ process.stdout.write(text, (error) => error === void 0 ? resolve() : reject(error));
321
+ });
322
+ },
323
+ catch: (cause) => cause
324
+ })
325
+ });
326
+ const TerminalLive = Layer.succeed(Terminal.Terminal, terminal);
327
+ const StdioLive = Stdio.layerTest({ args: Effect.sync(() => process.argv.slice(2)) });
328
+ const ChildProcessSpawnerLive = Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, ChildProcessSpawner.make(() => unsupported("ChildProcessSpawner.spawn")));
329
+ const NodeCLIServicesLive = Layer.mergeAll(FileSystemLive, Path.layer, TerminalLive, StdioLive, ChildProcessSpawnerLive);
330
+ //#endregion
331
+ //#region src/cli/main.ts
332
+ Effect.runPromise(runCLI.pipe(Effect.provide(NodeCLIServicesLive))).catch((cause) => {
333
+ console.error(cause);
334
+ process.exitCode = 1;
335
+ });
336
+ //#endregion
337
+ export {};