@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,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for product → destination denormalization.
|
|
3
|
+
*
|
|
4
|
+
* These fields don't live on the `products` table — they're joined from
|
|
5
|
+
* `product_destinations` → `destinations` (+ `destination_translations` for
|
|
6
|
+
* locale-aware names) at index time and projected onto the product search
|
|
7
|
+
* document. See `docs/architecture/catalog-architecture.md` §5.4 — the
|
|
8
|
+
* search index is the canonical place for cross-entity denormalization.
|
|
9
|
+
*
|
|
10
|
+
* Storefront product cards filter and display by destinations:
|
|
11
|
+
* - "trips to Italy" (filter: `countries[]` includes "Italy")
|
|
12
|
+
* - "trips in Rome" (filter: `cities[]` includes "Rome")
|
|
13
|
+
* - "Mediterranean cruises" (filter: `regions[]` includes "Mediterranean")
|
|
14
|
+
* - "cruises from Amsterdam" (filter: `ports[]` or canonical place ids)
|
|
15
|
+
*
|
|
16
|
+
* Wire this policy into the products registry by composing with
|
|
17
|
+
* `productCatalogPolicy`:
|
|
18
|
+
*
|
|
19
|
+
* const registry = createFieldPolicyRegistry([
|
|
20
|
+
* ...productCatalogPolicy,
|
|
21
|
+
* ...productDestinationsCatalogPolicy,
|
|
22
|
+
* ])
|
|
23
|
+
*
|
|
24
|
+
* and wire `createProductDestinationsProjectionExtension` into
|
|
25
|
+
* `createProductDocumentBuilder` so the values land in the doc.
|
|
26
|
+
*
|
|
27
|
+
* Destination rows can carry canonical place ids (for example UN/LOCODE)
|
|
28
|
+
* and optional display coordinates. The gazetteer itself remains external;
|
|
29
|
+
* this module stores stable pointers/snapshots for faceting.
|
|
30
|
+
*
|
|
31
|
+
* Out of scope here:
|
|
32
|
+
* - Slug fields per locale. Destinations have one canonical slug today;
|
|
33
|
+
* locale-specific slugs are a follow-up if marketing needs them.
|
|
34
|
+
*/
|
|
35
|
+
import { type FieldPolicyInput } from "@voyant-travel/catalog/contract";
|
|
36
|
+
declare const PRODUCT_DESTINATIONS_FIELD_POLICY: FieldPolicyInput[];
|
|
37
|
+
/**
|
|
38
|
+
* Resolved destinations policy. Compose with `productCatalogPolicy` when
|
|
39
|
+
* building the products registry.
|
|
40
|
+
*/
|
|
41
|
+
export declare const productDestinationsCatalogPolicy: import("@voyant-travel/catalog").FieldPolicy[];
|
|
42
|
+
export { PRODUCT_DESTINATIONS_FIELD_POLICY };
|
|
43
|
+
//# sourceMappingURL=catalog-policy-destinations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-policy-destinations.d.ts","sourceRoot":"","sources":["../src/catalog-policy-destinations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAE1F,QAAA,MAAM,iCAAiC,EAAE,gBAAgB,EA6HxD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gCAAgC,gDAAuD,CAAA;AAEpG,OAAO,EAAE,iCAAiC,EAAE,CAAA"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for product → destination denormalization.
|
|
3
|
+
*
|
|
4
|
+
* These fields don't live on the `products` table — they're joined from
|
|
5
|
+
* `product_destinations` → `destinations` (+ `destination_translations` for
|
|
6
|
+
* locale-aware names) at index time and projected onto the product search
|
|
7
|
+
* document. See `docs/architecture/catalog-architecture.md` §5.4 — the
|
|
8
|
+
* search index is the canonical place for cross-entity denormalization.
|
|
9
|
+
*
|
|
10
|
+
* Storefront product cards filter and display by destinations:
|
|
11
|
+
* - "trips to Italy" (filter: `countries[]` includes "Italy")
|
|
12
|
+
* - "trips in Rome" (filter: `cities[]` includes "Rome")
|
|
13
|
+
* - "Mediterranean cruises" (filter: `regions[]` includes "Mediterranean")
|
|
14
|
+
* - "cruises from Amsterdam" (filter: `ports[]` or canonical place ids)
|
|
15
|
+
*
|
|
16
|
+
* Wire this policy into the products registry by composing with
|
|
17
|
+
* `productCatalogPolicy`:
|
|
18
|
+
*
|
|
19
|
+
* const registry = createFieldPolicyRegistry([
|
|
20
|
+
* ...productCatalogPolicy,
|
|
21
|
+
* ...productDestinationsCatalogPolicy,
|
|
22
|
+
* ])
|
|
23
|
+
*
|
|
24
|
+
* and wire `createProductDestinationsProjectionExtension` into
|
|
25
|
+
* `createProductDocumentBuilder` so the values land in the doc.
|
|
26
|
+
*
|
|
27
|
+
* Destination rows can carry canonical place ids (for example UN/LOCODE)
|
|
28
|
+
* and optional display coordinates. The gazetteer itself remains external;
|
|
29
|
+
* this module stores stable pointers/snapshots for faceting.
|
|
30
|
+
*
|
|
31
|
+
* Out of scope here:
|
|
32
|
+
* - Slug fields per locale. Destinations have one canonical slug today;
|
|
33
|
+
* locale-specific slugs are a follow-up if marketing needs them.
|
|
34
|
+
*/
|
|
35
|
+
import { defineFieldPolicy } from "@voyant-travel/catalog/contract";
|
|
36
|
+
const PRODUCT_DESTINATIONS_FIELD_POLICY = [
|
|
37
|
+
// ── Locale-aware destination labels ──────────────────────────────────────
|
|
38
|
+
// Sourced from `destination_translations` (falls back to `destinations.slug`
|
|
39
|
+
// when no translation exists for the slice's locale). One array entry per
|
|
40
|
+
// linked destination of the matching `destination_type`.
|
|
41
|
+
{
|
|
42
|
+
path: "regions[]",
|
|
43
|
+
class: "structural",
|
|
44
|
+
merge: "source-only",
|
|
45
|
+
drift: "low",
|
|
46
|
+
reindex: "entry-locale",
|
|
47
|
+
snapshot: "on-book",
|
|
48
|
+
query: "indexed-column",
|
|
49
|
+
localized: true,
|
|
50
|
+
visibility: ["staff", "customer", "partner"],
|
|
51
|
+
editRole: "none",
|
|
52
|
+
overrideFriction: "none",
|
|
53
|
+
sourceFreshness: "sync",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
path: "countries[]",
|
|
57
|
+
class: "structural",
|
|
58
|
+
merge: "source-only",
|
|
59
|
+
drift: "low",
|
|
60
|
+
reindex: "entry-locale",
|
|
61
|
+
snapshot: "on-book",
|
|
62
|
+
query: "indexed-column",
|
|
63
|
+
localized: true,
|
|
64
|
+
visibility: ["staff", "customer", "partner"],
|
|
65
|
+
editRole: "none",
|
|
66
|
+
overrideFriction: "none",
|
|
67
|
+
sourceFreshness: "sync",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
path: "cities[]",
|
|
71
|
+
class: "structural",
|
|
72
|
+
merge: "source-only",
|
|
73
|
+
drift: "low",
|
|
74
|
+
reindex: "entry-locale",
|
|
75
|
+
snapshot: "on-book",
|
|
76
|
+
query: "indexed-column",
|
|
77
|
+
localized: true,
|
|
78
|
+
visibility: ["staff", "customer", "partner"],
|
|
79
|
+
editRole: "none",
|
|
80
|
+
overrideFriction: "none",
|
|
81
|
+
sourceFreshness: "sync",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
path: "ports[]",
|
|
85
|
+
class: "structural",
|
|
86
|
+
merge: "source-only",
|
|
87
|
+
drift: "low",
|
|
88
|
+
reindex: "entry-locale",
|
|
89
|
+
snapshot: "on-book",
|
|
90
|
+
query: "indexed-column",
|
|
91
|
+
localized: true,
|
|
92
|
+
visibility: ["staff", "customer", "partner"],
|
|
93
|
+
editRole: "none",
|
|
94
|
+
overrideFriction: "none",
|
|
95
|
+
sourceFreshness: "sync",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
path: "waterways[]",
|
|
99
|
+
class: "structural",
|
|
100
|
+
merge: "source-only",
|
|
101
|
+
drift: "low",
|
|
102
|
+
reindex: "entry-locale",
|
|
103
|
+
snapshot: "on-book",
|
|
104
|
+
query: "indexed-column",
|
|
105
|
+
localized: true,
|
|
106
|
+
visibility: ["staff", "customer", "partner"],
|
|
107
|
+
editRole: "none",
|
|
108
|
+
overrideFriction: "none",
|
|
109
|
+
sourceFreshness: "sync",
|
|
110
|
+
},
|
|
111
|
+
// ── Slugs (locale-stable) ────────────────────────────────────────────────
|
|
112
|
+
// Used for category-page links — operators want stable URLs that don't
|
|
113
|
+
// shift when translations are edited. One entry per linked destination.
|
|
114
|
+
{
|
|
115
|
+
path: "destinationSlugs[]",
|
|
116
|
+
class: "structural",
|
|
117
|
+
merge: "source-only",
|
|
118
|
+
drift: "low",
|
|
119
|
+
reindex: "facet-affecting",
|
|
120
|
+
snapshot: "on-book",
|
|
121
|
+
query: "indexed-column",
|
|
122
|
+
localized: false,
|
|
123
|
+
visibility: ["staff", "customer", "partner"],
|
|
124
|
+
editRole: "none",
|
|
125
|
+
overrideFriction: "none",
|
|
126
|
+
sourceFreshness: "sync",
|
|
127
|
+
},
|
|
128
|
+
// ── Destination IDs ──────────────────────────────────────────────────────
|
|
129
|
+
// Useful for filtering by exact destination match (e.g. landing pages
|
|
130
|
+
// pinned to a destination ID rather than a slug).
|
|
131
|
+
{
|
|
132
|
+
path: "destinationIds[]",
|
|
133
|
+
class: "structural",
|
|
134
|
+
merge: "source-only",
|
|
135
|
+
drift: "low",
|
|
136
|
+
reindex: "facet-affecting",
|
|
137
|
+
snapshot: "on-book",
|
|
138
|
+
query: "indexed-column",
|
|
139
|
+
localized: false,
|
|
140
|
+
visibility: ["staff", "customer", "partner"],
|
|
141
|
+
editRole: "none",
|
|
142
|
+
overrideFriction: "none",
|
|
143
|
+
sourceFreshness: "sync",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
path: "destinationCanonicalPlaceIds[]",
|
|
147
|
+
class: "structural",
|
|
148
|
+
merge: "source-only",
|
|
149
|
+
drift: "low",
|
|
150
|
+
reindex: "facet-affecting",
|
|
151
|
+
snapshot: "on-book",
|
|
152
|
+
query: "indexed-column",
|
|
153
|
+
localized: false,
|
|
154
|
+
visibility: ["staff", "customer", "partner"],
|
|
155
|
+
editRole: "none",
|
|
156
|
+
overrideFriction: "none",
|
|
157
|
+
sourceFreshness: "sync",
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
/**
|
|
161
|
+
* Resolved destinations policy. Compose with `productCatalogPolicy` when
|
|
162
|
+
* building the products registry.
|
|
163
|
+
*/
|
|
164
|
+
export const productDestinationsCatalogPolicy = defineFieldPolicy(PRODUCT_DESTINATIONS_FIELD_POLICY);
|
|
165
|
+
export { PRODUCT_DESTINATIONS_FIELD_POLICY };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for product → pricing denormalization.
|
|
3
|
+
*
|
|
4
|
+
* Aggregates a "price from" value across the product's future bookable
|
|
5
|
+
* default rate-plan prices so storefront cards can render `from $X`
|
|
6
|
+
* without fanning out to per-option pricing on every render. See
|
|
7
|
+
* `docs/architecture/catalog-architecture.md` §5.4.
|
|
8
|
+
*
|
|
9
|
+
* Storefront product cards filter and display by:
|
|
10
|
+
* - "trips under $1000" (filter: `priceFromAmountCents` <= 100000)
|
|
11
|
+
* - badge "from $X" (display: `priceFromAmountCents` + `priceFromCurrency`)
|
|
12
|
+
* - sort by price ascending (`priceFromAmountCents` asc)
|
|
13
|
+
*
|
|
14
|
+
* Wire this policy into the products registry by composing with
|
|
15
|
+
* `productCatalogPolicy`:
|
|
16
|
+
*
|
|
17
|
+
* const registry = createFieldPolicyRegistry([
|
|
18
|
+
* ...productCatalogPolicy,
|
|
19
|
+
* ...productPricingCatalogPolicy,
|
|
20
|
+
* ])
|
|
21
|
+
*
|
|
22
|
+
* and wire `createProductPricingProjectionExtension` (from
|
|
23
|
+
* `@voyant-travel/commerce` pricing projection support) into
|
|
24
|
+
* `createProductDocumentBuilder` so the values land in the doc.
|
|
25
|
+
*
|
|
26
|
+
* Why a separate field instead of reusing the existing `sellAmountCents`
|
|
27
|
+
* from `productCatalogPolicy`: that path projects the product-row
|
|
28
|
+
* configured default verbatim. Multi-option products often leave
|
|
29
|
+
* `products.sellAmountCents` null or stale and put the real prices on
|
|
30
|
+
* active rate-plan room/base/unit rows. This projection prefers those
|
|
31
|
+
* bookable prices and only falls back to the product row when no rate-
|
|
32
|
+
* plan price exists.
|
|
33
|
+
*
|
|
34
|
+
* Out of scope here (deferred):
|
|
35
|
+
* - Full schedule-aware rule resolution. The kernel reads
|
|
36
|
+
* `isDefault=true` rule prices on options that have a future
|
|
37
|
+
* bookable departure; it does NOT walk seasonal schedules or per-
|
|
38
|
+
* departure overrides.
|
|
39
|
+
* - Per-audience / per-market currency conversion. The currency we
|
|
40
|
+
* emit is `products.sellCurrency`; multi-catalog operators using
|
|
41
|
+
* mixed currencies for the same product will see prices clipped
|
|
42
|
+
* to the rules matching that currency.
|
|
43
|
+
* - `pricing.changed` event surface. Today, edits to option-price
|
|
44
|
+
* rules don't fire any event, so the bridge can only reindex on
|
|
45
|
+
* `product.updated`. Tracked separately.
|
|
46
|
+
*/
|
|
47
|
+
import { type FieldPolicyInput } from "@voyant-travel/catalog/contract";
|
|
48
|
+
declare const PRODUCT_PRICING_FIELD_POLICY: FieldPolicyInput[];
|
|
49
|
+
/**
|
|
50
|
+
* Resolved pricing policy. Compose with `productCatalogPolicy` when
|
|
51
|
+
* building the products registry.
|
|
52
|
+
*/
|
|
53
|
+
export declare const productPricingCatalogPolicy: import("@voyant-travel/catalog").FieldPolicy[];
|
|
54
|
+
export { PRODUCT_PRICING_FIELD_POLICY };
|
|
55
|
+
//# sourceMappingURL=catalog-policy-pricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-policy-pricing.d.ts","sourceRoot":"","sources":["../src/catalog-policy-pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAE1F,QAAA,MAAM,4BAA4B,EAAE,gBAAgB,EAuDnD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,gDAAkD,CAAA;AAE1F,OAAO,EAAE,4BAA4B,EAAE,CAAA"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for product → pricing denormalization.
|
|
3
|
+
*
|
|
4
|
+
* Aggregates a "price from" value across the product's future bookable
|
|
5
|
+
* default rate-plan prices so storefront cards can render `from $X`
|
|
6
|
+
* without fanning out to per-option pricing on every render. See
|
|
7
|
+
* `docs/architecture/catalog-architecture.md` §5.4.
|
|
8
|
+
*
|
|
9
|
+
* Storefront product cards filter and display by:
|
|
10
|
+
* - "trips under $1000" (filter: `priceFromAmountCents` <= 100000)
|
|
11
|
+
* - badge "from $X" (display: `priceFromAmountCents` + `priceFromCurrency`)
|
|
12
|
+
* - sort by price ascending (`priceFromAmountCents` asc)
|
|
13
|
+
*
|
|
14
|
+
* Wire this policy into the products registry by composing with
|
|
15
|
+
* `productCatalogPolicy`:
|
|
16
|
+
*
|
|
17
|
+
* const registry = createFieldPolicyRegistry([
|
|
18
|
+
* ...productCatalogPolicy,
|
|
19
|
+
* ...productPricingCatalogPolicy,
|
|
20
|
+
* ])
|
|
21
|
+
*
|
|
22
|
+
* and wire `createProductPricingProjectionExtension` (from
|
|
23
|
+
* `@voyant-travel/commerce` pricing projection support) into
|
|
24
|
+
* `createProductDocumentBuilder` so the values land in the doc.
|
|
25
|
+
*
|
|
26
|
+
* Why a separate field instead of reusing the existing `sellAmountCents`
|
|
27
|
+
* from `productCatalogPolicy`: that path projects the product-row
|
|
28
|
+
* configured default verbatim. Multi-option products often leave
|
|
29
|
+
* `products.sellAmountCents` null or stale and put the real prices on
|
|
30
|
+
* active rate-plan room/base/unit rows. This projection prefers those
|
|
31
|
+
* bookable prices and only falls back to the product row when no rate-
|
|
32
|
+
* plan price exists.
|
|
33
|
+
*
|
|
34
|
+
* Out of scope here (deferred):
|
|
35
|
+
* - Full schedule-aware rule resolution. The kernel reads
|
|
36
|
+
* `isDefault=true` rule prices on options that have a future
|
|
37
|
+
* bookable departure; it does NOT walk seasonal schedules or per-
|
|
38
|
+
* departure overrides.
|
|
39
|
+
* - Per-audience / per-market currency conversion. The currency we
|
|
40
|
+
* emit is `products.sellCurrency`; multi-catalog operators using
|
|
41
|
+
* mixed currencies for the same product will see prices clipped
|
|
42
|
+
* to the rules matching that currency.
|
|
43
|
+
* - `pricing.changed` event surface. Today, edits to option-price
|
|
44
|
+
* rules don't fire any event, so the bridge can only reindex on
|
|
45
|
+
* `product.updated`. Tracked separately.
|
|
46
|
+
*/
|
|
47
|
+
import { defineFieldPolicy } from "@voyant-travel/catalog/contract";
|
|
48
|
+
const PRODUCT_PRICING_FIELD_POLICY = [
|
|
49
|
+
// ── Aggregated "price from" amount ───────────────────────────────────────
|
|
50
|
+
// MIN across future bookable active default room prices first, then
|
|
51
|
+
// base/unit fallbacks, then `products.sellAmountCents`. `null` when no
|
|
52
|
+
// source has a positive amount.
|
|
53
|
+
{
|
|
54
|
+
path: "priceFromAmountCents",
|
|
55
|
+
class: "structural",
|
|
56
|
+
merge: "source-only",
|
|
57
|
+
drift: "low",
|
|
58
|
+
reindex: "facet-affecting",
|
|
59
|
+
snapshot: "on-book",
|
|
60
|
+
query: "indexed-column",
|
|
61
|
+
localized: false,
|
|
62
|
+
visibility: ["staff", "customer", "partner"],
|
|
63
|
+
editRole: "none",
|
|
64
|
+
overrideFriction: "none",
|
|
65
|
+
sourceFreshness: "sync",
|
|
66
|
+
},
|
|
67
|
+
// ── Currency for the projected amount ────────────────────────────────────
|
|
68
|
+
// `products.sellCurrency`. Stays consistent across all rule sources for
|
|
69
|
+
// the projected product because we filter rule rows to ones matching
|
|
70
|
+
// this currency before MIN'ing.
|
|
71
|
+
{
|
|
72
|
+
path: "priceFromCurrency",
|
|
73
|
+
class: "structural",
|
|
74
|
+
merge: "source-only",
|
|
75
|
+
drift: "low",
|
|
76
|
+
reindex: "facet-affecting",
|
|
77
|
+
snapshot: "on-book",
|
|
78
|
+
query: "indexed-column",
|
|
79
|
+
localized: false,
|
|
80
|
+
visibility: ["staff", "customer", "partner"],
|
|
81
|
+
editRole: "none",
|
|
82
|
+
overrideFriction: "none",
|
|
83
|
+
sourceFreshness: "sync",
|
|
84
|
+
},
|
|
85
|
+
// ── Existence flag ───────────────────────────────────────────────────────
|
|
86
|
+
// `false` when neither future rate-plan pricing nor the product row has
|
|
87
|
+
// a positive amount. Storefront filters use this for "show only priced
|
|
88
|
+
// products" and to suppress an empty `from` badge.
|
|
89
|
+
{
|
|
90
|
+
path: "hasPricing",
|
|
91
|
+
class: "structural",
|
|
92
|
+
merge: "source-only",
|
|
93
|
+
drift: "low",
|
|
94
|
+
reindex: "facet-affecting",
|
|
95
|
+
snapshot: "on-book",
|
|
96
|
+
query: "indexed-column",
|
|
97
|
+
localized: false,
|
|
98
|
+
visibility: ["staff", "customer", "partner"],
|
|
99
|
+
editRole: "none",
|
|
100
|
+
overrideFriction: "none",
|
|
101
|
+
sourceFreshness: "sync",
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
/**
|
|
105
|
+
* Resolved pricing policy. Compose with `productCatalogPolicy` when
|
|
106
|
+
* building the products registry.
|
|
107
|
+
*/
|
|
108
|
+
export const productPricingCatalogPolicy = defineFieldPolicy(PRODUCT_PRICING_FIELD_POLICY);
|
|
109
|
+
export { PRODUCT_PRICING_FIELD_POLICY };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog plane field policy for product → promotional-offer denormalization.
|
|
3
|
+
*
|
|
4
|
+
* Promotions are projected as **annotations only** — this policy does NOT
|
|
5
|
+
* touch the existing `priceFromAmountCents` field (that's emitted by the
|
|
6
|
+
* pricing extension and the two extensions can't read each other's output;
|
|
7
|
+
* see `docs/architecture/promotions-architecture.md` §3.7). Instead, we
|
|
8
|
+
* emit `bestOffer*` + `originalPriceFromAmountCents` and storefront
|
|
9
|
+
* consumers compute the effective price client-side:
|
|
10
|
+
*
|
|
11
|
+
* effective = bestOfferDiscountKind === "percentage"
|
|
12
|
+
* ? round(price × (1 - bestOfferDiscountPercent/100))
|
|
13
|
+
* : price - bestOfferDiscountAmountCents
|
|
14
|
+
*
|
|
15
|
+
* Catalog filter / sort behavior continues to use `priceFromAmountCents`
|
|
16
|
+
* (the list price). A customer searching `< $200` won't find a
|
|
17
|
+
* `$250 → $180` discounted product via the filter — acknowledged v1
|
|
18
|
+
* limitation, see §15.1 of the architecture doc.
|
|
19
|
+
*
|
|
20
|
+
* Conditional offers are surfaced separately so storefront cards can
|
|
21
|
+
* render hints like "From 4 pax: extra 5% off" — the catalog plane
|
|
22
|
+
* doesn't know pax at index time, so any offer with a `minPax` condition
|
|
23
|
+
* lands here instead of in `bestOffer*`.
|
|
24
|
+
*
|
|
25
|
+
* Wire this policy into the products registry by composing with
|
|
26
|
+
* `productCatalogPolicy`:
|
|
27
|
+
*
|
|
28
|
+
* const registry = createFieldPolicyRegistry([
|
|
29
|
+
* ...productCatalogPolicy,
|
|
30
|
+
* ...productPromotionsCatalogPolicy,
|
|
31
|
+
* ])
|
|
32
|
+
*
|
|
33
|
+
* and wire `createProductPromotionsProjectionExtension` (from
|
|
34
|
+
* `@voyant-travel/commerce` promotion projection support) into
|
|
35
|
+
* `createProductDocumentBuilder` so the values land in the doc.
|
|
36
|
+
*
|
|
37
|
+
* Out of scope here:
|
|
38
|
+
* - Localized offer names. Offers are operator-managed in one language
|
|
39
|
+
* for v1 (`localized: false`); a `promotional_offer_translations`
|
|
40
|
+
* table mirrors `destinations_translations` if/when needed.
|
|
41
|
+
* - Discount-aware filter / sort. Requires the §15.1 ordered-extensions
|
|
42
|
+
* contract change; deferred.
|
|
43
|
+
*/
|
|
44
|
+
import { type FieldPolicyInput } from "@voyant-travel/catalog/contract";
|
|
45
|
+
declare const PRODUCT_PROMOTIONS_FIELD_POLICY: FieldPolicyInput[];
|
|
46
|
+
/**
|
|
47
|
+
* Resolved promotions policy. Compose with `productCatalogPolicy` when
|
|
48
|
+
* building the products registry.
|
|
49
|
+
*/
|
|
50
|
+
export declare const productPromotionsCatalogPolicy: import("@voyant-travel/catalog").FieldPolicy[];
|
|
51
|
+
export { PRODUCT_PROMOTIONS_FIELD_POLICY };
|
|
52
|
+
//# sourceMappingURL=catalog-policy-promotions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-policy-promotions.d.ts","sourceRoot":"","sources":["../src/catalog-policy-promotions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAE1F,QAAA,MAAM,+BAA+B,EAAE,gBAAgB,EA4NtD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,8BAA8B,gDAAqD,CAAA;AAEhG,OAAO,EAAE,+BAA+B,EAAE,CAAA"}
|