@voyant-travel/inventory 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/action-ledger-drift.d.ts +29 -0
- package/dist/action-ledger-drift.d.ts.map +1 -0
- package/dist/action-ledger-drift.js +338 -0
- package/dist/action-ledger.d.ts +104 -0
- package/dist/action-ledger.d.ts.map +1 -0
- package/dist/action-ledger.js +100 -0
- package/dist/authoring/builder.d.ts +37 -0
- package/dist/authoring/builder.d.ts.map +1 -0
- package/dist/authoring/builder.js +248 -0
- package/dist/authoring/clone-content.d.ts +38 -0
- package/dist/authoring/clone-content.d.ts.map +1 -0
- package/dist/authoring/clone-content.js +367 -0
- package/dist/authoring/clone-pricing.d.ts +9 -0
- package/dist/authoring/clone-pricing.d.ts.map +1 -0
- package/dist/authoring/clone-pricing.js +242 -0
- package/dist/authoring/clone.d.ts +45 -0
- package/dist/authoring/clone.d.ts.map +1 -0
- package/dist/authoring/clone.js +142 -0
- package/dist/authoring/errors.d.ts +21 -0
- package/dist/authoring/errors.d.ts.map +1 -0
- package/dist/authoring/errors.js +13 -0
- package/dist/authoring/extension.d.ts +248 -0
- package/dist/authoring/extension.d.ts.map +1 -0
- package/dist/authoring/extension.js +116 -0
- package/dist/authoring/index.d.ts +12 -0
- package/dist/authoring/index.d.ts.map +1 -0
- package/dist/authoring/index.js +11 -0
- package/dist/authoring/schema.d.ts +85 -0
- package/dist/authoring/schema.d.ts.map +1 -0
- package/dist/authoring/schema.js +16 -0
- package/dist/authoring/service.d.ts +28 -0
- package/dist/authoring/service.d.ts.map +1 -0
- package/dist/authoring/service.js +66 -0
- package/dist/authoring/spec.d.ts +524 -0
- package/dist/authoring/spec.d.ts.map +1 -0
- package/dist/authoring/spec.js +167 -0
- package/dist/authoring/validate.d.ts +17 -0
- package/dist/authoring/validate.d.ts.map +1 -0
- package/dist/authoring/validate.js +83 -0
- package/dist/authoring.d.ts +2 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.js +1 -0
- package/dist/booking-engine/handler-support.d.ts +91 -0
- package/dist/booking-engine/handler-support.d.ts.map +1 -0
- package/dist/booking-engine/handler-support.js +355 -0
- package/dist/booking-engine/handler.d.ts +404 -0
- package/dist/booking-engine/handler.d.ts.map +1 -0
- package/dist/booking-engine/handler.js +398 -0
- package/dist/booking-engine/index.d.ts +8 -0
- package/dist/booking-engine/index.d.ts.map +1 -0
- package/dist/booking-engine/index.js +7 -0
- package/dist/booking-engine.d.ts +2 -0
- package/dist/booking-engine.d.ts.map +1 -0
- package/dist/booking-engine.js +1 -0
- package/dist/booking-extension.d.ts +278 -0
- package/dist/booking-extension.d.ts.map +1 -0
- package/dist/booking-extension.js +161 -0
- package/dist/catalog-policy-departures.d.ts +52 -0
- package/dist/catalog-policy-departures.d.ts.map +1 -0
- package/dist/catalog-policy-departures.js +169 -0
- package/dist/catalog-policy-destinations.d.ts +43 -0
- package/dist/catalog-policy-destinations.d.ts.map +1 -0
- package/dist/catalog-policy-destinations.js +165 -0
- package/dist/catalog-policy-pricing.d.ts +55 -0
- package/dist/catalog-policy-pricing.d.ts.map +1 -0
- package/dist/catalog-policy-pricing.js +109 -0
- package/dist/catalog-policy-promotions.d.ts +52 -0
- package/dist/catalog-policy-promotions.d.ts.map +1 -0
- package/dist/catalog-policy-promotions.js +270 -0
- package/dist/catalog-policy-taxonomy.d.ts +51 -0
- package/dist/catalog-policy-taxonomy.d.ts.map +1 -0
- package/dist/catalog-policy-taxonomy.js +191 -0
- package/dist/catalog-policy.d.ts +33 -0
- package/dist/catalog-policy.d.ts.map +1 -0
- package/dist/catalog-policy.js +733 -0
- package/dist/content-shape.d.ts +15 -0
- package/dist/content-shape.d.ts.map +1 -0
- package/dist/content-shape.js +28 -0
- package/dist/draft-shape.d.ts +43 -0
- package/dist/draft-shape.d.ts.map +1 -0
- package/dist/draft-shape.js +48 -0
- package/dist/events.d.ts +37 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +32 -0
- package/dist/extras/catalog-policy.d.ts +30 -0
- package/dist/extras/catalog-policy.d.ts.map +1 -0
- package/dist/extras/catalog-policy.js +319 -0
- package/dist/extras/content-shape.d.ts +5 -0
- package/dist/extras/content-shape.d.ts.map +1 -0
- package/dist/extras/content-shape.js +13 -0
- package/dist/extras/draft-shape.d.ts +34 -0
- package/dist/extras/draft-shape.d.ts.map +1 -0
- package/dist/extras/draft-shape.js +69 -0
- package/dist/extras/routes.d.ts +380 -0
- package/dist/extras/routes.d.ts.map +1 -0
- package/dist/extras/routes.js +59 -0
- package/dist/extras/schema-sourced-content.d.ts +254 -0
- package/dist/extras/schema-sourced-content.d.ts.map +1 -0
- package/dist/extras/schema-sourced-content.js +45 -0
- package/dist/extras/schema.d.ts +628 -0
- package/dist/extras/schema.d.ts.map +1 -0
- package/dist/extras/schema.js +87 -0
- package/dist/extras/service-catalog-plane.d.ts +77 -0
- package/dist/extras/service-catalog-plane.d.ts.map +1 -0
- package/dist/extras/service-catalog-plane.js +219 -0
- package/dist/extras/service-content-synthesizer.d.ts +41 -0
- package/dist/extras/service-content-synthesizer.d.ts.map +1 -0
- package/dist/extras/service-content-synthesizer.js +138 -0
- package/dist/extras/service-content.d.ts +48 -0
- package/dist/extras/service-content.d.ts.map +1 -0
- package/dist/extras/service-content.js +253 -0
- package/dist/extras/service.d.ts +185 -0
- package/dist/extras/service.d.ts.map +1 -0
- package/dist/extras/service.js +96 -0
- package/dist/extras/validation.d.ts +437 -0
- package/dist/extras/validation.d.ts.map +1 -0
- package/dist/extras/validation.js +149 -0
- package/dist/extras.d.ts +267 -0
- package/dist/extras.d.ts.map +1 -0
- package/dist/extras.js +19 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/interface.d.ts +5869 -0
- package/dist/interface.d.ts.map +1 -0
- package/dist/interface.js +54 -0
- package/dist/public-routes.d.ts +2 -0
- package/dist/public-routes.d.ts.map +1 -0
- package/dist/public-routes.js +1 -0
- package/dist/public-validation.d.ts +2 -0
- package/dist/public-validation.d.ts.map +1 -0
- package/dist/public-validation.js +1 -0
- package/dist/read-model.d.ts +25 -0
- package/dist/read-model.d.ts.map +1 -0
- package/dist/read-model.js +99 -0
- package/dist/route-env.d.ts +22 -0
- package/dist/route-env.d.ts.map +1 -0
- package/dist/route-env.js +1 -0
- package/dist/routes-associations.d.ts +164 -0
- package/dist/routes-associations.d.ts.map +1 -0
- package/dist/routes-associations.js +100 -0
- package/dist/routes-catalog.d.ts +436 -0
- package/dist/routes-catalog.d.ts.map +1 -0
- package/dist/routes-catalog.js +104 -0
- package/dist/routes-configuration.d.ts +773 -0
- package/dist/routes-configuration.d.ts.map +1 -0
- package/dist/routes-configuration.js +364 -0
- package/dist/routes-content.d.ts +74 -0
- package/dist/routes-content.d.ts.map +1 -0
- package/dist/routes-content.js +117 -0
- package/dist/routes-core.d.ts +331 -0
- package/dist/routes-core.d.ts.map +1 -0
- package/dist/routes-core.js +95 -0
- package/dist/routes-itinerary.d.ts +759 -0
- package/dist/routes-itinerary.d.ts.map +1 -0
- package/dist/routes-itinerary.js +387 -0
- package/dist/routes-maintenance.d.ts +32 -0
- package/dist/routes-maintenance.d.ts.map +1 -0
- package/dist/routes-maintenance.js +14 -0
- package/dist/routes-media.d.ts +634 -0
- package/dist/routes-media.d.ts.map +1 -0
- package/dist/routes-media.js +245 -0
- package/dist/routes-merchandising.d.ts +1120 -0
- package/dist/routes-merchandising.d.ts.map +1 -0
- package/dist/routes-merchandising.js +377 -0
- package/dist/routes-options.d.ts +363 -0
- package/dist/routes-options.d.ts.map +1 -0
- package/dist/routes-options.js +173 -0
- package/dist/routes-public.d.ts +776 -0
- package/dist/routes-public.d.ts.map +1 -0
- package/dist/routes-public.js +119 -0
- package/dist/routes-translations.d.ts +489 -0
- package/dist/routes-translations.d.ts.map +1 -0
- package/dist/routes-translations.js +258 -0
- package/dist/routes.d.ts +5097 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +64 -0
- package/dist/schema-core.d.ts +1238 -0
- package/dist/schema-core.d.ts.map +1 -0
- package/dist/schema-core.js +157 -0
- package/dist/schema-itinerary.d.ts +1169 -0
- package/dist/schema-itinerary.d.ts.map +1 -0
- package/dist/schema-itinerary.js +130 -0
- package/dist/schema-relations.d.ts +117 -0
- package/dist/schema-relations.d.ts.map +1 -0
- package/dist/schema-relations.js +192 -0
- package/dist/schema-settings.d.ts +1800 -0
- package/dist/schema-settings.d.ts.map +1 -0
- package/dist/schema-settings.js +220 -0
- package/dist/schema-shared.d.ts +15 -0
- package/dist/schema-shared.d.ts.map +1 -0
- package/dist/schema-shared.js +91 -0
- package/dist/schema-sourced-content.d.ts +262 -0
- package/dist/schema-sourced-content.d.ts.map +1 -0
- package/dist/schema-sourced-content.js +69 -0
- package/dist/schema-taxonomy.d.ts +1363 -0
- package/dist/schema-taxonomy.d.ts.map +1 -0
- package/dist/schema-taxonomy.js +203 -0
- package/dist/schema.d.ts +10 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +9 -0
- package/dist/service-aggregates.d.ts +29 -0
- package/dist/service-aggregates.d.ts.map +1 -0
- package/dist/service-aggregates.js +56 -0
- package/dist/service-catalog-plane-destinations.d.ts +30 -0
- package/dist/service-catalog-plane-destinations.d.ts.map +1 -0
- package/dist/service-catalog-plane-destinations.js +143 -0
- package/dist/service-catalog-plane-taxonomy.d.ts +73 -0
- package/dist/service-catalog-plane-taxonomy.d.ts.map +1 -0
- package/dist/service-catalog-plane-taxonomy.js +242 -0
- package/dist/service-catalog-plane.d.ts +179 -0
- package/dist/service-catalog-plane.d.ts.map +1 -0
- package/dist/service-catalog-plane.js +431 -0
- package/dist/service-catalog.d.ts +251 -0
- package/dist/service-catalog.d.ts.map +1 -0
- package/dist/service-catalog.js +517 -0
- package/dist/service-configuration.d.ts +261 -0
- package/dist/service-configuration.d.ts.map +1 -0
- package/dist/service-configuration.js +343 -0
- package/dist/service-content-owned.d.ts +68 -0
- package/dist/service-content-owned.d.ts.map +1 -0
- package/dist/service-content-owned.js +329 -0
- package/dist/service-content-synthesizer.d.ts +90 -0
- package/dist/service-content-synthesizer.d.ts.map +1 -0
- package/dist/service-content-synthesizer.js +178 -0
- package/dist/service-content.d.ts +106 -0
- package/dist/service-content.d.ts.map +1 -0
- package/dist/service-content.js +388 -0
- package/dist/service-core.d.ts +194 -0
- package/dist/service-core.d.ts.map +1 -0
- package/dist/service-core.js +213 -0
- package/dist/service-delivery-formats.d.ts +58 -0
- package/dist/service-delivery-formats.d.ts.map +1 -0
- package/dist/service-delivery-formats.js +107 -0
- package/dist/service-destinations.d.ts +223 -0
- package/dist/service-destinations.d.ts.map +1 -0
- package/dist/service-destinations.js +310 -0
- package/dist/service-itinerary-history.d.ts +457 -0
- package/dist/service-itinerary-history.d.ts.map +1 -0
- package/dist/service-itinerary-history.js +135 -0
- package/dist/service-itinerary.d.ts +1149 -0
- package/dist/service-itinerary.d.ts.map +1 -0
- package/dist/service-itinerary.js +419 -0
- package/dist/service-media.d.ts +272 -0
- package/dist/service-media.d.ts.map +1 -0
- package/dist/service-media.js +320 -0
- package/dist/service-merchandising.d.ts +184 -0
- package/dist/service-merchandising.d.ts.map +1 -0
- package/dist/service-merchandising.js +181 -0
- package/dist/service-option-translations.d.ts +268 -0
- package/dist/service-option-translations.d.ts.map +1 -0
- package/dist/service-option-translations.js +300 -0
- package/dist/service-options.d.ts +181 -0
- package/dist/service-options.d.ts.map +1 -0
- package/dist/service-options.js +179 -0
- package/dist/service-product-destinations.d.ts +37 -0
- package/dist/service-product-destinations.d.ts.map +1 -0
- package/dist/service-product-destinations.js +94 -0
- package/dist/service-public.d.ts +664 -0
- package/dist/service-public.d.ts.map +1 -0
- package/dist/service-public.js +374 -0
- package/dist/service-taxonomy.d.ts +197 -0
- package/dist/service-taxonomy.d.ts.map +1 -0
- package/dist/service-taxonomy.js +221 -0
- package/dist/service.d.ts +3929 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +28 -0
- package/dist/tasks/brochure-printers.d.ts +31 -0
- package/dist/tasks/brochure-printers.d.ts.map +1 -0
- package/dist/tasks/brochure-printers.js +149 -0
- package/dist/tasks/brochure-templates.d.ts +36 -0
- package/dist/tasks/brochure-templates.d.ts.map +1 -0
- package/dist/tasks/brochure-templates.js +110 -0
- package/dist/tasks/brochures.d.ts +43 -0
- package/dist/tasks/brochures.d.ts.map +1 -0
- package/dist/tasks/brochures.js +72 -0
- package/dist/tasks/generate-pdf.d.ts +8 -0
- package/dist/tasks/generate-pdf.d.ts.map +1 -0
- package/dist/tasks/generate-pdf.js +106 -0
- package/dist/tasks/index.d.ts +5 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +4 -0
- package/dist/tasks/pdf-text.d.ts +2 -0
- package/dist/tasks/pdf-text.d.ts.map +1 -0
- package/dist/tasks/pdf-text.js +40 -0
- package/dist/tasks.d.ts +2 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +1 -0
- package/dist/validation-catalog.d.ts +2 -0
- package/dist/validation-catalog.d.ts.map +1 -0
- package/dist/validation-catalog.js +3 -0
- package/dist/validation-config.d.ts +2 -0
- package/dist/validation-config.d.ts.map +1 -0
- package/dist/validation-config.js +3 -0
- package/dist/validation-content.d.ts +2 -0
- package/dist/validation-content.d.ts.map +1 -0
- package/dist/validation-content.js +3 -0
- package/dist/validation-core.d.ts +2 -0
- package/dist/validation-core.d.ts.map +1 -0
- package/dist/validation-core.js +3 -0
- package/dist/validation-public.d.ts +2 -0
- package/dist/validation-public.d.ts.map +1 -0
- package/dist/validation-public.js +3 -0
- package/dist/validation-shared.d.ts +2 -0
- package/dist/validation-shared.d.ts.map +1 -0
- package/dist/validation-shared.js +3 -0
- package/dist/validation.d.ts +2 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +3 -0
- package/package.json +204 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ContentOverlay, type MergeOverlaysOptions } from "@voyant-travel/catalog";
|
|
2
|
+
import { type ProductContent } from "@voyant-travel/products-contracts/content-shape";
|
|
3
|
+
export { BOARD_BASIS_FROM_SHORT_CODE, BOARD_BASIS_SHORT_CODES, BOARD_BASIS_VALUES, type BoardBasis, type BoardBasisShortCode, boardBasisSchema, PRODUCTS_CONTENT_SCHEMA_VERSION, type ProductContent, type ProductDay, type ProductDeparture, type ProductMediaItem, type ProductOption, type ProductPolicy, type ProductSummary, productContentSchema, productDaySchema, productDepartureSchema, productMediaItemSchema, productOptionSchema, productOptionUnitSchema, productPolicySchema, productSummarySchema, validateProductContent, } from "@voyant-travel/products-contracts/content-shape";
|
|
4
|
+
/**
|
|
5
|
+
* Apply a list of editorial overlays to a product content payload via
|
|
6
|
+
* RFC 6901 JSON pointers. Validates the merged result against the
|
|
7
|
+
* vertical's Zod schema; overlays that produce an invalid payload are
|
|
8
|
+
* rolled back and reported via `onOverlayError`.
|
|
9
|
+
*
|
|
10
|
+
* Per sourced-content §3.5.4, this is the "content-shape-aware merger"
|
|
11
|
+
* — the catalog plane stays neutral about the content shape; the
|
|
12
|
+
* vertical plugs in its validator here.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeOverlaysIntoProductContent(payload: ProductContent, overlays: ReadonlyArray<ContentOverlay>, options?: Pick<MergeOverlaysOptions, "onOverlayError">): ProductContent;
|
|
15
|
+
//# sourceMappingURL=content-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-shape.d.ts","sourceRoot":"","sources":["../src/content-shape.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,iDAAiD,CAAA;AAExD,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,gBAAgB,EAChB,+BAA+B,EAC/B,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,iDAAiD,CAAA;AAExD;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,EACvC,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,CAAM,GACzD,cAAc,CAchB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { mergeOverlaysIntoContent, } from "@voyant-travel/catalog";
|
|
2
|
+
import { productContentSchema, validateProductContent, } from "@voyant-travel/products-contracts/content-shape";
|
|
3
|
+
export { BOARD_BASIS_FROM_SHORT_CODE, BOARD_BASIS_SHORT_CODES, BOARD_BASIS_VALUES, boardBasisSchema, PRODUCTS_CONTENT_SCHEMA_VERSION, productContentSchema, productDaySchema, productDepartureSchema, productMediaItemSchema, productOptionSchema, productOptionUnitSchema, productPolicySchema, productSummarySchema, validateProductContent, } from "@voyant-travel/products-contracts/content-shape";
|
|
4
|
+
/**
|
|
5
|
+
* Apply a list of editorial overlays to a product content payload via
|
|
6
|
+
* RFC 6901 JSON pointers. Validates the merged result against the
|
|
7
|
+
* vertical's Zod schema; overlays that produce an invalid payload are
|
|
8
|
+
* rolled back and reported via `onOverlayError`.
|
|
9
|
+
*
|
|
10
|
+
* Per sourced-content §3.5.4, this is the "content-shape-aware merger"
|
|
11
|
+
* — the catalog plane stays neutral about the content shape; the
|
|
12
|
+
* vertical plugs in its validator here.
|
|
13
|
+
*/
|
|
14
|
+
export function mergeOverlaysIntoProductContent(payload, overlays, options = {}) {
|
|
15
|
+
const merged = mergeOverlaysIntoContent(payload, overlays, {
|
|
16
|
+
validate(p) {
|
|
17
|
+
const result = validateProductContent(p);
|
|
18
|
+
if (result.valid) {
|
|
19
|
+
return { valid: true };
|
|
20
|
+
}
|
|
21
|
+
return { valid: false, reason: result.reason };
|
|
22
|
+
},
|
|
23
|
+
onOverlayError: options.onOverlayError,
|
|
24
|
+
});
|
|
25
|
+
// The validator gates merges, so a successful merge always parses —
|
|
26
|
+
// re-parse here to satisfy the return type without an unsafe cast.
|
|
27
|
+
return productContentSchema.parse(merged);
|
|
28
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project a `ProductContent` payload into a `BookingDraftShape` so
|
|
3
|
+
* the journey wizard can render the correct sub-steps for a sourced
|
|
4
|
+
* product.
|
|
5
|
+
*
|
|
6
|
+
* Tour-style products typically need:
|
|
7
|
+
* - Configure: occupancy band selection (adult / child / infant)
|
|
8
|
+
* and optionally a date / departure picker if `days[]` carries
|
|
9
|
+
* scheduled departures.
|
|
10
|
+
* - Travelers: per-pax fields (first / last / email; passport when
|
|
11
|
+
* the supplier requires it — surfaced via overlay when known).
|
|
12
|
+
* - Product options: the product's own `options[]` projected as a
|
|
13
|
+
* configure sub-step, setting `draft.configure.variantId`.
|
|
14
|
+
*
|
|
15
|
+
* No accommodation sub-step today (multi-day tours w/ rooms route
|
|
16
|
+
* through accommodations, not products). Pricing flows through
|
|
17
|
+
* liveResolve at quote time, not the descriptor.
|
|
18
|
+
*
|
|
19
|
+
* See `docs/architecture/booking-journey-architecture.md` §3 + §F.
|
|
20
|
+
*/
|
|
21
|
+
import { type BookingDraftShape, type PaxBandSpec } from "@voyant-travel/catalog/booking-engine";
|
|
22
|
+
import type { ProductContent } from "./content-shape.js";
|
|
23
|
+
export interface BuildProductDraftShapeOptions {
|
|
24
|
+
/** Locale — used for option-label fallback. Defaults to `"en-GB"`. */
|
|
25
|
+
locale?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Override the default pax bands. Use when the supplier mandates
|
|
28
|
+
* specific age cutoffs (rare for tour products; common for cruises
|
|
29
|
+
* and family-oriented packages).
|
|
30
|
+
*/
|
|
31
|
+
paxBands?: ReadonlyArray<PaxBandSpec>;
|
|
32
|
+
/**
|
|
33
|
+
* Override the maximum total pax. Defaults to `paxBands` sum.
|
|
34
|
+
* Useful when supplier capacity is < combined band max (e.g. a
|
|
35
|
+
* 6-pax max party on a private tour).
|
|
36
|
+
*/
|
|
37
|
+
paxBandsAllowedTotal?: {
|
|
38
|
+
min: number;
|
|
39
|
+
max: number;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export declare function buildProductDraftShape(content: ProductContent, options?: BuildProductDraftShapeOptions): BookingDraftShape;
|
|
43
|
+
//# sourceMappingURL=draft-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-shape.d.ts","sourceRoot":"","sources":["../src/draft-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,KAAK,iBAAiB,EAKtB,KAAK,WAAW,EAEjB,MAAM,uCAAuC,CAAA;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,MAAM,WAAW,6BAA6B;IAC5C,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;IACrC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACpD;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,6BAAkC,GAC1C,iBAAiB,CA4BnB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project a `ProductContent` payload into a `BookingDraftShape` so
|
|
3
|
+
* the journey wizard can render the correct sub-steps for a sourced
|
|
4
|
+
* product.
|
|
5
|
+
*
|
|
6
|
+
* Tour-style products typically need:
|
|
7
|
+
* - Configure: occupancy band selection (adult / child / infant)
|
|
8
|
+
* and optionally a date / departure picker if `days[]` carries
|
|
9
|
+
* scheduled departures.
|
|
10
|
+
* - Travelers: per-pax fields (first / last / email; passport when
|
|
11
|
+
* the supplier requires it — surfaced via overlay when known).
|
|
12
|
+
* - Product options: the product's own `options[]` projected as a
|
|
13
|
+
* configure sub-step, setting `draft.configure.variantId`.
|
|
14
|
+
*
|
|
15
|
+
* No accommodation sub-step today (multi-day tours w/ rooms route
|
|
16
|
+
* through accommodations, not products). Pricing flows through
|
|
17
|
+
* liveResolve at quote time, not the descriptor.
|
|
18
|
+
*
|
|
19
|
+
* See `docs/architecture/booking-journey-architecture.md` §3 + §F.
|
|
20
|
+
*/
|
|
21
|
+
import { DEFAULT_PAX_BANDS, defaultBookingFields, defaultDraftShapeFlags, defaultTravelerFields, paxBandsAllowedTotalFrom, } from "@voyant-travel/catalog/booking-engine";
|
|
22
|
+
export function buildProductDraftShape(content, options = {}) {
|
|
23
|
+
const paxBands = options.paxBands ?? DEFAULT_PAX_BANDS;
|
|
24
|
+
const total = options.paxBandsAllowedTotal ?? paxBandsAllowedTotalFrom(paxBands);
|
|
25
|
+
const productOptions = content.options.map((opt) => ({
|
|
26
|
+
id: opt.id,
|
|
27
|
+
name: opt.name,
|
|
28
|
+
description: opt.description ?? null,
|
|
29
|
+
}));
|
|
30
|
+
return {
|
|
31
|
+
...defaultDraftShapeFlags(),
|
|
32
|
+
paxBands,
|
|
33
|
+
paxBandsAllowedTotal: total,
|
|
34
|
+
travelerFields: defaultTravelerFields(),
|
|
35
|
+
bookingFields: defaultBookingFields(),
|
|
36
|
+
paymentIntents: ["hold", "card"],
|
|
37
|
+
configureSubSteps: [
|
|
38
|
+
...(productOptions.length > 0
|
|
39
|
+
? [{ kind: "product-option", options: productOptions }]
|
|
40
|
+
: []),
|
|
41
|
+
// Owned products are scheduled — the operator picks a real departure.
|
|
42
|
+
// The journey renders an injected slot picker for this kind, falling
|
|
43
|
+
// back to a free date when the product has no scheduled departures.
|
|
44
|
+
{ kind: "departure", required: true },
|
|
45
|
+
{ kind: "occupancy", bands: paxBands },
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product domain events.
|
|
3
|
+
*
|
|
4
|
+
* Emitted by the products module on lifecycle and content changes.
|
|
5
|
+
* `product.content.changed` is the load-bearing channel-push signal —
|
|
6
|
+
* fired when ANY content axis (description, itinerary, media, options,
|
|
7
|
+
* days) changes.
|
|
8
|
+
*
|
|
9
|
+
* Per docs/architecture/channel-push-architecture.md §6.
|
|
10
|
+
*/
|
|
11
|
+
import type { EventBus } from "@voyant-travel/core";
|
|
12
|
+
/** Stable event identifier. */
|
|
13
|
+
export declare const PRODUCT_CONTENT_CHANGED_EVENT: "product.content.changed";
|
|
14
|
+
export interface ProductContentChangedEvent {
|
|
15
|
+
/** Product id whose content changed. */
|
|
16
|
+
id: string;
|
|
17
|
+
/**
|
|
18
|
+
* The content axis that changed, when known. Diagnostic only — channel
|
|
19
|
+
* push hashes the full current content at push time so this field is
|
|
20
|
+
* not load-bearing for correctness.
|
|
21
|
+
*/
|
|
22
|
+
axis?: "product" | "itinerary" | "option" | "day" | "media" | "feature" | "faq" | "location" | "destination" | "category" | "tag" | "translation";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Helper for route handlers / services to fire `product.content.changed`
|
|
26
|
+
* with a stable shape. Fire-and-forget per the EventBus contract; the
|
|
27
|
+
* caller does not await this if it's already on a hot path.
|
|
28
|
+
*
|
|
29
|
+
* v1 wiring: every product service/route mutation that touches a
|
|
30
|
+
* content-affecting field should call this helper. The top-level PATCH
|
|
31
|
+
* route already calls it (alongside the legacy `product.updated`); child
|
|
32
|
+
* routes can be wired incrementally. Until full coverage exists, the
|
|
33
|
+
* channel-push reconciler (§13) catches missed events by hashing
|
|
34
|
+
* current content per (product, channel).
|
|
35
|
+
*/
|
|
36
|
+
export declare function emitProductContentChanged(eventBus: EventBus | undefined, payload: ProductContentChangedEvent): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEnD,+BAA+B;AAC/B,eAAO,MAAM,6BAA6B,EAAG,yBAAkC,CAAA;AAE/E,MAAM,WAAW,0BAA0B;IACzC,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV;;;;OAIG;IACH,IAAI,CAAC,EACD,SAAS,GACT,WAAW,GACX,QAAQ,GACR,KAAK,GACL,OAAO,GACP,SAAS,GACT,KAAK,GACL,UAAU,GACV,aAAa,GACb,UAAU,GACV,KAAK,GACL,aAAa,CAAA;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAMf"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product domain events.
|
|
3
|
+
*
|
|
4
|
+
* Emitted by the products module on lifecycle and content changes.
|
|
5
|
+
* `product.content.changed` is the load-bearing channel-push signal —
|
|
6
|
+
* fired when ANY content axis (description, itinerary, media, options,
|
|
7
|
+
* days) changes.
|
|
8
|
+
*
|
|
9
|
+
* Per docs/architecture/channel-push-architecture.md §6.
|
|
10
|
+
*/
|
|
11
|
+
/** Stable event identifier. */
|
|
12
|
+
export const PRODUCT_CONTENT_CHANGED_EVENT = "product.content.changed";
|
|
13
|
+
/**
|
|
14
|
+
* Helper for route handlers / services to fire `product.content.changed`
|
|
15
|
+
* with a stable shape. Fire-and-forget per the EventBus contract; the
|
|
16
|
+
* caller does not await this if it's already on a hot path.
|
|
17
|
+
*
|
|
18
|
+
* v1 wiring: every product service/route mutation that touches a
|
|
19
|
+
* content-affecting field should call this helper. The top-level PATCH
|
|
20
|
+
* route already calls it (alongside the legacy `product.updated`); child
|
|
21
|
+
* routes can be wired incrementally. Until full coverage exists, the
|
|
22
|
+
* channel-push reconciler (§13) catches missed events by hashing
|
|
23
|
+
* current content per (product, channel).
|
|
24
|
+
*/
|
|
25
|
+
export async function emitProductContentChanged(eventBus, payload) {
|
|
26
|
+
if (!eventBus)
|
|
27
|
+
return;
|
|
28
|
+
await eventBus.emit(PRODUCT_CONTENT_CHANGED_EVENT, payload, {
|
|
29
|
+
category: "domain",
|
|
30
|
+
source: "service",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for `packages/extras`.
|
|
3
|
+
*
|
|
4
|
+
* Extras are booking add-ons (optional line items layered on a booked
|
|
5
|
+
* parent product) — **not independently sellable inventory**. Per
|
|
6
|
+
* architecture §3.3.1, extras are a partial-adoption vertical:
|
|
7
|
+
*
|
|
8
|
+
* - **Adopt:** provenance shape (§5.1), booking snapshot graph (§5.3),
|
|
9
|
+
* catalog event taxonomy for the cancellation/fulfillment lifecycle.
|
|
10
|
+
* - **Skip:** search index projection (§5.4), editorial overlay store
|
|
11
|
+
* (§5.2), embeddings / RAG (Phase 2). Extras are discovered through
|
|
12
|
+
* the parent's surface, not via standalone catalog browse.
|
|
13
|
+
*
|
|
14
|
+
* Most fields below have `reindex: "none"` because extras are primarily
|
|
15
|
+
* discovered through their parent product. The `thumbnailUrl` card-image
|
|
16
|
+
* projection is indexed for operator catalog search surfaces that opt
|
|
17
|
+
* extras into the shared catalog index.
|
|
18
|
+
*
|
|
19
|
+
* Scope of this file:
|
|
20
|
+
* - The `product_extras` table (extra catalog definitions).
|
|
21
|
+
*
|
|
22
|
+
* Out of scope:
|
|
23
|
+
* - `option_extra_configs` — option-level overrides; promoted child.
|
|
24
|
+
* - `booking_extras` — runtime line items on a booking; not catalog data.
|
|
25
|
+
*/
|
|
26
|
+
import { type FieldPolicyInput } from "@voyant-travel/catalog/contract";
|
|
27
|
+
declare const EXTRAS_FIELD_POLICY: FieldPolicyInput[];
|
|
28
|
+
export declare const extrasCatalogPolicy: import("@voyant-travel/catalog").FieldPolicy[];
|
|
29
|
+
export { EXTRAS_FIELD_POLICY };
|
|
30
|
+
//# sourceMappingURL=catalog-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-policy.d.ts","sourceRoot":"","sources":["../../src/extras/catalog-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAE1F,QAAA,MAAM,mBAAmB,EAAE,gBAAgB,EAsS1C,CAAA;AAED,eAAO,MAAM,mBAAmB,gDAAyC,CAAA;AAEzE,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for `packages/extras`.
|
|
3
|
+
*
|
|
4
|
+
* Extras are booking add-ons (optional line items layered on a booked
|
|
5
|
+
* parent product) — **not independently sellable inventory**. Per
|
|
6
|
+
* architecture §3.3.1, extras are a partial-adoption vertical:
|
|
7
|
+
*
|
|
8
|
+
* - **Adopt:** provenance shape (§5.1), booking snapshot graph (§5.3),
|
|
9
|
+
* catalog event taxonomy for the cancellation/fulfillment lifecycle.
|
|
10
|
+
* - **Skip:** search index projection (§5.4), editorial overlay store
|
|
11
|
+
* (§5.2), embeddings / RAG (Phase 2). Extras are discovered through
|
|
12
|
+
* the parent's surface, not via standalone catalog browse.
|
|
13
|
+
*
|
|
14
|
+
* Most fields below have `reindex: "none"` because extras are primarily
|
|
15
|
+
* discovered through their parent product. The `thumbnailUrl` card-image
|
|
16
|
+
* projection is indexed for operator catalog search surfaces that opt
|
|
17
|
+
* extras into the shared catalog index.
|
|
18
|
+
*
|
|
19
|
+
* Scope of this file:
|
|
20
|
+
* - The `product_extras` table (extra catalog definitions).
|
|
21
|
+
*
|
|
22
|
+
* Out of scope:
|
|
23
|
+
* - `option_extra_configs` — option-level overrides; promoted child.
|
|
24
|
+
* - `booking_extras` — runtime line items on a booking; not catalog data.
|
|
25
|
+
*/
|
|
26
|
+
import { defineFieldPolicy } from "@voyant-travel/catalog/contract";
|
|
27
|
+
const EXTRAS_FIELD_POLICY = [
|
|
28
|
+
// ── Source pointer / provenance ─────────────────────────────────────────
|
|
29
|
+
{
|
|
30
|
+
path: "source.kind",
|
|
31
|
+
class: "managed",
|
|
32
|
+
merge: "source-only",
|
|
33
|
+
drift: "critical",
|
|
34
|
+
reindex: "facet-affecting",
|
|
35
|
+
snapshot: "on-book",
|
|
36
|
+
query: "indexed-column",
|
|
37
|
+
localized: false,
|
|
38
|
+
visibility: ["staff"],
|
|
39
|
+
editRole: "none",
|
|
40
|
+
overrideFriction: "none",
|
|
41
|
+
sourceFreshness: "sync",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
path: "source.ref",
|
|
45
|
+
class: "managed",
|
|
46
|
+
merge: "source-only",
|
|
47
|
+
drift: "critical",
|
|
48
|
+
reindex: "none",
|
|
49
|
+
snapshot: "on-book",
|
|
50
|
+
query: "indexed-column",
|
|
51
|
+
localized: false,
|
|
52
|
+
visibility: ["staff"],
|
|
53
|
+
editRole: "none",
|
|
54
|
+
overrideFriction: "none",
|
|
55
|
+
sourceFreshness: "sync",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
path: "seller.operator_id",
|
|
59
|
+
class: "managed",
|
|
60
|
+
merge: "source-only",
|
|
61
|
+
drift: "critical",
|
|
62
|
+
reindex: "none",
|
|
63
|
+
snapshot: "on-book",
|
|
64
|
+
query: "indexed-column",
|
|
65
|
+
localized: false,
|
|
66
|
+
visibility: ["staff"],
|
|
67
|
+
editRole: "none",
|
|
68
|
+
overrideFriction: "none",
|
|
69
|
+
sourceFreshness: "static",
|
|
70
|
+
},
|
|
71
|
+
// ── Identity / lifecycle ────────────────────────────────────────────────
|
|
72
|
+
{
|
|
73
|
+
path: "id",
|
|
74
|
+
class: "managed",
|
|
75
|
+
merge: "source-only",
|
|
76
|
+
drift: "critical",
|
|
77
|
+
reindex: "none",
|
|
78
|
+
snapshot: "on-book",
|
|
79
|
+
query: "first-class-table",
|
|
80
|
+
localized: false,
|
|
81
|
+
visibility: ["staff", "customer", "partner"],
|
|
82
|
+
editRole: "none",
|
|
83
|
+
overrideFriction: "none",
|
|
84
|
+
sourceFreshness: "static",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
path: "code",
|
|
88
|
+
class: "managed",
|
|
89
|
+
merge: "source-only",
|
|
90
|
+
drift: "high",
|
|
91
|
+
reindex: "none",
|
|
92
|
+
snapshot: "on-book",
|
|
93
|
+
query: "indexed-column",
|
|
94
|
+
localized: false,
|
|
95
|
+
visibility: ["staff"],
|
|
96
|
+
editRole: "none",
|
|
97
|
+
overrideFriction: "none",
|
|
98
|
+
sourceFreshness: "sync",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
path: "createdAt",
|
|
102
|
+
class: "managed",
|
|
103
|
+
merge: "source-only",
|
|
104
|
+
drift: "none",
|
|
105
|
+
reindex: "none",
|
|
106
|
+
snapshot: "on-book",
|
|
107
|
+
query: "indexed-column",
|
|
108
|
+
localized: false,
|
|
109
|
+
visibility: ["staff"],
|
|
110
|
+
editRole: "none",
|
|
111
|
+
overrideFriction: "none",
|
|
112
|
+
sourceFreshness: "static",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
path: "updatedAt",
|
|
116
|
+
class: "managed",
|
|
117
|
+
merge: "source-only",
|
|
118
|
+
drift: "none",
|
|
119
|
+
reindex: "none",
|
|
120
|
+
snapshot: "never",
|
|
121
|
+
query: "indexed-column",
|
|
122
|
+
localized: false,
|
|
123
|
+
visibility: ["staff"],
|
|
124
|
+
editRole: "none",
|
|
125
|
+
overrideFriction: "none",
|
|
126
|
+
sourceFreshness: "sync",
|
|
127
|
+
},
|
|
128
|
+
// ── Cross-module reference (the parent product the extra attaches to) ──
|
|
129
|
+
{
|
|
130
|
+
path: "productId",
|
|
131
|
+
class: "managed",
|
|
132
|
+
merge: "source-only",
|
|
133
|
+
drift: "critical",
|
|
134
|
+
reindex: "none",
|
|
135
|
+
snapshot: "on-book",
|
|
136
|
+
query: "indexed-column",
|
|
137
|
+
localized: false,
|
|
138
|
+
visibility: ["staff"],
|
|
139
|
+
editRole: "none",
|
|
140
|
+
overrideFriction: "none",
|
|
141
|
+
sourceFreshness: "sync",
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
path: "supplierId",
|
|
145
|
+
class: "structural",
|
|
146
|
+
merge: "source-only",
|
|
147
|
+
drift: "high",
|
|
148
|
+
reindex: "none",
|
|
149
|
+
snapshot: "on-book",
|
|
150
|
+
query: "indexed-column",
|
|
151
|
+
localized: false,
|
|
152
|
+
visibility: ["staff"],
|
|
153
|
+
editRole: "none",
|
|
154
|
+
overrideFriction: "none",
|
|
155
|
+
sourceFreshness: "sync",
|
|
156
|
+
},
|
|
157
|
+
// ── Snapshot-relevant managed fields ────────────────────────────────────
|
|
158
|
+
// Extras' name/description aren't merchandised standalone — they're
|
|
159
|
+
// shown inside the parent product's add-on UI. Marked as managed for
|
|
160
|
+
// simplicity; if a future case requires marketing overrides on extras'
|
|
161
|
+
// names, this can be promoted to merchandisable.
|
|
162
|
+
{
|
|
163
|
+
path: "name",
|
|
164
|
+
class: "managed",
|
|
165
|
+
merge: "source-only",
|
|
166
|
+
drift: "medium",
|
|
167
|
+
reindex: "none",
|
|
168
|
+
snapshot: "on-book",
|
|
169
|
+
query: "indexed-column",
|
|
170
|
+
localized: false,
|
|
171
|
+
visibility: ["staff", "customer", "partner"],
|
|
172
|
+
editRole: "none",
|
|
173
|
+
overrideFriction: "none",
|
|
174
|
+
sourceFreshness: "sync",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
path: "description",
|
|
178
|
+
class: "managed",
|
|
179
|
+
merge: "source-only",
|
|
180
|
+
drift: "low",
|
|
181
|
+
reindex: "none",
|
|
182
|
+
snapshot: "on-book",
|
|
183
|
+
query: "blob-only",
|
|
184
|
+
localized: false,
|
|
185
|
+
visibility: ["staff", "customer", "partner"],
|
|
186
|
+
editRole: "none",
|
|
187
|
+
overrideFriction: "none",
|
|
188
|
+
sourceFreshness: "sync",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
path: "thumbnailUrl",
|
|
192
|
+
class: "merchandisable",
|
|
193
|
+
merge: "source-only",
|
|
194
|
+
drift: "low",
|
|
195
|
+
reindex: "entry",
|
|
196
|
+
snapshot: "on-book",
|
|
197
|
+
query: "indexed-column",
|
|
198
|
+
localized: false,
|
|
199
|
+
visibility: ["staff", "customer", "partner"],
|
|
200
|
+
editRole: "none",
|
|
201
|
+
overrideFriction: "none",
|
|
202
|
+
sourceFreshness: "sync",
|
|
203
|
+
},
|
|
204
|
+
// ── Selection / pricing structure (snapshotted at book time) ───────────
|
|
205
|
+
{
|
|
206
|
+
path: "selectionType",
|
|
207
|
+
class: "structural",
|
|
208
|
+
merge: "source-only",
|
|
209
|
+
drift: "high",
|
|
210
|
+
reindex: "none",
|
|
211
|
+
snapshot: "on-book",
|
|
212
|
+
query: "indexed-column",
|
|
213
|
+
localized: false,
|
|
214
|
+
visibility: ["staff", "customer", "partner"],
|
|
215
|
+
editRole: "none",
|
|
216
|
+
overrideFriction: "none",
|
|
217
|
+
sourceFreshness: "sync",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
path: "pricingMode",
|
|
221
|
+
class: "structural",
|
|
222
|
+
merge: "source-only",
|
|
223
|
+
drift: "high",
|
|
224
|
+
reindex: "none",
|
|
225
|
+
snapshot: "on-quote-and-book",
|
|
226
|
+
query: "indexed-column",
|
|
227
|
+
localized: false,
|
|
228
|
+
visibility: ["staff", "customer", "partner"],
|
|
229
|
+
editRole: "none",
|
|
230
|
+
overrideFriction: "none",
|
|
231
|
+
sourceFreshness: "sync",
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
path: "pricedPerPerson",
|
|
235
|
+
class: "structural",
|
|
236
|
+
merge: "source-only",
|
|
237
|
+
drift: "high",
|
|
238
|
+
reindex: "none",
|
|
239
|
+
snapshot: "on-quote-and-book",
|
|
240
|
+
query: "indexed-column",
|
|
241
|
+
localized: false,
|
|
242
|
+
visibility: ["staff", "customer", "partner"],
|
|
243
|
+
editRole: "none",
|
|
244
|
+
overrideFriction: "none",
|
|
245
|
+
sourceFreshness: "sync",
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
path: "minQuantity",
|
|
249
|
+
class: "structural",
|
|
250
|
+
merge: "source-only",
|
|
251
|
+
drift: "medium",
|
|
252
|
+
reindex: "none",
|
|
253
|
+
snapshot: "on-book",
|
|
254
|
+
query: "indexed-column",
|
|
255
|
+
localized: false,
|
|
256
|
+
visibility: ["staff", "customer", "partner"],
|
|
257
|
+
editRole: "none",
|
|
258
|
+
overrideFriction: "none",
|
|
259
|
+
sourceFreshness: "sync",
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
path: "maxQuantity",
|
|
263
|
+
class: "structural",
|
|
264
|
+
merge: "source-only",
|
|
265
|
+
drift: "medium",
|
|
266
|
+
reindex: "none",
|
|
267
|
+
snapshot: "on-book",
|
|
268
|
+
query: "indexed-column",
|
|
269
|
+
localized: false,
|
|
270
|
+
visibility: ["staff", "customer", "partner"],
|
|
271
|
+
editRole: "none",
|
|
272
|
+
overrideFriction: "none",
|
|
273
|
+
sourceFreshness: "sync",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
path: "defaultQuantity",
|
|
277
|
+
class: "structural",
|
|
278
|
+
merge: "source-only",
|
|
279
|
+
drift: "low",
|
|
280
|
+
reindex: "none",
|
|
281
|
+
snapshot: "on-book",
|
|
282
|
+
query: "indexed-column",
|
|
283
|
+
localized: false,
|
|
284
|
+
visibility: ["staff", "customer", "partner"],
|
|
285
|
+
editRole: "none",
|
|
286
|
+
overrideFriction: "none",
|
|
287
|
+
sourceFreshness: "sync",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
path: "active",
|
|
291
|
+
class: "structural",
|
|
292
|
+
merge: "source-only",
|
|
293
|
+
drift: "high",
|
|
294
|
+
reindex: "none",
|
|
295
|
+
snapshot: "on-book",
|
|
296
|
+
query: "indexed-column",
|
|
297
|
+
localized: false,
|
|
298
|
+
visibility: ["staff"],
|
|
299
|
+
editRole: "none",
|
|
300
|
+
overrideFriction: "none",
|
|
301
|
+
sourceFreshness: "sync",
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
path: "sortOrder",
|
|
305
|
+
class: "structural",
|
|
306
|
+
merge: "source-only",
|
|
307
|
+
drift: "none",
|
|
308
|
+
reindex: "none",
|
|
309
|
+
snapshot: "never",
|
|
310
|
+
query: "indexed-column",
|
|
311
|
+
localized: false,
|
|
312
|
+
visibility: ["staff"],
|
|
313
|
+
editRole: "ops",
|
|
314
|
+
overrideFriction: "none",
|
|
315
|
+
sourceFreshness: "sync",
|
|
316
|
+
},
|
|
317
|
+
];
|
|
318
|
+
export const extrasCatalogPolicy = defineFieldPolicy(EXTRAS_FIELD_POLICY);
|
|
319
|
+
export { EXTRAS_FIELD_POLICY };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ContentOverlay, type MergeOverlaysOptions } from "@voyant-travel/catalog";
|
|
2
|
+
import { type ExtraContent } from "@voyant-travel/extras-contracts/content-shape";
|
|
3
|
+
export { EXTRAS_CONTENT_SCHEMA_VERSION, type ExtraContent, type ExtraMediaItem, type ExtraOption, type ExtraPolicy, type ExtraSummary, extraContentSchema, extraMediaItemSchema, extraOptionSchema, extraPolicySchema, extraSummarySchema, validateExtraContent, } from "@voyant-travel/extras-contracts/content-shape";
|
|
4
|
+
export declare function mergeOverlaysIntoExtraContent(payload: ExtraContent, overlays: ReadonlyArray<ContentOverlay>, options?: Pick<MergeOverlaysOptions, "onOverlayError">): ExtraContent;
|
|
5
|
+
//# sourceMappingURL=content-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-shape.d.ts","sourceRoot":"","sources":["../../src/extras/content-shape.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,+CAA+C,CAAA;AAEtD,OAAO,EACL,6BAA6B,EAC7B,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,+CAA+C,CAAA;AAEtD,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,EACvC,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,CAAM,GACzD,YAAY,CASd"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { mergeOverlaysIntoContent, } from "@voyant-travel/catalog";
|
|
2
|
+
import { extraContentSchema, validateExtraContent, } from "@voyant-travel/extras-contracts/content-shape";
|
|
3
|
+
export { EXTRAS_CONTENT_SCHEMA_VERSION, extraContentSchema, extraMediaItemSchema, extraOptionSchema, extraPolicySchema, extraSummarySchema, validateExtraContent, } from "@voyant-travel/extras-contracts/content-shape";
|
|
4
|
+
export function mergeOverlaysIntoExtraContent(payload, overlays, options = {}) {
|
|
5
|
+
const merged = mergeOverlaysIntoContent(payload, overlays, {
|
|
6
|
+
validate(p) {
|
|
7
|
+
const r = validateExtraContent(p);
|
|
8
|
+
return r.valid ? { valid: true } : { valid: false, reason: r.reason };
|
|
9
|
+
},
|
|
10
|
+
onOverlayError: options.onOverlayError,
|
|
11
|
+
});
|
|
12
|
+
return extraContentSchema.parse(merged);
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project an `ExtraContent` payload into a `BookingDraftShape`.
|
|
3
|
+
*
|
|
4
|
+
* Extras are booking add-ons (excursions, transfers, insurance) —
|
|
5
|
+
* they're never standalone bookable on their own; they always layer
|
|
6
|
+
* onto a parent product. So the descriptor here is **degenerate**:
|
|
7
|
+
*
|
|
8
|
+
* - `showsConfigure: false` (no configure step — extras are picked
|
|
9
|
+
* during the parent product's add-on step).
|
|
10
|
+
* - `showsTravelers: false` (extras don't have their own pax flow).
|
|
11
|
+
* - `showsPayment: false` (extras roll up into the parent's pricing).
|
|
12
|
+
* - `addons.catalog`: the extra itself + its sub-options projected
|
|
13
|
+
* as a small catalog. Useful for journey contexts that want to
|
|
14
|
+
* render an add-on detail view (e.g. ops admin reviewing a
|
|
15
|
+
* supplier's extras).
|
|
16
|
+
*
|
|
17
|
+
* In practice templates rarely call this directly — the parent
|
|
18
|
+
* product's `BookingDraftShape` aggregates extras via the journey's
|
|
19
|
+
* cross-product composer. This function is the building block.
|
|
20
|
+
*/
|
|
21
|
+
import { type BookingDraftShape } from "@voyant-travel/catalog/booking-engine";
|
|
22
|
+
import type { ExtraContent } from "./content-shape.js";
|
|
23
|
+
export interface BuildExtraDraftShapeOptions {
|
|
24
|
+
locale?: string;
|
|
25
|
+
/**
|
|
26
|
+
* When true, returns the full descriptor surface (configure +
|
|
27
|
+
* travelers + payment all visible). Useful for tests or admin
|
|
28
|
+
* surfaces that render extras standalone. Defaults to false (the
|
|
29
|
+
* normal "extras-as-addon" mode).
|
|
30
|
+
*/
|
|
31
|
+
standalone?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function buildExtraDraftShape(content: ExtraContent, options?: BuildExtraDraftShapeOptions): BookingDraftShape;
|
|
34
|
+
//# sourceMappingURL=draft-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draft-shape.d.ts","sourceRoot":"","sources":["../../src/extras/draft-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAEL,KAAK,iBAAiB,EAMvB,MAAM,uCAAuC,CAAA;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAMtD,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,GAAE,2BAAgC,GACxC,iBAAiB,CAsCnB"}
|