@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.
Files changed (311) hide show
  1. package/LICENSE +201 -0
  2. package/dist/action-ledger-drift.d.ts +29 -0
  3. package/dist/action-ledger-drift.d.ts.map +1 -0
  4. package/dist/action-ledger-drift.js +338 -0
  5. package/dist/action-ledger.d.ts +104 -0
  6. package/dist/action-ledger.d.ts.map +1 -0
  7. package/dist/action-ledger.js +100 -0
  8. package/dist/authoring/builder.d.ts +37 -0
  9. package/dist/authoring/builder.d.ts.map +1 -0
  10. package/dist/authoring/builder.js +248 -0
  11. package/dist/authoring/clone-content.d.ts +38 -0
  12. package/dist/authoring/clone-content.d.ts.map +1 -0
  13. package/dist/authoring/clone-content.js +367 -0
  14. package/dist/authoring/clone-pricing.d.ts +9 -0
  15. package/dist/authoring/clone-pricing.d.ts.map +1 -0
  16. package/dist/authoring/clone-pricing.js +242 -0
  17. package/dist/authoring/clone.d.ts +45 -0
  18. package/dist/authoring/clone.d.ts.map +1 -0
  19. package/dist/authoring/clone.js +142 -0
  20. package/dist/authoring/errors.d.ts +21 -0
  21. package/dist/authoring/errors.d.ts.map +1 -0
  22. package/dist/authoring/errors.js +13 -0
  23. package/dist/authoring/extension.d.ts +248 -0
  24. package/dist/authoring/extension.d.ts.map +1 -0
  25. package/dist/authoring/extension.js +116 -0
  26. package/dist/authoring/index.d.ts +12 -0
  27. package/dist/authoring/index.d.ts.map +1 -0
  28. package/dist/authoring/index.js +11 -0
  29. package/dist/authoring/schema.d.ts +85 -0
  30. package/dist/authoring/schema.d.ts.map +1 -0
  31. package/dist/authoring/schema.js +16 -0
  32. package/dist/authoring/service.d.ts +28 -0
  33. package/dist/authoring/service.d.ts.map +1 -0
  34. package/dist/authoring/service.js +66 -0
  35. package/dist/authoring/spec.d.ts +524 -0
  36. package/dist/authoring/spec.d.ts.map +1 -0
  37. package/dist/authoring/spec.js +167 -0
  38. package/dist/authoring/validate.d.ts +17 -0
  39. package/dist/authoring/validate.d.ts.map +1 -0
  40. package/dist/authoring/validate.js +83 -0
  41. package/dist/authoring.d.ts +2 -0
  42. package/dist/authoring.d.ts.map +1 -0
  43. package/dist/authoring.js +1 -0
  44. package/dist/booking-engine/handler-support.d.ts +91 -0
  45. package/dist/booking-engine/handler-support.d.ts.map +1 -0
  46. package/dist/booking-engine/handler-support.js +355 -0
  47. package/dist/booking-engine/handler.d.ts +404 -0
  48. package/dist/booking-engine/handler.d.ts.map +1 -0
  49. package/dist/booking-engine/handler.js +398 -0
  50. package/dist/booking-engine/index.d.ts +8 -0
  51. package/dist/booking-engine/index.d.ts.map +1 -0
  52. package/dist/booking-engine/index.js +7 -0
  53. package/dist/booking-engine.d.ts +2 -0
  54. package/dist/booking-engine.d.ts.map +1 -0
  55. package/dist/booking-engine.js +1 -0
  56. package/dist/booking-extension.d.ts +278 -0
  57. package/dist/booking-extension.d.ts.map +1 -0
  58. package/dist/booking-extension.js +161 -0
  59. package/dist/catalog-policy-departures.d.ts +52 -0
  60. package/dist/catalog-policy-departures.d.ts.map +1 -0
  61. package/dist/catalog-policy-departures.js +169 -0
  62. package/dist/catalog-policy-destinations.d.ts +43 -0
  63. package/dist/catalog-policy-destinations.d.ts.map +1 -0
  64. package/dist/catalog-policy-destinations.js +165 -0
  65. package/dist/catalog-policy-pricing.d.ts +55 -0
  66. package/dist/catalog-policy-pricing.d.ts.map +1 -0
  67. package/dist/catalog-policy-pricing.js +109 -0
  68. package/dist/catalog-policy-promotions.d.ts +52 -0
  69. package/dist/catalog-policy-promotions.d.ts.map +1 -0
  70. package/dist/catalog-policy-promotions.js +270 -0
  71. package/dist/catalog-policy-taxonomy.d.ts +51 -0
  72. package/dist/catalog-policy-taxonomy.d.ts.map +1 -0
  73. package/dist/catalog-policy-taxonomy.js +191 -0
  74. package/dist/catalog-policy.d.ts +33 -0
  75. package/dist/catalog-policy.d.ts.map +1 -0
  76. package/dist/catalog-policy.js +733 -0
  77. package/dist/content-shape.d.ts +15 -0
  78. package/dist/content-shape.d.ts.map +1 -0
  79. package/dist/content-shape.js +28 -0
  80. package/dist/draft-shape.d.ts +43 -0
  81. package/dist/draft-shape.d.ts.map +1 -0
  82. package/dist/draft-shape.js +48 -0
  83. package/dist/events.d.ts +37 -0
  84. package/dist/events.d.ts.map +1 -0
  85. package/dist/events.js +32 -0
  86. package/dist/extras/catalog-policy.d.ts +30 -0
  87. package/dist/extras/catalog-policy.d.ts.map +1 -0
  88. package/dist/extras/catalog-policy.js +319 -0
  89. package/dist/extras/content-shape.d.ts +5 -0
  90. package/dist/extras/content-shape.d.ts.map +1 -0
  91. package/dist/extras/content-shape.js +13 -0
  92. package/dist/extras/draft-shape.d.ts +34 -0
  93. package/dist/extras/draft-shape.d.ts.map +1 -0
  94. package/dist/extras/draft-shape.js +69 -0
  95. package/dist/extras/routes.d.ts +380 -0
  96. package/dist/extras/routes.d.ts.map +1 -0
  97. package/dist/extras/routes.js +59 -0
  98. package/dist/extras/schema-sourced-content.d.ts +254 -0
  99. package/dist/extras/schema-sourced-content.d.ts.map +1 -0
  100. package/dist/extras/schema-sourced-content.js +45 -0
  101. package/dist/extras/schema.d.ts +628 -0
  102. package/dist/extras/schema.d.ts.map +1 -0
  103. package/dist/extras/schema.js +87 -0
  104. package/dist/extras/service-catalog-plane.d.ts +77 -0
  105. package/dist/extras/service-catalog-plane.d.ts.map +1 -0
  106. package/dist/extras/service-catalog-plane.js +219 -0
  107. package/dist/extras/service-content-synthesizer.d.ts +41 -0
  108. package/dist/extras/service-content-synthesizer.d.ts.map +1 -0
  109. package/dist/extras/service-content-synthesizer.js +138 -0
  110. package/dist/extras/service-content.d.ts +48 -0
  111. package/dist/extras/service-content.d.ts.map +1 -0
  112. package/dist/extras/service-content.js +253 -0
  113. package/dist/extras/service.d.ts +185 -0
  114. package/dist/extras/service.d.ts.map +1 -0
  115. package/dist/extras/service.js +96 -0
  116. package/dist/extras/validation.d.ts +437 -0
  117. package/dist/extras/validation.d.ts.map +1 -0
  118. package/dist/extras/validation.js +149 -0
  119. package/dist/extras.d.ts +267 -0
  120. package/dist/extras.d.ts.map +1 -0
  121. package/dist/extras.js +19 -0
  122. package/dist/index.d.ts +22 -0
  123. package/dist/index.d.ts.map +1 -0
  124. package/dist/index.js +32 -0
  125. package/dist/interface.d.ts +5869 -0
  126. package/dist/interface.d.ts.map +1 -0
  127. package/dist/interface.js +54 -0
  128. package/dist/public-routes.d.ts +2 -0
  129. package/dist/public-routes.d.ts.map +1 -0
  130. package/dist/public-routes.js +1 -0
  131. package/dist/public-validation.d.ts +2 -0
  132. package/dist/public-validation.d.ts.map +1 -0
  133. package/dist/public-validation.js +1 -0
  134. package/dist/read-model.d.ts +25 -0
  135. package/dist/read-model.d.ts.map +1 -0
  136. package/dist/read-model.js +99 -0
  137. package/dist/route-env.d.ts +22 -0
  138. package/dist/route-env.d.ts.map +1 -0
  139. package/dist/route-env.js +1 -0
  140. package/dist/routes-associations.d.ts +164 -0
  141. package/dist/routes-associations.d.ts.map +1 -0
  142. package/dist/routes-associations.js +100 -0
  143. package/dist/routes-catalog.d.ts +436 -0
  144. package/dist/routes-catalog.d.ts.map +1 -0
  145. package/dist/routes-catalog.js +104 -0
  146. package/dist/routes-configuration.d.ts +773 -0
  147. package/dist/routes-configuration.d.ts.map +1 -0
  148. package/dist/routes-configuration.js +364 -0
  149. package/dist/routes-content.d.ts +74 -0
  150. package/dist/routes-content.d.ts.map +1 -0
  151. package/dist/routes-content.js +117 -0
  152. package/dist/routes-core.d.ts +331 -0
  153. package/dist/routes-core.d.ts.map +1 -0
  154. package/dist/routes-core.js +95 -0
  155. package/dist/routes-itinerary.d.ts +759 -0
  156. package/dist/routes-itinerary.d.ts.map +1 -0
  157. package/dist/routes-itinerary.js +387 -0
  158. package/dist/routes-maintenance.d.ts +32 -0
  159. package/dist/routes-maintenance.d.ts.map +1 -0
  160. package/dist/routes-maintenance.js +14 -0
  161. package/dist/routes-media.d.ts +634 -0
  162. package/dist/routes-media.d.ts.map +1 -0
  163. package/dist/routes-media.js +245 -0
  164. package/dist/routes-merchandising.d.ts +1120 -0
  165. package/dist/routes-merchandising.d.ts.map +1 -0
  166. package/dist/routes-merchandising.js +377 -0
  167. package/dist/routes-options.d.ts +363 -0
  168. package/dist/routes-options.d.ts.map +1 -0
  169. package/dist/routes-options.js +173 -0
  170. package/dist/routes-public.d.ts +776 -0
  171. package/dist/routes-public.d.ts.map +1 -0
  172. package/dist/routes-public.js +119 -0
  173. package/dist/routes-translations.d.ts +489 -0
  174. package/dist/routes-translations.d.ts.map +1 -0
  175. package/dist/routes-translations.js +258 -0
  176. package/dist/routes.d.ts +5097 -0
  177. package/dist/routes.d.ts.map +1 -0
  178. package/dist/routes.js +64 -0
  179. package/dist/schema-core.d.ts +1238 -0
  180. package/dist/schema-core.d.ts.map +1 -0
  181. package/dist/schema-core.js +157 -0
  182. package/dist/schema-itinerary.d.ts +1169 -0
  183. package/dist/schema-itinerary.d.ts.map +1 -0
  184. package/dist/schema-itinerary.js +130 -0
  185. package/dist/schema-relations.d.ts +117 -0
  186. package/dist/schema-relations.d.ts.map +1 -0
  187. package/dist/schema-relations.js +192 -0
  188. package/dist/schema-settings.d.ts +1800 -0
  189. package/dist/schema-settings.d.ts.map +1 -0
  190. package/dist/schema-settings.js +220 -0
  191. package/dist/schema-shared.d.ts +15 -0
  192. package/dist/schema-shared.d.ts.map +1 -0
  193. package/dist/schema-shared.js +91 -0
  194. package/dist/schema-sourced-content.d.ts +262 -0
  195. package/dist/schema-sourced-content.d.ts.map +1 -0
  196. package/dist/schema-sourced-content.js +69 -0
  197. package/dist/schema-taxonomy.d.ts +1363 -0
  198. package/dist/schema-taxonomy.d.ts.map +1 -0
  199. package/dist/schema-taxonomy.js +203 -0
  200. package/dist/schema.d.ts +10 -0
  201. package/dist/schema.d.ts.map +1 -0
  202. package/dist/schema.js +9 -0
  203. package/dist/service-aggregates.d.ts +29 -0
  204. package/dist/service-aggregates.d.ts.map +1 -0
  205. package/dist/service-aggregates.js +56 -0
  206. package/dist/service-catalog-plane-destinations.d.ts +30 -0
  207. package/dist/service-catalog-plane-destinations.d.ts.map +1 -0
  208. package/dist/service-catalog-plane-destinations.js +143 -0
  209. package/dist/service-catalog-plane-taxonomy.d.ts +73 -0
  210. package/dist/service-catalog-plane-taxonomy.d.ts.map +1 -0
  211. package/dist/service-catalog-plane-taxonomy.js +242 -0
  212. package/dist/service-catalog-plane.d.ts +179 -0
  213. package/dist/service-catalog-plane.d.ts.map +1 -0
  214. package/dist/service-catalog-plane.js +431 -0
  215. package/dist/service-catalog.d.ts +251 -0
  216. package/dist/service-catalog.d.ts.map +1 -0
  217. package/dist/service-catalog.js +517 -0
  218. package/dist/service-configuration.d.ts +261 -0
  219. package/dist/service-configuration.d.ts.map +1 -0
  220. package/dist/service-configuration.js +343 -0
  221. package/dist/service-content-owned.d.ts +68 -0
  222. package/dist/service-content-owned.d.ts.map +1 -0
  223. package/dist/service-content-owned.js +329 -0
  224. package/dist/service-content-synthesizer.d.ts +90 -0
  225. package/dist/service-content-synthesizer.d.ts.map +1 -0
  226. package/dist/service-content-synthesizer.js +178 -0
  227. package/dist/service-content.d.ts +106 -0
  228. package/dist/service-content.d.ts.map +1 -0
  229. package/dist/service-content.js +388 -0
  230. package/dist/service-core.d.ts +194 -0
  231. package/dist/service-core.d.ts.map +1 -0
  232. package/dist/service-core.js +213 -0
  233. package/dist/service-delivery-formats.d.ts +58 -0
  234. package/dist/service-delivery-formats.d.ts.map +1 -0
  235. package/dist/service-delivery-formats.js +107 -0
  236. package/dist/service-destinations.d.ts +223 -0
  237. package/dist/service-destinations.d.ts.map +1 -0
  238. package/dist/service-destinations.js +310 -0
  239. package/dist/service-itinerary-history.d.ts +457 -0
  240. package/dist/service-itinerary-history.d.ts.map +1 -0
  241. package/dist/service-itinerary-history.js +135 -0
  242. package/dist/service-itinerary.d.ts +1149 -0
  243. package/dist/service-itinerary.d.ts.map +1 -0
  244. package/dist/service-itinerary.js +419 -0
  245. package/dist/service-media.d.ts +272 -0
  246. package/dist/service-media.d.ts.map +1 -0
  247. package/dist/service-media.js +320 -0
  248. package/dist/service-merchandising.d.ts +184 -0
  249. package/dist/service-merchandising.d.ts.map +1 -0
  250. package/dist/service-merchandising.js +181 -0
  251. package/dist/service-option-translations.d.ts +268 -0
  252. package/dist/service-option-translations.d.ts.map +1 -0
  253. package/dist/service-option-translations.js +300 -0
  254. package/dist/service-options.d.ts +181 -0
  255. package/dist/service-options.d.ts.map +1 -0
  256. package/dist/service-options.js +179 -0
  257. package/dist/service-product-destinations.d.ts +37 -0
  258. package/dist/service-product-destinations.d.ts.map +1 -0
  259. package/dist/service-product-destinations.js +94 -0
  260. package/dist/service-public.d.ts +664 -0
  261. package/dist/service-public.d.ts.map +1 -0
  262. package/dist/service-public.js +374 -0
  263. package/dist/service-taxonomy.d.ts +197 -0
  264. package/dist/service-taxonomy.d.ts.map +1 -0
  265. package/dist/service-taxonomy.js +221 -0
  266. package/dist/service.d.ts +3929 -0
  267. package/dist/service.d.ts.map +1 -0
  268. package/dist/service.js +28 -0
  269. package/dist/tasks/brochure-printers.d.ts +31 -0
  270. package/dist/tasks/brochure-printers.d.ts.map +1 -0
  271. package/dist/tasks/brochure-printers.js +149 -0
  272. package/dist/tasks/brochure-templates.d.ts +36 -0
  273. package/dist/tasks/brochure-templates.d.ts.map +1 -0
  274. package/dist/tasks/brochure-templates.js +110 -0
  275. package/dist/tasks/brochures.d.ts +43 -0
  276. package/dist/tasks/brochures.d.ts.map +1 -0
  277. package/dist/tasks/brochures.js +72 -0
  278. package/dist/tasks/generate-pdf.d.ts +8 -0
  279. package/dist/tasks/generate-pdf.d.ts.map +1 -0
  280. package/dist/tasks/generate-pdf.js +106 -0
  281. package/dist/tasks/index.d.ts +5 -0
  282. package/dist/tasks/index.d.ts.map +1 -0
  283. package/dist/tasks/index.js +4 -0
  284. package/dist/tasks/pdf-text.d.ts +2 -0
  285. package/dist/tasks/pdf-text.d.ts.map +1 -0
  286. package/dist/tasks/pdf-text.js +40 -0
  287. package/dist/tasks.d.ts +2 -0
  288. package/dist/tasks.d.ts.map +1 -0
  289. package/dist/tasks.js +1 -0
  290. package/dist/validation-catalog.d.ts +2 -0
  291. package/dist/validation-catalog.d.ts.map +1 -0
  292. package/dist/validation-catalog.js +3 -0
  293. package/dist/validation-config.d.ts +2 -0
  294. package/dist/validation-config.d.ts.map +1 -0
  295. package/dist/validation-config.js +3 -0
  296. package/dist/validation-content.d.ts +2 -0
  297. package/dist/validation-content.d.ts.map +1 -0
  298. package/dist/validation-content.js +3 -0
  299. package/dist/validation-core.d.ts +2 -0
  300. package/dist/validation-core.d.ts.map +1 -0
  301. package/dist/validation-core.js +3 -0
  302. package/dist/validation-public.d.ts +2 -0
  303. package/dist/validation-public.d.ts.map +1 -0
  304. package/dist/validation-public.js +3 -0
  305. package/dist/validation-shared.d.ts +2 -0
  306. package/dist/validation-shared.d.ts.map +1 -0
  307. package/dist/validation-shared.js +3 -0
  308. package/dist/validation.d.ts +2 -0
  309. package/dist/validation.d.ts.map +1 -0
  310. package/dist/validation.js +3 -0
  311. 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"}