@voyant-travel/cruises 0.118.2

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 (210) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +50 -0
  3. package/dist/adapters/connect-compat.d.ts +20 -0
  4. package/dist/adapters/connect-compat.d.ts.map +1 -0
  5. package/dist/adapters/connect-compat.js +71 -0
  6. package/dist/adapters/contract-fixture.d.ts +32 -0
  7. package/dist/adapters/contract-fixture.d.ts.map +1 -0
  8. package/dist/adapters/contract-fixture.js +152 -0
  9. package/dist/adapters/index.d.ts +331 -0
  10. package/dist/adapters/index.d.ts.map +1 -0
  11. package/dist/adapters/index.js +16 -0
  12. package/dist/adapters/memoize.d.ts +28 -0
  13. package/dist/adapters/memoize.d.ts.map +1 -0
  14. package/dist/adapters/memoize.js +131 -0
  15. package/dist/adapters/mock.d.ts +44 -0
  16. package/dist/adapters/mock.d.ts.map +1 -0
  17. package/dist/adapters/mock.js +192 -0
  18. package/dist/adapters/registry.d.ts +26 -0
  19. package/dist/adapters/registry.d.ts.map +1 -0
  20. package/dist/adapters/registry.js +42 -0
  21. package/dist/adapters/source-adapter-shim.d.ts +80 -0
  22. package/dist/adapters/source-adapter-shim.d.ts.map +1 -0
  23. package/dist/adapters/source-adapter-shim.js +390 -0
  24. package/dist/booking-engine/handler.d.ts +108 -0
  25. package/dist/booking-engine/handler.d.ts.map +1 -0
  26. package/dist/booking-engine/handler.js +225 -0
  27. package/dist/booking-engine/index.d.ts +9 -0
  28. package/dist/booking-engine/index.d.ts.map +1 -0
  29. package/dist/booking-engine/index.js +8 -0
  30. package/dist/booking-extension.d.ts +1179 -0
  31. package/dist/booking-extension.d.ts.map +1 -0
  32. package/dist/booking-extension.js +342 -0
  33. package/dist/cabin-features.d.ts +8 -0
  34. package/dist/cabin-features.d.ts.map +1 -0
  35. package/dist/cabin-features.js +7 -0
  36. package/dist/catalog-policy-cabins.d.ts +18 -0
  37. package/dist/catalog-policy-cabins.d.ts.map +1 -0
  38. package/dist/catalog-policy-cabins.js +96 -0
  39. package/dist/catalog-policy-core.d.ts +3 -0
  40. package/dist/catalog-policy-core.d.ts.map +1 -0
  41. package/dist/catalog-policy-core.js +247 -0
  42. package/dist/catalog-policy-structure.d.ts +3 -0
  43. package/dist/catalog-policy-structure.d.ts.map +1 -0
  44. package/dist/catalog-policy-structure.js +387 -0
  45. package/dist/catalog-policy.d.ts +15 -0
  46. package/dist/catalog-policy.d.ts.map +1 -0
  47. package/dist/catalog-policy.js +19 -0
  48. package/dist/content-shape.d.ts +5 -0
  49. package/dist/content-shape.d.ts.map +1 -0
  50. package/dist/content-shape.js +13 -0
  51. package/dist/draft-shape.d.ts +59 -0
  52. package/dist/draft-shape.d.ts.map +1 -0
  53. package/dist/draft-shape.js +98 -0
  54. package/dist/events.d.ts +21 -0
  55. package/dist/events.d.ts.map +1 -0
  56. package/dist/events.js +21 -0
  57. package/dist/index.d.ts +43 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +66 -0
  60. package/dist/lib/key.d.ts +41 -0
  61. package/dist/lib/key.d.ts.map +1 -0
  62. package/dist/lib/key.js +100 -0
  63. package/dist/routes-booking-payloads.d.ts +133 -0
  64. package/dist/routes-booking-payloads.d.ts.map +1 -0
  65. package/dist/routes-booking-payloads.js +142 -0
  66. package/dist/routes-content.d.ts +53 -0
  67. package/dist/routes-content.d.ts.map +1 -0
  68. package/dist/routes-content.js +158 -0
  69. package/dist/routes-core.d.ts +4 -0
  70. package/dist/routes-core.d.ts.map +1 -0
  71. package/dist/routes-core.js +68 -0
  72. package/dist/routes-detail.d.ts +4 -0
  73. package/dist/routes-detail.d.ts.map +1 -0
  74. package/dist/routes-detail.js +261 -0
  75. package/dist/routes-env.d.ts +13 -0
  76. package/dist/routes-env.d.ts.map +1 -0
  77. package/dist/routes-env.js +1 -0
  78. package/dist/routes-keying.d.ts +28 -0
  79. package/dist/routes-keying.d.ts.map +1 -0
  80. package/dist/routes-keying.js +70 -0
  81. package/dist/routes-public.d.ts +911 -0
  82. package/dist/routes-public.d.ts.map +1 -0
  83. package/dist/routes-public.js +252 -0
  84. package/dist/routes-sailings-prices.d.ts +4 -0
  85. package/dist/routes-sailings-prices.d.ts.map +1 -0
  86. package/dist/routes-sailings-prices.js +278 -0
  87. package/dist/routes-search-index.d.ts +4 -0
  88. package/dist/routes-search-index.d.ts.map +1 -0
  89. package/dist/routes-search-index.js +25 -0
  90. package/dist/routes-ships.d.ts +4 -0
  91. package/dist/routes-ships.d.ts.map +1 -0
  92. package/dist/routes-ships.js +147 -0
  93. package/dist/routes-voyage-groups.d.ts +4 -0
  94. package/dist/routes-voyage-groups.d.ts.map +1 -0
  95. package/dist/routes-voyage-groups.js +85 -0
  96. package/dist/routes.d.ts +5 -0
  97. package/dist/routes.d.ts.map +1 -0
  98. package/dist/routes.js +14 -0
  99. package/dist/schema-cabins.d.ts +1098 -0
  100. package/dist/schema-cabins.d.ts.map +1 -0
  101. package/dist/schema-cabins.js +105 -0
  102. package/dist/schema-content.d.ts +577 -0
  103. package/dist/schema-content.d.ts.map +1 -0
  104. package/dist/schema-content.js +63 -0
  105. package/dist/schema-core.d.ts +1790 -0
  106. package/dist/schema-core.d.ts.map +1 -0
  107. package/dist/schema-core.js +171 -0
  108. package/dist/schema-itinerary.d.ts +556 -0
  109. package/dist/schema-itinerary.d.ts.map +1 -0
  110. package/dist/schema-itinerary.js +50 -0
  111. package/dist/schema-pricing.d.ts +633 -0
  112. package/dist/schema-pricing.d.ts.map +1 -0
  113. package/dist/schema-pricing.js +73 -0
  114. package/dist/schema-search.d.ts +611 -0
  115. package/dist/schema-search.d.ts.map +1 -0
  116. package/dist/schema-search.js +64 -0
  117. package/dist/schema-shared.d.ts +23 -0
  118. package/dist/schema-shared.d.ts.map +1 -0
  119. package/dist/schema-shared.js +107 -0
  120. package/dist/schema-sourced-content.d.ts +247 -0
  121. package/dist/schema-sourced-content.d.ts.map +1 -0
  122. package/dist/schema-sourced-content.js +38 -0
  123. package/dist/schema.d.ts +10 -0
  124. package/dist/schema.d.ts.map +1 -0
  125. package/dist/schema.js +9 -0
  126. package/dist/service-booking-helpers.d.ts +12 -0
  127. package/dist/service-booking-helpers.d.ts.map +1 -0
  128. package/dist/service-booking-helpers.js +94 -0
  129. package/dist/service-booking-types.d.ts +101 -0
  130. package/dist/service-booking-types.d.ts.map +1 -0
  131. package/dist/service-booking-types.js +1 -0
  132. package/dist/service-bookings.d.ts +46 -0
  133. package/dist/service-bookings.d.ts.map +1 -0
  134. package/dist/service-bookings.js +420 -0
  135. package/dist/service-catalog-plane-cabins.d.ts +24 -0
  136. package/dist/service-catalog-plane-cabins.d.ts.map +1 -0
  137. package/dist/service-catalog-plane-cabins.js +90 -0
  138. package/dist/service-catalog-plane.d.ts +74 -0
  139. package/dist/service-catalog-plane.d.ts.map +1 -0
  140. package/dist/service-catalog-plane.js +194 -0
  141. package/dist/service-content-synthesizer.d.ts +42 -0
  142. package/dist/service-content-synthesizer.d.ts.map +1 -0
  143. package/dist/service-content-synthesizer.js +144 -0
  144. package/dist/service-content.d.ts +74 -0
  145. package/dist/service-content.d.ts.map +1 -0
  146. package/dist/service-content.js +315 -0
  147. package/dist/service-core.d.ts +134 -0
  148. package/dist/service-core.d.ts.map +1 -0
  149. package/dist/service-core.js +257 -0
  150. package/dist/service-detach.d.ts +18 -0
  151. package/dist/service-detach.d.ts.map +1 -0
  152. package/dist/service-detach.js +199 -0
  153. package/dist/service-enrichment.d.ts +11 -0
  154. package/dist/service-enrichment.d.ts.map +1 -0
  155. package/dist/service-enrichment.js +47 -0
  156. package/dist/service-external-refresh.d.ts +39 -0
  157. package/dist/service-external-refresh.d.ts.map +1 -0
  158. package/dist/service-external-refresh.js +47 -0
  159. package/dist/service-itinerary.d.ts +22 -0
  160. package/dist/service-itinerary.d.ts.map +1 -0
  161. package/dist/service-itinerary.js +34 -0
  162. package/dist/service-prices.d.ts +46 -0
  163. package/dist/service-prices.d.ts.map +1 -0
  164. package/dist/service-prices.js +89 -0
  165. package/dist/service-pricing.d.ts +97 -0
  166. package/dist/service-pricing.d.ts.map +1 -0
  167. package/dist/service-pricing.js +198 -0
  168. package/dist/service-sailings.d.ts +48 -0
  169. package/dist/service-sailings.d.ts.map +1 -0
  170. package/dist/service-sailings.js +145 -0
  171. package/dist/service-search-types.d.ts +54 -0
  172. package/dist/service-search-types.d.ts.map +1 -0
  173. package/dist/service-search-types.js +1 -0
  174. package/dist/service-search.d.ts +65 -0
  175. package/dist/service-search.d.ts.map +1 -0
  176. package/dist/service-search.js +467 -0
  177. package/dist/service-shared.d.ts +22 -0
  178. package/dist/service-shared.d.ts.map +1 -0
  179. package/dist/service-shared.js +22 -0
  180. package/dist/service-ships.d.ts +47 -0
  181. package/dist/service-ships.d.ts.map +1 -0
  182. package/dist/service-ships.js +156 -0
  183. package/dist/service.d.ts +255 -0
  184. package/dist/service.d.ts.map +1 -0
  185. package/dist/service.js +12 -0
  186. package/dist/validation-cabins.d.ts +267 -0
  187. package/dist/validation-cabins.d.ts.map +1 -0
  188. package/dist/validation-cabins.js +77 -0
  189. package/dist/validation-content.d.ts +123 -0
  190. package/dist/validation-content.d.ts.map +1 -0
  191. package/dist/validation-content.js +40 -0
  192. package/dist/validation-core.d.ts +393 -0
  193. package/dist/validation-core.d.ts.map +1 -0
  194. package/dist/validation-core.js +162 -0
  195. package/dist/validation-itinerary.d.ts +123 -0
  196. package/dist/validation-itinerary.d.ts.map +1 -0
  197. package/dist/validation-itinerary.js +47 -0
  198. package/dist/validation-pricing.d.ts +137 -0
  199. package/dist/validation-pricing.d.ts.map +1 -0
  200. package/dist/validation-pricing.js +49 -0
  201. package/dist/validation-search.d.ts +118 -0
  202. package/dist/validation-search.d.ts.map +1 -0
  203. package/dist/validation-search.js +60 -0
  204. package/dist/validation-shared.d.ts +123 -0
  205. package/dist/validation-shared.d.ts.map +1 -0
  206. package/dist/validation-shared.js +103 -0
  207. package/dist/validation.d.ts +8 -0
  208. package/dist/validation.d.ts.map +1 -0
  209. package/dist/validation.js +7 -0
  210. package/package.json +146 -0
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Owned-arm booking handler for the `cruises` vertical (Phase F
3
+ * skeleton).
4
+ *
5
+ * Per `docs/architecture/booking-journey-architecture.md` §6 +
6
+ * §7 (cruise example) + §10 Phase F.
7
+ *
8
+ * computeQuote scope:
9
+ * - Reads cruise content via the caller-supplied loader
10
+ * (`getCruiseContent`).
11
+ * - Projects to a `BookingDraftShape` with cabin-category +
12
+ * occupancy sub-steps via `buildCruiseDraftShape`.
13
+ * - When a sailing + cabin category + occupancy are picked,
14
+ * looks up the per-occupancy `cruise_prices` row and returns
15
+ * pricing as `pricePerPerson × paxCount`.
16
+ *
17
+ * commit scope:
18
+ * - Returns `failed:not_yet_implemented`. Cruises need a
19
+ * vertical-specific commit primitive (cabin allocation +
20
+ * supplier hold + air-add-on routing) that doesn't exist
21
+ * today. The shell renders the descriptor cleanly; commit
22
+ * lands separately.
23
+ */
24
+ import { buildCruiseDraftShape } from "../draft-shape.js";
25
+ export function createCruiseBookingHandler(options) {
26
+ return {
27
+ entityModule: "cruises",
28
+ // Cruise lines commonly hold cabin capacity for 24h after a
29
+ // journey times out (the "I'll be right back" pattern). Per
30
+ // booking-journey-architecture §12.9. Templates can override
31
+ // by replacing the handler at boot.
32
+ holdReleaseGraceMs: 24 * 60 * 60 * 1000,
33
+ async computeQuote(ctx, request) {
34
+ const content = await options.loadContent(ctx, request.entityId);
35
+ if (!content) {
36
+ return { available: false, invalidReason: "cruise_not_found" };
37
+ }
38
+ const shape = buildCruiseDraftShape(content, {
39
+ forceCabinNumberSubStep: options.forceCabinNumberSubStep,
40
+ includeInsurance: options.includeInsurance,
41
+ });
42
+ const draft = (request.draft ?? {});
43
+ const sailingId = draft.configure?.departureSlotId;
44
+ const cabinCategoryId = draft.configure?.cabinCategoryId;
45
+ const paxCount = sumPax(draft.configure?.pax);
46
+ // Pricing requires (sailing, category, occupancy). Until the
47
+ // user picks all three, return shape only — the wizard
48
+ // renders the steps and waits.
49
+ if (!sailingId || !cabinCategoryId || paxCount <= 0) {
50
+ return { available: true, shape };
51
+ }
52
+ const price = await options.loadPrice(ctx, {
53
+ entityId: request.entityId,
54
+ sailingId,
55
+ cabinCategoryId,
56
+ occupancy: paxCount,
57
+ });
58
+ if (!price) {
59
+ return {
60
+ available: false,
61
+ invalidReason: "no_price_for_occupancy",
62
+ shape,
63
+ };
64
+ }
65
+ const perPaxCents = priceStringToCents(price.pricePerPerson);
66
+ const totalCents = perPaxCents * paxCount;
67
+ return {
68
+ available: true,
69
+ shape,
70
+ pricing: {
71
+ base_amount: totalCents,
72
+ taxes: 0,
73
+ fees: 0,
74
+ surcharges: 0,
75
+ currency: price.currency,
76
+ breakdown: {
77
+ lines: [
78
+ {
79
+ kind: "base",
80
+ label: cabinCategoryLabel(content, cabinCategoryId, price.fareCode ?? null),
81
+ quantity: paxCount,
82
+ unitAmount: perPaxCents,
83
+ totalAmount: totalCents,
84
+ },
85
+ ],
86
+ subtotal: totalCents,
87
+ taxTotal: 0,
88
+ total: totalCents,
89
+ paxCount,
90
+ occupancy: paxCount,
91
+ sailingId,
92
+ cabinCategoryId,
93
+ fareCode: price.fareCode ?? null,
94
+ },
95
+ },
96
+ };
97
+ },
98
+ async commit(_ctx, request) {
99
+ if (!options.commitBridge) {
100
+ return {
101
+ status: "failed",
102
+ orderRef: "",
103
+ upstreamPayload: { reason: "cruise_commit_bridge_not_wired" },
104
+ };
105
+ }
106
+ const draft = (request.draft ?? {});
107
+ const sailingId = draft.configure?.departureSlotId;
108
+ const cabinCategoryId = draft.configure?.cabinCategoryId;
109
+ const cabinId = draft.configure?.cabinNumberId;
110
+ const occupancy = sumPax(draft.configure?.pax);
111
+ if (!sailingId || !cabinCategoryId || occupancy <= 0) {
112
+ return {
113
+ status: "failed",
114
+ orderRef: "",
115
+ upstreamPayload: {
116
+ reason: "cruise_commit_missing_inputs",
117
+ need: ["sailingId", "cabinCategoryId", "occupancy"],
118
+ },
119
+ };
120
+ }
121
+ const contact = {
122
+ firstName: draft.billing?.contact?.firstName ?? "",
123
+ lastName: draft.billing?.contact?.lastName ?? "",
124
+ email: draft.billing?.contact?.email ?? null,
125
+ phone: draft.billing?.contact?.phone ?? null,
126
+ };
127
+ const passengers = (draft.travelers ?? []).map((t) => ({
128
+ firstName: t.firstName,
129
+ lastName: t.lastName,
130
+ dateOfBirth: t.dateOfBirth ?? null,
131
+ travelerCategory: t.band === "child" || t.band === "infant"
132
+ ? t.band
133
+ : "adult",
134
+ }));
135
+ // The cruise commit primitive demands at least one passenger;
136
+ // if the journey didn't collect them, fall back to the lead
137
+ // contact as a single passenger so the commit doesn't reject
138
+ // outright. Operators using the journey for inquiry-style
139
+ // bookings can fill traveler details from the booking detail
140
+ // page later.
141
+ if (passengers.length === 0) {
142
+ passengers.push({
143
+ firstName: contact.firstName,
144
+ lastName: contact.lastName,
145
+ dateOfBirth: null,
146
+ travelerCategory: "adult",
147
+ });
148
+ }
149
+ const bridge = await options.commitBridge({
150
+ sailingId,
151
+ cabinCategoryId,
152
+ cabinId: cabinId ?? null,
153
+ occupancy,
154
+ fareCode: draft.configure?.variantId ?? null,
155
+ personId: extractPersonId(request.party),
156
+ organizationId: extractOrganizationId(request.party),
157
+ contact,
158
+ passengers,
159
+ airArrangement: draft.configure?.airArrangement ?? null,
160
+ notes: draft.internalNotes ?? null,
161
+ });
162
+ if (bridge.status !== "ok" || !bridge.bookingId) {
163
+ return {
164
+ status: "failed",
165
+ orderRef: "",
166
+ upstreamPayload: { reason: bridge.reason ?? "cruise_commit_failed" },
167
+ };
168
+ }
169
+ return {
170
+ status: "held",
171
+ orderRef: bridge.bookingNumber ?? bridge.bookingId,
172
+ pricing: request.pricing,
173
+ upstreamPayload: { bridgeBookingId: bridge.bookingId },
174
+ };
175
+ },
176
+ async placeHold(_ctx, request) {
177
+ const token = request.draftId ?? `cruise_${Date.now().toString(36)}`;
178
+ return {
179
+ holdToken: token,
180
+ expiresAt: new Date(Date.now() + request.ttlMs),
181
+ };
182
+ },
183
+ async releaseHold(_ctx, _holdToken) {
184
+ // No-op until supplier-side hold APIs are wired.
185
+ },
186
+ };
187
+ }
188
+ // ─────────────────────────────────────────────────────────────────
189
+ // Helpers
190
+ // ─────────────────────────────────────────────────────────────────
191
+ function sumPax(pax) {
192
+ if (!pax)
193
+ return 0;
194
+ let total = 0;
195
+ for (const v of Object.values(pax)) {
196
+ if (typeof v === "number" && Number.isFinite(v) && v > 0)
197
+ total += v;
198
+ }
199
+ return total;
200
+ }
201
+ function extractPersonId(party) {
202
+ if (!party)
203
+ return undefined;
204
+ const v = party.personId;
205
+ return typeof v === "string" && v.length > 0 ? v : undefined;
206
+ }
207
+ function extractOrganizationId(party) {
208
+ if (!party)
209
+ return undefined;
210
+ const v = party.organizationId;
211
+ return typeof v === "string" && v.length > 0 ? v : undefined;
212
+ }
213
+ function priceStringToCents(price) {
214
+ // cruise_prices.pricePerPerson is numeric(precision, scale). The
215
+ // major-unit string parses straight; round to integer cents.
216
+ const major = Number.parseFloat(price);
217
+ if (!Number.isFinite(major))
218
+ return 0;
219
+ return Math.round(major * 100);
220
+ }
221
+ function cabinCategoryLabel(content, categoryId, fareCode) {
222
+ const category = content.cabin_categories.find((c) => c.id === categoryId);
223
+ const base = category?.name ?? "Cabin";
224
+ return fareCode ? `${base} (${fareCode})` : base;
225
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `@voyant-travel/cruises/booking-engine` — owned-arm booking handler
3
+ * for the cruises vertical (Phase F skeleton).
4
+ *
5
+ * Per `docs/architecture/booking-journey-architecture.md` §6 + §10
6
+ * Phase F.
7
+ */
8
+ export { type CreateCruiseBookingHandlerOptions, type CruiseCommitBridge, type CruiseCommitBridgeInput, type CruiseCommitBridgeResult, type CruiseHandlerLoaders, createCruiseBookingHandler, type ResolvedCruisePrice, } from "./handler.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/booking-engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,iCAAiC,EACtC,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,KAAK,mBAAmB,GACzB,MAAM,cAAc,CAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `@voyant-travel/cruises/booking-engine` — owned-arm booking handler
3
+ * for the cruises vertical (Phase F skeleton).
4
+ *
5
+ * Per `docs/architecture/booking-journey-architecture.md` §6 + §10
6
+ * Phase F.
7
+ */
8
+ export { createCruiseBookingHandler, } from "./handler.js";