@voyant-travel/storefront 0.120.1

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 (126) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +231 -0
  3. package/dist/booking-intents.d.ts +42 -0
  4. package/dist/booking-intents.d.ts.map +1 -0
  5. package/dist/booking-intents.js +83 -0
  6. package/dist/customer-portal/index.d.ts +16 -0
  7. package/dist/customer-portal/index.d.ts.map +1 -0
  8. package/dist/customer-portal/index.js +23 -0
  9. package/dist/customer-portal/route-runtime.d.ts +16 -0
  10. package/dist/customer-portal/route-runtime.d.ts.map +1 -0
  11. package/dist/customer-portal/route-runtime.js +27 -0
  12. package/dist/customer-portal/routes-public.d.ts +1936 -0
  13. package/dist/customer-portal/routes-public.d.ts.map +1 -0
  14. package/dist/customer-portal/routes-public.js +165 -0
  15. package/dist/customer-portal/routes.d.ts +43 -0
  16. package/dist/customer-portal/routes.d.ts.map +1 -0
  17. package/dist/customer-portal/routes.js +17 -0
  18. package/dist/customer-portal/service-public-impl.d.ts +138 -0
  19. package/dist/customer-portal/service-public-impl.d.ts.map +1 -0
  20. package/dist/customer-portal/service-public-impl.js +1808 -0
  21. package/dist/customer-portal/service-public.d.ts +2 -0
  22. package/dist/customer-portal/service-public.d.ts.map +1 -0
  23. package/dist/customer-portal/service-public.js +1 -0
  24. package/dist/customer-portal/validation-public/bookings.d.ts +551 -0
  25. package/dist/customer-portal/validation-public/bookings.d.ts.map +1 -0
  26. package/dist/customer-portal/validation-public/bookings.js +132 -0
  27. package/dist/customer-portal/validation-public/common.d.ts +162 -0
  28. package/dist/customer-portal/validation-public/common.d.ts.map +1 -0
  29. package/dist/customer-portal/validation-public/common.js +139 -0
  30. package/dist/customer-portal/validation-public/profile.d.ts +749 -0
  31. package/dist/customer-portal/validation-public/profile.d.ts.map +1 -0
  32. package/dist/customer-portal/validation-public/profile.js +308 -0
  33. package/dist/customer-portal/validation-public.d.ts +3 -0
  34. package/dist/customer-portal/validation-public.d.ts.map +1 -0
  35. package/dist/customer-portal/validation-public.js +2 -0
  36. package/dist/guest-booking-guard.d.ts +24 -0
  37. package/dist/guest-booking-guard.d.ts.map +1 -0
  38. package/dist/guest-booking-guard.js +55 -0
  39. package/dist/index.d.ts +23 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +41 -0
  42. package/dist/product-extra-ref.d.ts +238 -0
  43. package/dist/product-extra-ref.d.ts.map +1 -0
  44. package/dist/product-extra-ref.js +22 -0
  45. package/dist/routes-admin.d.ts +220 -0
  46. package/dist/routes-admin.d.ts.map +1 -0
  47. package/dist/routes-admin.js +28 -0
  48. package/dist/routes-public.d.ts +1475 -0
  49. package/dist/routes-public.d.ts.map +1 -0
  50. package/dist/routes-public.js +362 -0
  51. package/dist/service-booking-session-bootstrap.d.ts +227 -0
  52. package/dist/service-booking-session-bootstrap.d.ts.map +1 -0
  53. package/dist/service-booking-session-bootstrap.js +287 -0
  54. package/dist/service-boundary-resource-sql.d.ts +18 -0
  55. package/dist/service-boundary-resource-sql.d.ts.map +1 -0
  56. package/dist/service-boundary-resource-sql.js +73 -0
  57. package/dist/service-boundary-sql.d.ts +103 -0
  58. package/dist/service-boundary-sql.d.ts.map +1 -0
  59. package/dist/service-boundary-sql.js +307 -0
  60. package/dist/service-departures-core.d.ts +41 -0
  61. package/dist/service-departures-core.d.ts.map +1 -0
  62. package/dist/service-departures-core.js +92 -0
  63. package/dist/service-departures-extensions.d.ts +46 -0
  64. package/dist/service-departures-extensions.d.ts.map +1 -0
  65. package/dist/service-departures-extensions.js +81 -0
  66. package/dist/service-departures-offers.d.ts +220 -0
  67. package/dist/service-departures-offers.d.ts.map +1 -0
  68. package/dist/service-departures-offers.js +177 -0
  69. package/dist/service-departures-price-preview.d.ts +306 -0
  70. package/dist/service-departures-price-preview.d.ts.map +1 -0
  71. package/dist/service-departures-price-preview.js +383 -0
  72. package/dist/service-departures-pricing-context.d.ts +115 -0
  73. package/dist/service-departures-pricing-context.d.ts.map +1 -0
  74. package/dist/service-departures-pricing-context.js +237 -0
  75. package/dist/service-departures-pricing.d.ts +5 -0
  76. package/dist/service-departures-pricing.d.ts.map +1 -0
  77. package/dist/service-departures-pricing.js +4 -0
  78. package/dist/service-departures.d.ts +192 -0
  79. package/dist/service-departures.d.ts.map +1 -0
  80. package/dist/service-departures.js +213 -0
  81. package/dist/service-intake.d.ts +130 -0
  82. package/dist/service-intake.d.ts.map +1 -0
  83. package/dist/service-intake.js +274 -0
  84. package/dist/service-transport-eligibility.d.ts +10 -0
  85. package/dist/service-transport-eligibility.d.ts.map +1 -0
  86. package/dist/service-transport-eligibility.js +198 -0
  87. package/dist/service.d.ts +1062 -0
  88. package/dist/service.d.ts.map +1 -0
  89. package/dist/service.js +332 -0
  90. package/dist/transport-eligibility.d.ts +4 -0
  91. package/dist/transport-eligibility.d.ts.map +1 -0
  92. package/dist/transport-eligibility.js +2 -0
  93. package/dist/validation/departures.d.ts +1669 -0
  94. package/dist/validation/departures.d.ts.map +1 -0
  95. package/dist/validation/departures.js +397 -0
  96. package/dist/validation/intake.d.ts +147 -0
  97. package/dist/validation/intake.d.ts.map +1 -0
  98. package/dist/validation/intake.js +69 -0
  99. package/dist/validation/offers.d.ts +340 -0
  100. package/dist/validation/offers.d.ts.map +1 -0
  101. package/dist/validation/offers.js +117 -0
  102. package/dist/validation-settings.d.ts +609 -0
  103. package/dist/validation-settings.d.ts.map +1 -0
  104. package/dist/validation-settings.js +235 -0
  105. package/dist/validation-transport-eligibility.d.ts +314 -0
  106. package/dist/validation-transport-eligibility.d.ts.map +1 -0
  107. package/dist/validation-transport-eligibility.js +97 -0
  108. package/dist/validation.d.ts +6 -0
  109. package/dist/validation.d.ts.map +1 -0
  110. package/dist/validation.js +4 -0
  111. package/dist/verification/index.d.ts +12 -0
  112. package/dist/verification/index.d.ts.map +1 -0
  113. package/dist/verification/index.js +18 -0
  114. package/dist/verification/routes-public.d.ts +121 -0
  115. package/dist/verification/routes-public.d.ts.map +1 -0
  116. package/dist/verification/routes-public.js +125 -0
  117. package/dist/verification/schema.d.ts +273 -0
  118. package/dist/verification/schema.d.ts.map +1 -0
  119. package/dist/verification/schema.js +50 -0
  120. package/dist/verification/service.d.ts +114 -0
  121. package/dist/verification/service.d.ts.map +1 -0
  122. package/dist/verification/service.js +283 -0
  123. package/dist/verification/validation.d.ts +98 -0
  124. package/dist/verification/validation.d.ts.map +1 -0
  125. package/dist/verification/validation.js +54 -0
  126. package/package.json +148 -0
@@ -0,0 +1,1475 @@
1
+ import { type VoyantBindings, type VoyantVariables } from "@voyant-travel/hono";
2
+ import type { Context } from "hono";
3
+ import { type StorefrontServiceOptions } from "./service.js";
4
+ export declare function departuresDocKey(productId: string, query: Record<string, unknown>): string;
5
+ /**
6
+ * Read-through KV cache for a departures payload. Best-effort: any KV
7
+ * failure (or a missing CACHE binding) degrades to the live query.
8
+ */
9
+ export declare function readThroughDepartures<T>(c: Context<Env>, key: string, compute: () => Promise<T>): Promise<T>;
10
+ type Env = {
11
+ Bindings: VoyantBindings;
12
+ Variables: {
13
+ userId?: string;
14
+ } & VoyantVariables;
15
+ };
16
+ export declare function createStorefrontPublicRoutes(options?: StorefrontServiceOptions): import("hono/hono-base").HonoBase<Env, {
17
+ "/settings": {
18
+ $get: {
19
+ input: {};
20
+ output: {
21
+ data: {
22
+ branding: {
23
+ logoUrl: string | null;
24
+ faviconUrl: string | null;
25
+ brandMarkUrl: string | null;
26
+ primaryColor: string | null;
27
+ accentColor: string | null;
28
+ supportedLanguages: string[];
29
+ };
30
+ support: {
31
+ email: string | null;
32
+ phone: string | null;
33
+ links: {
34
+ label: string;
35
+ url: string;
36
+ }[];
37
+ };
38
+ legal: {
39
+ termsUrl: string | null;
40
+ privacyUrl: string | null;
41
+ cancellationUrl: string | null;
42
+ defaultContractTemplateId: string | null;
43
+ };
44
+ localization: {
45
+ defaultLocale: string | null;
46
+ currencyDisplay: "symbol" | "name" | "code";
47
+ };
48
+ forms: {
49
+ billing: {
50
+ fields: {
51
+ key: string;
52
+ label: string;
53
+ type: "date" | "select" | "text" | "email" | "textarea" | "country" | "tel" | "checkbox";
54
+ required: boolean;
55
+ placeholder: string | null;
56
+ description: string | null;
57
+ autocomplete: string | null;
58
+ options: {
59
+ value: string;
60
+ label: string;
61
+ }[];
62
+ }[];
63
+ };
64
+ travelers: {
65
+ fields: {
66
+ key: string;
67
+ label: string;
68
+ type: "date" | "select" | "text" | "email" | "textarea" | "country" | "tel" | "checkbox";
69
+ required: boolean;
70
+ placeholder: string | null;
71
+ description: string | null;
72
+ autocomplete: string | null;
73
+ options: {
74
+ value: string;
75
+ label: string;
76
+ }[];
77
+ }[];
78
+ };
79
+ };
80
+ payment: {
81
+ defaultMethod: "voucher" | "bank_transfer" | "cash" | "invoice" | "card" | null;
82
+ methods: {
83
+ code: "voucher" | "bank_transfer" | "cash" | "invoice" | "card";
84
+ label: string;
85
+ description: string | null;
86
+ enabled: boolean;
87
+ }[];
88
+ structure: "split" | "full";
89
+ schedule: {
90
+ percent: number;
91
+ dueInDays: number;
92
+ dueCondition: "after_booking" | "before_departure";
93
+ }[];
94
+ defaultSchedule: {
95
+ depositPercent: number | null;
96
+ balanceDueDaysBeforeDeparture: number | null;
97
+ } | null;
98
+ bankTransfer: {
99
+ dueDays: number | null;
100
+ account: {
101
+ provider: string | null;
102
+ currency: string | null;
103
+ iban: string;
104
+ beneficiary: string;
105
+ bank: string;
106
+ } | null;
107
+ accountHolder: string | null;
108
+ bankName: string | null;
109
+ iban: string | null;
110
+ bic: string | null;
111
+ paymentReference: string | null;
112
+ instructions: string | null;
113
+ } | null;
114
+ };
115
+ };
116
+ };
117
+ outputFormat: "json";
118
+ status: import("hono/utils/http-status").ContentfulStatusCode;
119
+ };
120
+ };
121
+ } & {
122
+ "/leads": {
123
+ $post: {
124
+ input: {};
125
+ output: {
126
+ error: string;
127
+ };
128
+ outputFormat: "json";
129
+ status: 429 | 400 | 403;
130
+ } | {
131
+ input: {};
132
+ output: {
133
+ data: {
134
+ id: string;
135
+ personId: string;
136
+ kind: "notify" | "wishlist" | "inquiry" | "request_offer" | "referral";
137
+ source: "admin" | "phone" | "booking" | "form" | "website" | "abandoned_cart";
138
+ status: "expired" | "lost" | "new" | "contacted" | "qualified" | "converted";
139
+ duplicate: boolean;
140
+ };
141
+ };
142
+ outputFormat: "json";
143
+ status: 201;
144
+ };
145
+ };
146
+ } & {
147
+ "/newsletter/subscribe": {
148
+ $post: {
149
+ input: {};
150
+ output: {
151
+ error: string;
152
+ };
153
+ outputFormat: "json";
154
+ status: 429 | 400 | 403;
155
+ } | {
156
+ input: {};
157
+ output: {
158
+ data: {
159
+ id: string;
160
+ personId: string;
161
+ kind: "notify" | "wishlist" | "inquiry" | "request_offer" | "referral";
162
+ source: "admin" | "phone" | "booking" | "form" | "website" | "abandoned_cart";
163
+ status: "expired" | "lost" | "new" | "contacted" | "qualified" | "converted";
164
+ duplicate: boolean;
165
+ doubleOptIn: "requested" | "not_configured";
166
+ };
167
+ };
168
+ outputFormat: "json";
169
+ status: 202;
170
+ };
171
+ };
172
+ } & {
173
+ "/departures/:departureId": {
174
+ $get: {
175
+ input: {
176
+ param: {
177
+ departureId: string;
178
+ };
179
+ };
180
+ output: {
181
+ error: string;
182
+ };
183
+ outputFormat: "json";
184
+ status: 404;
185
+ } | {
186
+ input: {
187
+ param: {
188
+ departureId: string;
189
+ };
190
+ };
191
+ output: {
192
+ data: {
193
+ id: string;
194
+ productId: string;
195
+ itineraryId: string;
196
+ optionId: string | null;
197
+ dateLocal: string | null;
198
+ startAt: string | null;
199
+ endAt: string | null;
200
+ timezone: string;
201
+ startTime: {
202
+ id: string;
203
+ label: string | null;
204
+ startTimeLocal: string;
205
+ durationMinutes: number | null;
206
+ } | null;
207
+ meetingPoint: string | null;
208
+ capacity: number | null;
209
+ remaining: number | null;
210
+ departureStatus: "on_request" | import("./service-boundary-sql.js").StorefrontSlotStatus;
211
+ nights: number | null;
212
+ days: number | null;
213
+ ratePlans: {
214
+ id: string;
215
+ active: boolean;
216
+ name: string;
217
+ pricingModel: string;
218
+ basePrices: {
219
+ amount: number;
220
+ currencyCode: string;
221
+ }[];
222
+ roomPrices: {
223
+ amount: number;
224
+ currencyCode: string;
225
+ roomType: {
226
+ id: string;
227
+ name: string;
228
+ occupancy: {
229
+ adultsMin: number;
230
+ adultsMax: number;
231
+ childrenMax: number;
232
+ };
233
+ };
234
+ }[];
235
+ }[];
236
+ resourceManifest: {
237
+ kinds: {
238
+ capacity: number;
239
+ assigned: number;
240
+ available: number;
241
+ kind: string;
242
+ }[];
243
+ resources: {
244
+ id: string;
245
+ kind: string;
246
+ label: string | null;
247
+ refType: string | null;
248
+ refId: string | null;
249
+ capacity: number;
250
+ assigned: number;
251
+ available: number;
252
+ parentId: string | null;
253
+ flags: {
254
+ [x: string]: import("hono/utils/types").JSONValue;
255
+ };
256
+ }[];
257
+ } | null;
258
+ };
259
+ };
260
+ outputFormat: "json";
261
+ status: import("hono/utils/http-status").ContentfulStatusCode;
262
+ };
263
+ };
264
+ } & {
265
+ "/products/:productId/departures": {
266
+ $get: {
267
+ input: {
268
+ param: {
269
+ productId: string;
270
+ };
271
+ };
272
+ output: {
273
+ data: {
274
+ id: string;
275
+ productId: string;
276
+ itineraryId: string;
277
+ optionId: string | null;
278
+ dateLocal: string | null;
279
+ startAt: string | null;
280
+ endAt: string | null;
281
+ timezone: string;
282
+ startTime: {
283
+ id: string;
284
+ label: string | null;
285
+ startTimeLocal: string;
286
+ durationMinutes: number | null;
287
+ } | null;
288
+ meetingPoint: string | null;
289
+ capacity: number | null;
290
+ remaining: number | null;
291
+ departureStatus: "on_request" | import("./service-boundary-sql.js").StorefrontSlotStatus;
292
+ nights: number | null;
293
+ days: number | null;
294
+ ratePlans: {
295
+ id: string;
296
+ active: boolean;
297
+ name: string;
298
+ pricingModel: string;
299
+ basePrices: {
300
+ amount: number;
301
+ currencyCode: string;
302
+ }[];
303
+ roomPrices: {
304
+ amount: number;
305
+ currencyCode: string;
306
+ roomType: {
307
+ id: string;
308
+ name: string;
309
+ occupancy: {
310
+ adultsMin: number;
311
+ adultsMax: number;
312
+ childrenMax: number;
313
+ };
314
+ };
315
+ }[];
316
+ }[];
317
+ resourceManifest: {
318
+ kinds: {
319
+ capacity: number;
320
+ assigned: number;
321
+ available: number;
322
+ kind: string;
323
+ }[];
324
+ resources: {
325
+ id: string;
326
+ kind: string;
327
+ label: string | null;
328
+ refType: string | null;
329
+ refId: string | null;
330
+ capacity: number;
331
+ assigned: number;
332
+ available: number;
333
+ parentId: string | null;
334
+ flags: {
335
+ [x: string]: import("hono/utils/types").JSONValue;
336
+ };
337
+ }[];
338
+ } | null;
339
+ }[];
340
+ total: number;
341
+ limit: number;
342
+ offset: number;
343
+ };
344
+ outputFormat: "json";
345
+ status: import("hono/utils/http-status").ContentfulStatusCode;
346
+ };
347
+ };
348
+ } & {
349
+ "/departures/:departureId/price": {
350
+ $post: {
351
+ input: {
352
+ param: {
353
+ departureId: string;
354
+ };
355
+ };
356
+ output: {
357
+ data: {
358
+ departureId: string;
359
+ productId: string;
360
+ optionId: string | null;
361
+ currencyCode: string;
362
+ basePrice: number;
363
+ taxAmount: number;
364
+ total: number;
365
+ notes: string | null;
366
+ lineItems: {
367
+ name: string;
368
+ total: number;
369
+ quantity: number;
370
+ unitPrice: number;
371
+ }[];
372
+ allocation: {
373
+ slot: {
374
+ id: string;
375
+ productId: string;
376
+ optionId: string | null;
377
+ dateLocal: string | null;
378
+ startAt: string | null;
379
+ endAt: string | null;
380
+ timezone: string;
381
+ status: "on_request" | import("./service-boundary-sql.js").StorefrontSlotStatus;
382
+ availabilityState: import("./service-departures-core.js").StorefrontProductAvailabilityState;
383
+ capacity: number | null;
384
+ remaining: number | null;
385
+ pastCutoff: boolean;
386
+ tooEarly: boolean;
387
+ resourceManifest: {
388
+ kinds: {
389
+ capacity: number;
390
+ assigned: number;
391
+ available: number;
392
+ kind: string;
393
+ }[];
394
+ resources: {
395
+ id: string;
396
+ kind: string;
397
+ label: string | null;
398
+ refType: string | null;
399
+ refId: string | null;
400
+ capacity: number;
401
+ assigned: number;
402
+ available: number;
403
+ parentId: string | null;
404
+ flags: {
405
+ [x: string]: import("hono/utils/types").JSONValue;
406
+ };
407
+ }[];
408
+ } | null;
409
+ };
410
+ pax: {
411
+ adults: number;
412
+ children: number;
413
+ infants: number;
414
+ total: number;
415
+ };
416
+ requestedUnits: {
417
+ unitId: string | null;
418
+ requestRef: string | null;
419
+ name: string;
420
+ unitType: string | null;
421
+ quantity: number;
422
+ pricingMode: string | null;
423
+ unitPrice: number;
424
+ total: number;
425
+ currencyCode: string;
426
+ tierId: string | null;
427
+ }[];
428
+ rooms: {
429
+ unitId: string;
430
+ name: string;
431
+ occupancy: number;
432
+ quantity: number;
433
+ pax: number;
434
+ pricingMode: string | null;
435
+ unitPrice: number;
436
+ total: number;
437
+ currencyCode: string;
438
+ tierId: string | null;
439
+ }[];
440
+ };
441
+ units: {
442
+ unitId: string | null;
443
+ requestRef: string | null;
444
+ name: string;
445
+ unitType: string | null;
446
+ quantity: number;
447
+ pricingMode: string | null;
448
+ unitPrice: number;
449
+ total: number;
450
+ currencyCode: string;
451
+ tierId: string | null;
452
+ }[];
453
+ rooms: {
454
+ unitId: string;
455
+ name: string;
456
+ occupancy: number;
457
+ quantity: number;
458
+ pax: number;
459
+ pricingMode: string | null;
460
+ unitPrice: number;
461
+ total: number;
462
+ currencyCode: string;
463
+ tierId: string | null;
464
+ }[];
465
+ extras: {
466
+ extraId: string;
467
+ name: string;
468
+ required: boolean;
469
+ selectable: boolean;
470
+ selected: boolean;
471
+ pricingMode: string;
472
+ quantity: number;
473
+ unitPrice: number;
474
+ total: number;
475
+ currencyCode: string;
476
+ }[];
477
+ offers: {
478
+ available: {
479
+ offer: {
480
+ id: string;
481
+ name: string;
482
+ slug: string | null;
483
+ description: string | null;
484
+ discountType: "percentage" | "fixed_amount";
485
+ discountValue: string;
486
+ currency: string | null;
487
+ applicableProductIds: string[];
488
+ applicableDepartureIds: string[];
489
+ validFrom: string | null;
490
+ validTo: string | null;
491
+ minTravelers: number | null;
492
+ imageMobileUrl: string | null;
493
+ imageDesktopUrl: string | null;
494
+ stackable: boolean;
495
+ createdAt: string;
496
+ updatedAt: string;
497
+ };
498
+ status: string;
499
+ reason: string | null;
500
+ selected: boolean;
501
+ discountAppliedCents: number;
502
+ discountedPriceCents: number;
503
+ }[];
504
+ requested: ({
505
+ kind: "slug";
506
+ value: string;
507
+ result: {
508
+ status: "applied" | "not_applicable" | "invalid" | "conflict";
509
+ reason: "currency" | "scope" | "booking_mismatch" | "conflict" | "offer_not_found" | "offer_expired" | "offer_not_yet_valid" | "code_not_found" | "code_required" | "code_expired" | "code_not_yet_valid" | "min_pax" | "eligibility" | "no_discount" | "session_mismatch" | null;
510
+ offer: {
511
+ id: string;
512
+ name: string;
513
+ slug: string | null;
514
+ description: string | null;
515
+ discountType: "percentage" | "fixed_amount";
516
+ discountValue: string;
517
+ currency: string | null;
518
+ applicableProductIds: string[];
519
+ applicableDepartureIds: string[];
520
+ validFrom: string | null;
521
+ validTo: string | null;
522
+ minTravelers: number | null;
523
+ imageMobileUrl: string | null;
524
+ imageDesktopUrl: string | null;
525
+ stackable: boolean;
526
+ createdAt: string;
527
+ updatedAt: string;
528
+ } | null;
529
+ target: {
530
+ bookingId: string | null;
531
+ sessionId: string | null;
532
+ productId: string;
533
+ departureId: string | null;
534
+ };
535
+ pricing: {
536
+ basePriceCents: number;
537
+ currency: string;
538
+ discountAppliedCents: number;
539
+ discountedPriceCents: number;
540
+ };
541
+ appliedOffers: {
542
+ offerId: string;
543
+ offerName: string;
544
+ discountAppliedCents: number;
545
+ discountedPriceCents: number;
546
+ currency: string;
547
+ discountKind: "percentage" | "fixed_amount";
548
+ discountPercent: number | null;
549
+ discountAmountCents: number | null;
550
+ appliedCode: string | null;
551
+ stackable: boolean;
552
+ }[];
553
+ conflict: {
554
+ policy: "best_discount_wins" | "stackable_compose";
555
+ autoAppliedOfferIds: string[];
556
+ manualOfferId: string | null;
557
+ selectedOfferIds: string[];
558
+ message: string;
559
+ } | null;
560
+ } | null;
561
+ } | {
562
+ kind: "code";
563
+ value: string;
564
+ result: {
565
+ status: "applied" | "not_applicable" | "invalid" | "conflict";
566
+ reason: "currency" | "scope" | "booking_mismatch" | "conflict" | "offer_not_found" | "offer_expired" | "offer_not_yet_valid" | "code_not_found" | "code_required" | "code_expired" | "code_not_yet_valid" | "min_pax" | "eligibility" | "no_discount" | "session_mismatch" | null;
567
+ offer: {
568
+ id: string;
569
+ name: string;
570
+ slug: string | null;
571
+ description: string | null;
572
+ discountType: "percentage" | "fixed_amount";
573
+ discountValue: string;
574
+ currency: string | null;
575
+ applicableProductIds: string[];
576
+ applicableDepartureIds: string[];
577
+ validFrom: string | null;
578
+ validTo: string | null;
579
+ minTravelers: number | null;
580
+ imageMobileUrl: string | null;
581
+ imageDesktopUrl: string | null;
582
+ stackable: boolean;
583
+ createdAt: string;
584
+ updatedAt: string;
585
+ } | null;
586
+ target: {
587
+ bookingId: string | null;
588
+ sessionId: string | null;
589
+ productId: string;
590
+ departureId: string | null;
591
+ };
592
+ pricing: {
593
+ basePriceCents: number;
594
+ currency: string;
595
+ discountAppliedCents: number;
596
+ discountedPriceCents: number;
597
+ };
598
+ appliedOffers: {
599
+ offerId: string;
600
+ offerName: string;
601
+ discountAppliedCents: number;
602
+ discountedPriceCents: number;
603
+ currency: string;
604
+ discountKind: "percentage" | "fixed_amount";
605
+ discountPercent: number | null;
606
+ discountAmountCents: number | null;
607
+ appliedCode: string | null;
608
+ stackable: boolean;
609
+ }[];
610
+ conflict: {
611
+ policy: "best_discount_wins" | "stackable_compose";
612
+ autoAppliedOfferIds: string[];
613
+ manualOfferId: string | null;
614
+ selectedOfferIds: string[];
615
+ message: string;
616
+ } | null;
617
+ } | null;
618
+ })[];
619
+ applied: {
620
+ offerId: string;
621
+ offerName: string;
622
+ discountAppliedCents: number;
623
+ discountedPriceCents: number;
624
+ currency: string;
625
+ discountKind: "percentage" | "fixed_amount";
626
+ discountPercent: number | null;
627
+ discountAmountCents: number | null;
628
+ appliedCode: string | null;
629
+ stackable: boolean;
630
+ }[];
631
+ conflict: {
632
+ policy: "best_discount_wins" | "stackable_compose";
633
+ autoAppliedOfferIds: string[];
634
+ manualOfferId: string | null;
635
+ selectedOfferIds: string[];
636
+ message: string;
637
+ } | {
638
+ policy: string;
639
+ autoAppliedOfferIds: string[];
640
+ manualOfferId: null;
641
+ selectedOfferIds: string[];
642
+ message: string;
643
+ } | null;
644
+ discountTotal: number;
645
+ discountTotalCents: number;
646
+ totalAfterDiscount: number;
647
+ currencyCode: string;
648
+ };
649
+ totals: {
650
+ currencyCode: string;
651
+ base: number;
652
+ extras: number;
653
+ subtotal: number;
654
+ discount: number;
655
+ tax: number;
656
+ total: number;
657
+ perPerson: number;
658
+ perBooking: number;
659
+ };
660
+ };
661
+ };
662
+ outputFormat: "json";
663
+ status: import("hono/utils/http-status").ContentfulStatusCode;
664
+ } | {
665
+ input: {
666
+ param: {
667
+ departureId: string;
668
+ };
669
+ };
670
+ output: {
671
+ error: string;
672
+ };
673
+ outputFormat: "json";
674
+ status: 404;
675
+ };
676
+ };
677
+ } & {
678
+ "/bookings/sessions/bootstrap": {
679
+ $post: {
680
+ input: {};
681
+ output: {
682
+ error: string;
683
+ };
684
+ outputFormat: "json";
685
+ status: 428;
686
+ } | {
687
+ input: {};
688
+ output: {
689
+ data: {
690
+ intentId: string;
691
+ status: "failed" | "pending" | "succeeded";
692
+ statusUrl: string;
693
+ };
694
+ };
695
+ outputFormat: "json";
696
+ status: 202;
697
+ } | {
698
+ input: {};
699
+ output: {
700
+ error: string;
701
+ };
702
+ outputFormat: "json";
703
+ status: 404;
704
+ } | {
705
+ input: {};
706
+ output: {
707
+ data?: {
708
+ repricing: {
709
+ originalQuote: {
710
+ currencyCode: string;
711
+ totalSellAmountCents: number;
712
+ quotedAt?: string | null | undefined;
713
+ expiresAt?: string | null | undefined;
714
+ };
715
+ current: {
716
+ sessionId: string;
717
+ catalogId: string | null;
718
+ currencyCode: string;
719
+ totalSellAmountCents: number;
720
+ items: {
721
+ inputIndex: number;
722
+ itemId: string;
723
+ title: string;
724
+ productId: string | null;
725
+ optionId: string | null;
726
+ optionUnitId: string | null;
727
+ optionUnitName: string | null;
728
+ optionUnitType: string | null;
729
+ pricingCategoryId: string | null;
730
+ quantity: number;
731
+ pricingMode: string;
732
+ unitSellAmountCents: number | null;
733
+ totalSellAmountCents: number | null;
734
+ warnings: string[];
735
+ }[];
736
+ warnings: never[];
737
+ appliedToSession: boolean;
738
+ };
739
+ deltaAmountCents: number;
740
+ staleQuote: boolean;
741
+ };
742
+ } | undefined;
743
+ error: string;
744
+ };
745
+ outputFormat: "json";
746
+ status: 400 | 409;
747
+ } | {
748
+ input: {};
749
+ output: {
750
+ error: string;
751
+ };
752
+ outputFormat: "json";
753
+ status: 409;
754
+ } | {
755
+ input: {};
756
+ output: {
757
+ data: {
758
+ session: {
759
+ sessionId: string;
760
+ bookingNumber: string;
761
+ status: "draft" | "confirmed" | "cancelled" | "on_hold" | "awaiting_payment" | "in_progress" | "completed" | "expired";
762
+ externalBookingRef: string | null;
763
+ communicationLanguage: string | null;
764
+ sellCurrency: string;
765
+ sellAmountCents: number | null;
766
+ startDate: string | null;
767
+ endDate: string | null;
768
+ pax: number | null;
769
+ holdExpiresAt: string | null;
770
+ confirmedAt: string | null;
771
+ expiredAt: string | null;
772
+ cancelledAt: string | null;
773
+ completedAt: string | null;
774
+ travelers: {
775
+ id: string;
776
+ participantType: "other" | "traveler" | "occupant";
777
+ travelerCategory: "other" | "adult" | "child" | "infant" | "senior" | null;
778
+ firstName: string;
779
+ lastName: string;
780
+ email: string | null;
781
+ phone: string | null;
782
+ preferredLanguage: string | null;
783
+ specialRequests: string | null;
784
+ isPrimary: boolean;
785
+ notes: string | null;
786
+ }[];
787
+ items: {
788
+ id: string;
789
+ title: string;
790
+ description: string | null;
791
+ itemType: "service" | "unit" | "other" | "extra" | "fee" | "tax" | "discount" | "adjustment" | "accommodation" | "transport";
792
+ status: "draft" | "confirmed" | "cancelled" | "fulfilled" | "on_hold" | "expired";
793
+ serviceDate: string | null;
794
+ startsAt: string | null;
795
+ endsAt: string | null;
796
+ quantity: number;
797
+ sellCurrency: string;
798
+ unitSellAmountCents: number | null;
799
+ totalSellAmountCents: number | null;
800
+ costCurrency: string | null;
801
+ unitCostAmountCents: number | null;
802
+ totalCostAmountCents: number | null;
803
+ notes: string | null;
804
+ productId: string | null;
805
+ optionId: string | null;
806
+ optionUnitId: string | null;
807
+ pricingCategoryId: string | null;
808
+ travelerLinks: {
809
+ id: string;
810
+ travelerId: string;
811
+ role: string;
812
+ isPrimary: boolean;
813
+ }[];
814
+ }[];
815
+ allocations: {
816
+ id: string;
817
+ bookingItemId: string;
818
+ productId: string | null;
819
+ optionId: string | null;
820
+ optionUnitId: string | null;
821
+ pricingCategoryId: string | null;
822
+ availabilitySlotId: string | null;
823
+ quantity: number;
824
+ allocationType: "unit" | "pickup" | "resource";
825
+ status: "confirmed" | "cancelled" | "fulfilled" | "expired" | "held" | "released";
826
+ holdExpiresAt: string | null;
827
+ confirmedAt: string | null;
828
+ releasedAt: string | null;
829
+ }[];
830
+ checklist: {
831
+ hasTravelers: boolean;
832
+ hasPrimaryTraveler: boolean;
833
+ hasItems: boolean;
834
+ hasAllocations: boolean;
835
+ readyForConfirmation: boolean;
836
+ };
837
+ state: {
838
+ sessionId: string;
839
+ stateKey: "wizard";
840
+ currentStep: string | null;
841
+ completedSteps: string[];
842
+ payload: {
843
+ [x: string]: import("hono/utils/types").JSONValue;
844
+ };
845
+ version: number;
846
+ createdAt: string;
847
+ updatedAt: string;
848
+ } | null;
849
+ checkoutCapability: {
850
+ token: string;
851
+ expiresAt: string;
852
+ actions: ("session:read" | "session:update" | "session:reprice" | "session:finalize" | "payment:read" | "payment:start")[];
853
+ };
854
+ };
855
+ paymentPlan: {
856
+ source: "storefront_default";
857
+ depositKind: import("@voyant-travel/finance").DepositKind;
858
+ depositPercent: number | null;
859
+ depositAmountCents: number | null;
860
+ requiresFullPayment: boolean;
861
+ };
862
+ paymentSchedule: {
863
+ id: string;
864
+ scheduleType: "other" | "deposit" | "installment" | "balance" | "hold";
865
+ status: "pending" | "cancelled" | "waived" | "expired" | "paid" | "due";
866
+ dueDate: string;
867
+ currency: string;
868
+ amountCents: number;
869
+ notes: string | null;
870
+ }[];
871
+ repricing: {
872
+ originalQuote: {
873
+ currencyCode: string;
874
+ totalSellAmountCents: number;
875
+ quotedAt?: string | null | undefined;
876
+ expiresAt?: string | null | undefined;
877
+ };
878
+ current: {
879
+ sessionId: string;
880
+ items: {
881
+ itemId: string;
882
+ title: string;
883
+ productId: string | null;
884
+ optionId: string | null;
885
+ optionUnitId: string | null;
886
+ optionUnitName: string | null;
887
+ optionUnitType: string | null;
888
+ pricingCategoryId: string | null;
889
+ quantity: number;
890
+ pricingMode: string;
891
+ unitSellAmountCents: number | null;
892
+ totalSellAmountCents: number | null;
893
+ warnings: string[];
894
+ }[];
895
+ catalogId: string | null;
896
+ currencyCode: string;
897
+ totalSellAmountCents: number;
898
+ warnings: never[];
899
+ appliedToSession: boolean;
900
+ };
901
+ deltaAmountCents: number;
902
+ staleQuote: boolean;
903
+ };
904
+ availability: {
905
+ departureId: string;
906
+ slotId: string;
907
+ productId: string;
908
+ optionId: string | null;
909
+ dateLocal: string;
910
+ startsAt: string | null;
911
+ endsAt: string | null;
912
+ timezone: string;
913
+ status: import("./service-boundary-sql.js").StorefrontSlotStatus;
914
+ capacity: number | null;
915
+ remaining: number | null;
916
+ };
917
+ allocation: {
918
+ id: string;
919
+ bookingItemId: string;
920
+ productId: string | null;
921
+ optionId: string | null;
922
+ optionUnitId: string | null;
923
+ pricingCategoryId: string | null;
924
+ availabilitySlotId: string | null;
925
+ quantity: number;
926
+ allocationType: "unit" | "pickup" | "resource";
927
+ status: "confirmed" | "cancelled" | "fulfilled" | "expired" | "held" | "released";
928
+ holdExpiresAt: string | null;
929
+ confirmedAt: string | null;
930
+ releasedAt: string | null;
931
+ }[];
932
+ currency: string;
933
+ };
934
+ };
935
+ outputFormat: "json";
936
+ status: 201;
937
+ };
938
+ };
939
+ } & {
940
+ "/bookings/intents/:intentId": {
941
+ $get: {
942
+ input: {
943
+ param: {
944
+ intentId: string;
945
+ };
946
+ };
947
+ output: {
948
+ error: string;
949
+ };
950
+ outputFormat: "json";
951
+ status: 404;
952
+ } | {
953
+ input: {
954
+ param: {
955
+ intentId: string;
956
+ };
957
+ };
958
+ output: {
959
+ data: {
960
+ intentId: string;
961
+ status: string;
962
+ };
963
+ };
964
+ outputFormat: "json";
965
+ status: import("hono/utils/http-status").ContentfulStatusCode;
966
+ };
967
+ };
968
+ } & {
969
+ "/departures/:departureId/eligibility": {
970
+ $post: {
971
+ input: {
972
+ param: {
973
+ departureId: string;
974
+ };
975
+ };
976
+ output: {
977
+ data: {
978
+ departureId: string;
979
+ productId: string | null;
980
+ travelStartsOn: string | null;
981
+ travelEndsOn: string | null;
982
+ eligible: boolean;
983
+ blockingIssues: {
984
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
985
+ severity: "warning" | "blocking";
986
+ message: string;
987
+ travelerRef: string;
988
+ ruleId: string;
989
+ destinationCountries: string[];
990
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
991
+ }[];
992
+ warnings: {
993
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
994
+ severity: "warning" | "blocking";
995
+ message: string;
996
+ travelerRef: string;
997
+ ruleId: string;
998
+ destinationCountries: string[];
999
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1000
+ }[];
1001
+ travelers: {
1002
+ travelerRef: string;
1003
+ eligible: boolean;
1004
+ matchedRuleIds: string[];
1005
+ blockingIssues: {
1006
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
1007
+ severity: "warning" | "blocking";
1008
+ message: string;
1009
+ travelerRef: string;
1010
+ ruleId: string;
1011
+ destinationCountries: string[];
1012
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1013
+ }[];
1014
+ warnings: {
1015
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
1016
+ severity: "warning" | "blocking";
1017
+ message: string;
1018
+ travelerRef: string;
1019
+ ruleId: string;
1020
+ destinationCountries: string[];
1021
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1022
+ }[];
1023
+ }[];
1024
+ };
1025
+ };
1026
+ outputFormat: "json";
1027
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1028
+ };
1029
+ };
1030
+ } & {
1031
+ "/products/:productId/departures/:departureId/eligibility": {
1032
+ $post: {
1033
+ input: {
1034
+ param: {
1035
+ departureId: string;
1036
+ } & {
1037
+ productId: string;
1038
+ };
1039
+ };
1040
+ output: {
1041
+ data: {
1042
+ departureId: string;
1043
+ productId: string | null;
1044
+ travelStartsOn: string | null;
1045
+ travelEndsOn: string | null;
1046
+ eligible: boolean;
1047
+ blockingIssues: {
1048
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
1049
+ severity: "warning" | "blocking";
1050
+ message: string;
1051
+ travelerRef: string;
1052
+ ruleId: string;
1053
+ destinationCountries: string[];
1054
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1055
+ }[];
1056
+ warnings: {
1057
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
1058
+ severity: "warning" | "blocking";
1059
+ message: string;
1060
+ travelerRef: string;
1061
+ ruleId: string;
1062
+ destinationCountries: string[];
1063
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1064
+ }[];
1065
+ travelers: {
1066
+ travelerRef: string;
1067
+ eligible: boolean;
1068
+ matchedRuleIds: string[];
1069
+ blockingIssues: {
1070
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
1071
+ severity: "warning" | "blocking";
1072
+ message: string;
1073
+ travelerRef: string;
1074
+ ruleId: string;
1075
+ destinationCountries: string[];
1076
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1077
+ }[];
1078
+ warnings: {
1079
+ code: "date_of_birth_required" | "document_required" | "document_expiry_required" | "document_validity" | "nationality_required" | "visa_required" | "minor_consent_required" | "travel_dates_required";
1080
+ severity: "warning" | "blocking";
1081
+ message: string;
1082
+ travelerRef: string;
1083
+ ruleId: string;
1084
+ destinationCountries: string[];
1085
+ requiredDocumentType: "passport" | "none" | "id_card" | "passport_or_id_card";
1086
+ }[];
1087
+ }[];
1088
+ };
1089
+ };
1090
+ outputFormat: "json";
1091
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1092
+ };
1093
+ };
1094
+ } & {
1095
+ "/products/:productId/extensions": {
1096
+ $get: {
1097
+ input: {
1098
+ param: {
1099
+ productId: string;
1100
+ };
1101
+ };
1102
+ output: {
1103
+ data: {
1104
+ extensions: {
1105
+ id: string;
1106
+ name: string;
1107
+ label: string;
1108
+ required: boolean;
1109
+ selectable: boolean;
1110
+ hasOptions: boolean;
1111
+ refProductId: string | null;
1112
+ thumb: string | null;
1113
+ pricePerPerson: number | null;
1114
+ currencyCode: string;
1115
+ pricingMode: string;
1116
+ defaultQuantity: number | null;
1117
+ minQuantity: number | null;
1118
+ maxQuantity: number | null;
1119
+ }[];
1120
+ items: {
1121
+ id: string;
1122
+ name: string;
1123
+ label: string;
1124
+ required: boolean;
1125
+ selectable: boolean;
1126
+ hasOptions: boolean;
1127
+ refProductId: string | null;
1128
+ thumb: string | null;
1129
+ pricePerPerson: number | null;
1130
+ currencyCode: string;
1131
+ pricingMode: string;
1132
+ defaultQuantity: number | null;
1133
+ minQuantity: number | null;
1134
+ maxQuantity: number | null;
1135
+ }[];
1136
+ details: {
1137
+ [x: string]: {
1138
+ description: string | null;
1139
+ media: {
1140
+ url: string;
1141
+ alt: string | null;
1142
+ }[];
1143
+ };
1144
+ };
1145
+ currencyCode: string;
1146
+ };
1147
+ };
1148
+ outputFormat: "json";
1149
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1150
+ };
1151
+ };
1152
+ } & {
1153
+ "/products/:productId/availability": {
1154
+ $get: {
1155
+ input: {
1156
+ param: {
1157
+ productId: string;
1158
+ };
1159
+ };
1160
+ output: {
1161
+ data: {
1162
+ productId: string;
1163
+ availabilityState: import("./service-departures-core.js").StorefrontProductAvailabilityState;
1164
+ counts: {
1165
+ total: number;
1166
+ open: number;
1167
+ closed: number;
1168
+ soldOut: number;
1169
+ cancelled: number;
1170
+ onRequest: number;
1171
+ pastCutoff: number;
1172
+ tooEarly: number;
1173
+ available: number;
1174
+ };
1175
+ departures: {
1176
+ id: string;
1177
+ productId: string;
1178
+ optionId: string | null;
1179
+ dateLocal: string | null;
1180
+ startAt: string | null;
1181
+ endAt: string | null;
1182
+ timezone: string;
1183
+ status: "on_request" | import("./service-boundary-sql.js").StorefrontSlotStatus;
1184
+ availabilityState: import("./service-departures-core.js").StorefrontProductAvailabilityState;
1185
+ capacity: number | null;
1186
+ remaining: number | null;
1187
+ pastCutoff: boolean;
1188
+ tooEarly: boolean;
1189
+ }[];
1190
+ total: number;
1191
+ limit: number;
1192
+ offset: number;
1193
+ };
1194
+ };
1195
+ outputFormat: "json";
1196
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1197
+ };
1198
+ };
1199
+ } & {
1200
+ "/products/:productId/departures/:departureId/itinerary": {
1201
+ $get: {
1202
+ input: {
1203
+ param: {
1204
+ departureId: string;
1205
+ } & {
1206
+ productId: string;
1207
+ };
1208
+ };
1209
+ output: {
1210
+ error: string;
1211
+ };
1212
+ outputFormat: "json";
1213
+ status: 404;
1214
+ } | {
1215
+ input: {
1216
+ param: {
1217
+ departureId: string;
1218
+ } & {
1219
+ productId: string;
1220
+ };
1221
+ };
1222
+ output: {
1223
+ data: {
1224
+ id: string;
1225
+ itineraryId: string;
1226
+ days: {
1227
+ id: string;
1228
+ title: string;
1229
+ description: string | null;
1230
+ thumbnail: {
1231
+ url: string;
1232
+ } | null;
1233
+ segments: {
1234
+ id: string;
1235
+ title: string;
1236
+ description: string | null;
1237
+ }[];
1238
+ }[];
1239
+ };
1240
+ };
1241
+ outputFormat: "json";
1242
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1243
+ };
1244
+ };
1245
+ } & {
1246
+ "/products/:productId/offers": {
1247
+ $get: {
1248
+ input: {
1249
+ param: {
1250
+ productId: string;
1251
+ };
1252
+ };
1253
+ output: {
1254
+ data: {
1255
+ id: string;
1256
+ name: string;
1257
+ slug: string | null;
1258
+ description: string | null;
1259
+ discountType: "percentage" | "fixed_amount";
1260
+ discountValue: string;
1261
+ currency: string | null;
1262
+ applicableProductIds: string[];
1263
+ applicableDepartureIds: string[];
1264
+ validFrom: string | null;
1265
+ validTo: string | null;
1266
+ minTravelers: number | null;
1267
+ imageMobileUrl: string | null;
1268
+ imageDesktopUrl: string | null;
1269
+ stackable: boolean;
1270
+ createdAt: string;
1271
+ updatedAt: string;
1272
+ }[];
1273
+ };
1274
+ outputFormat: "json";
1275
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1276
+ };
1277
+ };
1278
+ } & {
1279
+ "/offers/:slug": {
1280
+ $get: {
1281
+ input: {
1282
+ param: {
1283
+ slug: string;
1284
+ };
1285
+ };
1286
+ output: {
1287
+ data: {
1288
+ id: string;
1289
+ name: string;
1290
+ slug: string | null;
1291
+ description: string | null;
1292
+ discountType: "percentage" | "fixed_amount";
1293
+ discountValue: string;
1294
+ currency: string | null;
1295
+ applicableProductIds: string[];
1296
+ applicableDepartureIds: string[];
1297
+ validFrom: string | null;
1298
+ validTo: string | null;
1299
+ minTravelers: number | null;
1300
+ imageMobileUrl: string | null;
1301
+ imageDesktopUrl: string | null;
1302
+ stackable: boolean;
1303
+ createdAt: string;
1304
+ updatedAt: string;
1305
+ };
1306
+ };
1307
+ outputFormat: "json";
1308
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1309
+ } | {
1310
+ input: {
1311
+ param: {
1312
+ slug: string;
1313
+ };
1314
+ };
1315
+ output: {
1316
+ error: string;
1317
+ };
1318
+ outputFormat: "json";
1319
+ status: 404;
1320
+ };
1321
+ };
1322
+ } & {
1323
+ "/offers/:slug/apply": {
1324
+ $post: {
1325
+ input: {
1326
+ param: {
1327
+ slug: string;
1328
+ };
1329
+ };
1330
+ output: {
1331
+ data: {
1332
+ status: "applied" | "not_applicable" | "invalid" | "conflict";
1333
+ reason: "currency" | "scope" | "booking_mismatch" | "conflict" | "offer_not_found" | "offer_expired" | "offer_not_yet_valid" | "code_not_found" | "code_required" | "code_expired" | "code_not_yet_valid" | "min_pax" | "eligibility" | "no_discount" | "session_mismatch" | null;
1334
+ offer: {
1335
+ id: string;
1336
+ name: string;
1337
+ slug: string | null;
1338
+ description: string | null;
1339
+ discountType: "percentage" | "fixed_amount";
1340
+ discountValue: string;
1341
+ currency: string | null;
1342
+ applicableProductIds: string[];
1343
+ applicableDepartureIds: string[];
1344
+ validFrom: string | null;
1345
+ validTo: string | null;
1346
+ minTravelers: number | null;
1347
+ imageMobileUrl: string | null;
1348
+ imageDesktopUrl: string | null;
1349
+ stackable: boolean;
1350
+ createdAt: string;
1351
+ updatedAt: string;
1352
+ } | null;
1353
+ target: {
1354
+ bookingId: string | null;
1355
+ sessionId: string | null;
1356
+ productId: string;
1357
+ departureId: string | null;
1358
+ };
1359
+ pricing: {
1360
+ basePriceCents: number;
1361
+ currency: string;
1362
+ discountAppliedCents: number;
1363
+ discountedPriceCents: number;
1364
+ };
1365
+ appliedOffers: {
1366
+ offerId: string;
1367
+ offerName: string;
1368
+ discountAppliedCents: number;
1369
+ discountedPriceCents: number;
1370
+ currency: string;
1371
+ discountKind: "percentage" | "fixed_amount";
1372
+ discountPercent: number | null;
1373
+ discountAmountCents: number | null;
1374
+ appliedCode: string | null;
1375
+ stackable: boolean;
1376
+ }[];
1377
+ conflict: {
1378
+ policy: "best_discount_wins" | "stackable_compose";
1379
+ autoAppliedOfferIds: string[];
1380
+ manualOfferId: string | null;
1381
+ selectedOfferIds: string[];
1382
+ message: string;
1383
+ } | null;
1384
+ };
1385
+ };
1386
+ outputFormat: "json";
1387
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1388
+ } | {
1389
+ input: {
1390
+ param: {
1391
+ slug: string;
1392
+ };
1393
+ };
1394
+ output: {
1395
+ error: string;
1396
+ };
1397
+ outputFormat: "json";
1398
+ status: 501;
1399
+ };
1400
+ };
1401
+ } & {
1402
+ "/offers/redeem": {
1403
+ $post: {
1404
+ input: {};
1405
+ output: {
1406
+ data: {
1407
+ status: "applied" | "not_applicable" | "invalid" | "conflict";
1408
+ reason: "currency" | "scope" | "booking_mismatch" | "conflict" | "offer_not_found" | "offer_expired" | "offer_not_yet_valid" | "code_not_found" | "code_required" | "code_expired" | "code_not_yet_valid" | "min_pax" | "eligibility" | "no_discount" | "session_mismatch" | null;
1409
+ offer: {
1410
+ id: string;
1411
+ name: string;
1412
+ slug: string | null;
1413
+ description: string | null;
1414
+ discountType: "percentage" | "fixed_amount";
1415
+ discountValue: string;
1416
+ currency: string | null;
1417
+ applicableProductIds: string[];
1418
+ applicableDepartureIds: string[];
1419
+ validFrom: string | null;
1420
+ validTo: string | null;
1421
+ minTravelers: number | null;
1422
+ imageMobileUrl: string | null;
1423
+ imageDesktopUrl: string | null;
1424
+ stackable: boolean;
1425
+ createdAt: string;
1426
+ updatedAt: string;
1427
+ } | null;
1428
+ target: {
1429
+ bookingId: string | null;
1430
+ sessionId: string | null;
1431
+ productId: string;
1432
+ departureId: string | null;
1433
+ };
1434
+ pricing: {
1435
+ basePriceCents: number;
1436
+ currency: string;
1437
+ discountAppliedCents: number;
1438
+ discountedPriceCents: number;
1439
+ };
1440
+ appliedOffers: {
1441
+ offerId: string;
1442
+ offerName: string;
1443
+ discountAppliedCents: number;
1444
+ discountedPriceCents: number;
1445
+ currency: string;
1446
+ discountKind: "percentage" | "fixed_amount";
1447
+ discountPercent: number | null;
1448
+ discountAmountCents: number | null;
1449
+ appliedCode: string | null;
1450
+ stackable: boolean;
1451
+ }[];
1452
+ conflict: {
1453
+ policy: "best_discount_wins" | "stackable_compose";
1454
+ autoAppliedOfferIds: string[];
1455
+ manualOfferId: string | null;
1456
+ selectedOfferIds: string[];
1457
+ message: string;
1458
+ } | null;
1459
+ };
1460
+ };
1461
+ outputFormat: "json";
1462
+ status: import("hono/utils/http-status").ContentfulStatusCode;
1463
+ } | {
1464
+ input: {};
1465
+ output: {
1466
+ error: string;
1467
+ };
1468
+ outputFormat: "json";
1469
+ status: 501;
1470
+ };
1471
+ };
1472
+ }, "/", "/offers/redeem">;
1473
+ export type StorefrontPublicRoutes = ReturnType<typeof createStorefrontPublicRoutes>;
1474
+ export {};
1475
+ //# sourceMappingURL=routes-public.d.ts.map