@openlup/platform 0.17.0 → 0.19.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 (525) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/README.md +299 -6
  3. package/dist/catalog/activeSkuSelection.d.ts +2 -0
  4. package/dist/catalog/activeSkuSelection.js +20 -0
  5. package/dist/catalog/adminBindings.d.ts +72 -0
  6. package/dist/catalog/adminBindings.js +1 -0
  7. package/dist/catalog/adminBundleHandler.d.ts +26 -0
  8. package/dist/catalog/adminBundleHandler.js +111 -0
  9. package/dist/catalog/adminBundleReadHandler.d.ts +21 -0
  10. package/dist/catalog/adminBundleReadHandler.js +185 -0
  11. package/dist/catalog/adminBundleWritePort.d.ts +85 -0
  12. package/dist/catalog/adminBundleWritePort.js +1 -0
  13. package/dist/catalog/bundleAvailability.d.ts +63 -0
  14. package/dist/catalog/bundleAvailability.js +78 -0
  15. package/dist/catalog/bundleAvailabilityService.d.ts +65 -0
  16. package/dist/catalog/bundleAvailabilityService.js +89 -0
  17. package/dist/catalog/bundleBindings.d.ts +33 -0
  18. package/dist/catalog/bundleBindings.js +1 -0
  19. package/dist/catalog/bundleCatalogQueries.d.ts +28 -0
  20. package/dist/catalog/bundleCatalogQueries.js +84 -0
  21. package/dist/catalog/bundleCatalogReadPort.d.ts +173 -0
  22. package/dist/catalog/bundleCatalogReadPort.js +36 -0
  23. package/dist/catalog/bundleCatalogStore.d.ts +5 -0
  24. package/dist/catalog/bundleCatalogStore.js +156 -0
  25. package/dist/catalog/bundlePriceSelection.d.ts +13 -0
  26. package/dist/catalog/bundlePriceSelection.js +26 -0
  27. package/dist/catalog/bundleRuleCodes.d.ts +41 -0
  28. package/dist/catalog/bundleRuleCodes.js +110 -0
  29. package/dist/catalog/bundleRules.d.ts +69 -0
  30. package/dist/catalog/bundleRules.js +102 -0
  31. package/dist/catalog/catalogDraftStore.d.ts +4 -0
  32. package/dist/catalog/catalogDraftStore.js +63 -0
  33. package/dist/catalog/catalogSkuEnvelope.d.ts +7 -0
  34. package/dist/catalog/catalogSkuEnvelope.js +142 -0
  35. package/dist/catalog/catalogSkuEnvelopeMapper.d.ts +38 -0
  36. package/dist/catalog/catalogSkuEnvelopeMapper.js +88 -0
  37. package/dist/catalog/contracts/bundleAdmin.d.ts +143 -0
  38. package/dist/catalog/contracts/bundleAdmin.js +1 -0
  39. package/dist/catalog/contracts/bundleAvailability.d.ts +61 -0
  40. package/dist/catalog/contracts/bundleAvailability.js +1 -0
  41. package/dist/catalog/contracts/bundleRead.d.ts +241 -0
  42. package/dist/catalog/contracts/bundleRead.js +1 -0
  43. package/dist/catalog/contracts/draft.d.ts +79 -0
  44. package/dist/catalog/contracts/draft.js +47 -0
  45. package/dist/catalog/contracts/foundation.d.ts +78 -0
  46. package/dist/catalog/contracts/foundation.js +53 -0
  47. package/dist/catalog/contracts/index.d.ts +14 -0
  48. package/dist/catalog/contracts/index.js +6 -0
  49. package/dist/catalog/contracts/lifecycle.d.ts +77 -0
  50. package/dist/catalog/contracts/lifecycle.js +1 -0
  51. package/dist/catalog/contracts/productMediaContracts.d.ts +77 -0
  52. package/dist/catalog/contracts/productMediaContracts.js +149 -0
  53. package/dist/catalog/contracts/productTypes.d.ts +54 -0
  54. package/dist/catalog/contracts/productTypes.js +16 -0
  55. package/dist/catalog/contracts/resolveProductMedia.d.ts +3 -0
  56. package/dist/catalog/contracts/resolveProductMedia.js +78 -0
  57. package/dist/catalog/contracts/sellable.d.ts +23 -0
  58. package/dist/catalog/contracts/sellable.js +1 -0
  59. package/dist/catalog/draftHandler.d.ts +25 -0
  60. package/dist/catalog/draftHandler.js +118 -0
  61. package/dist/catalog/draftPorts.d.ts +18 -0
  62. package/dist/catalog/draftPorts.js +8 -0
  63. package/dist/catalog/draftSchemas.d.ts +423 -0
  64. package/dist/catalog/draftSchemas.js +89 -0
  65. package/dist/catalog/draftValidation.d.ts +21 -0
  66. package/dist/catalog/draftValidation.js +125 -0
  67. package/dist/catalog/effectiveBundleCatalogQueries.d.ts +8 -0
  68. package/dist/catalog/effectiveBundleCatalogQueries.js +79 -0
  69. package/dist/catalog/effectiveBundleCatalogStore.d.ts +4 -0
  70. package/dist/catalog/effectiveBundleCatalogStore.js +156 -0
  71. package/dist/catalog/foundationSchemas.d.ts +98 -0
  72. package/dist/catalog/foundationSchemas.js +110 -0
  73. package/dist/catalog/index.d.ts +44 -0
  74. package/dist/catalog/index.js +26 -0
  75. package/dist/catalog/mediaSourcePack.d.ts +51 -0
  76. package/dist/catalog/mediaSourcePack.js +247 -0
  77. package/dist/catalog/productTypeSchemas.d.ts +46 -0
  78. package/dist/catalog/productTypeSchemas.js +72 -0
  79. package/dist/catalog/publicationPorts.d.ts +42 -0
  80. package/dist/catalog/publicationPorts.js +1 -0
  81. package/dist/catalog/readPorts.d.ts +51 -0
  82. package/dist/catalog/readPorts.js +1 -0
  83. package/dist/catalog/referenceCatalogHandler.d.ts +7 -0
  84. package/dist/catalog/referenceCatalogHandler.js +27 -0
  85. package/dist/catalog/resolvedSkuProjection.d.ts +88 -0
  86. package/dist/catalog/resolvedSkuProjection.js +60 -0
  87. package/dist/catalog/sellableBundleHandler.d.ts +46 -0
  88. package/dist/catalog/sellableBundleHandler.js +84 -0
  89. package/dist/catalog/sellableSchemas.d.ts +46 -0
  90. package/dist/catalog/sellableSchemas.js +27 -0
  91. package/dist/catalog/sql.d.ts +46 -0
  92. package/dist/catalog/sql.js +13 -0
  93. package/dist/catalog/validation.d.ts +2 -0
  94. package/dist/catalog/validation.js +3 -0
  95. package/dist/communications/contracts/index.d.ts +1 -0
  96. package/dist/communications/contracts/marketingSync.d.ts +194 -0
  97. package/dist/communications/contracts/marketingSync.js +1 -0
  98. package/dist/communications/index.d.ts +1 -0
  99. package/dist/communications/klaviyo/consentPush.d.ts +51 -0
  100. package/dist/communications/klaviyo/consentPush.js +19 -0
  101. package/dist/communications/klaviyo/index.d.ts +110 -0
  102. package/dist/communications/klaviyo/index.js +860 -0
  103. package/dist/communications/newsletterIntegrationContracts.d.ts +3 -3
  104. package/dist/communications/resend/index.d.ts +40 -0
  105. package/dist/communications/resend/index.js +310 -0
  106. package/dist/composition/catalogContribution.d.ts +18 -0
  107. package/dist/composition/catalogContribution.js +21 -0
  108. package/dist/composition/index.d.ts +3 -0
  109. package/dist/composition/index.js +3 -0
  110. package/dist/composition/inventoryContribution.d.ts +16 -0
  111. package/dist/composition/inventoryContribution.js +17 -0
  112. package/dist/composition/shippingContribution.d.ts +16 -0
  113. package/dist/composition/shippingContribution.js +17 -0
  114. package/dist/identity/customerContracts.d.ts +2 -2
  115. package/dist/inventory/adminInventory.d.ts +13 -0
  116. package/dist/inventory/adminInventory.js +214 -0
  117. package/dist/inventory/bindings.d.ts +35 -0
  118. package/dist/inventory/bindings.js +45 -0
  119. package/dist/inventory/contracts/forecast.d.ts +86 -0
  120. package/dist/inventory/contracts/forecast.js +1 -0
  121. package/dist/inventory/contracts/index.d.ts +4 -0
  122. package/dist/inventory/contracts/index.js +1 -0
  123. package/dist/inventory/contracts/inventory.d.ts +157 -0
  124. package/dist/inventory/contracts/inventory.js +1 -0
  125. package/dist/inventory/contracts/newPurchaseStock.d.ts +20 -0
  126. package/dist/inventory/contracts/newPurchaseStock.js +1 -0
  127. package/dist/inventory/contracts/reservation.d.ts +18 -0
  128. package/dist/inventory/contracts/reservation.js +1 -0
  129. package/dist/inventory/forecast.d.ts +24 -0
  130. package/dist/inventory/forecast.js +200 -0
  131. package/dist/inventory/index.d.ts +14 -0
  132. package/dist/inventory/index.js +11 -0
  133. package/dist/inventory/inventoryHandlers.d.ts +53 -0
  134. package/dist/inventory/inventoryHandlers.js +151 -0
  135. package/dist/inventory/newPurchaseStockAvailability.d.ts +47 -0
  136. package/dist/inventory/newPurchaseStockAvailability.js +75 -0
  137. package/dist/inventory/ports.d.ts +21 -0
  138. package/dist/inventory/ports.js +16 -0
  139. package/dist/inventory/renewalReservation.d.ts +27 -0
  140. package/dist/inventory/renewalReservation.js +61 -0
  141. package/dist/inventory/reservationPolicy.d.ts +6 -0
  142. package/dist/inventory/reservationPolicy.js +19 -0
  143. package/dist/inventory/schemas.d.ts +137 -0
  144. package/dist/inventory/schemas.js +112 -0
  145. package/dist/inventory/sql.d.ts +14 -0
  146. package/dist/inventory/sql.js +5 -0
  147. package/dist/inventory/subscriptionForecastCalculation.d.ts +4 -0
  148. package/dist/inventory/subscriptionForecastCalculation.js +133 -0
  149. package/dist/pricing/acquisitionFinancialPolicy.d.ts +26 -0
  150. package/dist/pricing/acquisitionFinancialPolicy.js +1 -0
  151. package/dist/pricing/acquisitionOfferPricing.d.ts +27 -0
  152. package/dist/pricing/acquisitionOfferPricing.js +25 -0
  153. package/dist/pricing/acquisitionOfferPricingHandler.d.ts +20 -0
  154. package/dist/pricing/acquisitionOfferPricingHandler.js +105 -0
  155. package/dist/pricing/acquisitionOfferPricingSchemas.d.ts +31 -0
  156. package/dist/pricing/acquisitionOfferPricingSchemas.js +33 -0
  157. package/dist/pricing/acquisitionQuoteBinding.d.ts +12 -0
  158. package/dist/pricing/acquisitionQuoteBinding.js +12 -0
  159. package/dist/pricing/acquisitionReadiness.d.ts +31 -0
  160. package/dist/pricing/acquisitionReadiness.js +117 -0
  161. package/dist/pricing/acquisitionTerms.d.ts +19 -0
  162. package/dist/pricing/acquisitionTerms.js +126 -0
  163. package/dist/pricing/acquisitionTermsSchemas.d.ts +59 -0
  164. package/dist/pricing/acquisitionTermsSchemas.js +42 -0
  165. package/dist/pricing/catalogFactsProvenance.d.ts +33 -0
  166. package/dist/pricing/catalogFactsProvenance.js +64 -0
  167. package/dist/pricing/catalogFactsSchemas.d.ts +45 -0
  168. package/dist/pricing/catalogFactsSchemas.js +58 -0
  169. package/dist/pricing/commerceOfferPricing.d.ts +25 -0
  170. package/dist/pricing/commerceOfferPricing.js +139 -0
  171. package/dist/pricing/commerceOfferPricingCache.d.ts +10 -0
  172. package/dist/pricing/commerceOfferPricingCache.js +44 -0
  173. package/dist/pricing/commerceOfferPricingHandler.d.ts +21 -0
  174. package/dist/pricing/commerceOfferPricingHandler.js +78 -0
  175. package/dist/pricing/commercePriceAuthority.d.ts +28 -0
  176. package/dist/pricing/commercePriceAuthority.js +140 -0
  177. package/dist/pricing/commercePricingPolicyErrors.d.ts +40 -0
  178. package/dist/pricing/commercePricingPolicyErrors.js +67 -0
  179. package/dist/pricing/commerceQuoteBatchHandler.d.ts +37 -0
  180. package/dist/pricing/commerceQuoteBatchHandler.js +83 -0
  181. package/dist/pricing/commerceQuoteCatalogReadPort.d.ts +27 -0
  182. package/dist/pricing/commerceQuoteCatalogReadPort.js +8 -0
  183. package/dist/pricing/commerceQuoteHandler.d.ts +35 -0
  184. package/dist/pricing/commerceQuoteHandler.js +122 -0
  185. package/dist/pricing/commerceQuoteSnapshotExpect.d.ts +9 -0
  186. package/dist/pricing/commerceQuoteSnapshotExpect.js +22 -0
  187. package/dist/pricing/contracts/acquisitionTerms.d.ts +32 -0
  188. package/dist/pricing/contracts/acquisitionTerms.js +2 -0
  189. package/dist/pricing/contracts/authority.d.ts +27 -0
  190. package/dist/pricing/contracts/authority.js +1 -0
  191. package/dist/pricing/contracts/evidence.d.ts +33 -0
  192. package/dist/pricing/contracts/evidence.js +1 -0
  193. package/dist/pricing/contracts/index.d.ts +17 -0
  194. package/dist/pricing/contracts/index.js +7 -0
  195. package/dist/pricing/contracts/money.d.ts +27 -0
  196. package/dist/pricing/contracts/money.js +1 -0
  197. package/dist/pricing/contracts/offer.d.ts +52 -0
  198. package/dist/pricing/contracts/offer.js +4 -0
  199. package/dist/pricing/contracts/offerPolicy.d.ts +16 -0
  200. package/dist/pricing/contracts/offerPolicy.js +5 -0
  201. package/dist/pricing/contracts/policy.d.ts +22 -0
  202. package/dist/pricing/contracts/policy.js +3 -0
  203. package/dist/pricing/contracts/provenance.d.ts +24 -0
  204. package/dist/pricing/contracts/provenance.js +2 -0
  205. package/dist/pricing/contracts/quote.d.ts +94 -0
  206. package/dist/pricing/contracts/quote.js +1 -0
  207. package/dist/pricing/dbBackedCommerceQuoteHelpers.d.ts +78 -0
  208. package/dist/pricing/dbBackedCommerceQuoteHelpers.js +146 -0
  209. package/dist/pricing/dbBackedCommerceQuotePort.d.ts +74 -0
  210. package/dist/pricing/dbBackedCommerceQuotePort.js +223 -0
  211. package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.d.ts +4 -0
  212. package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.js +25 -0
  213. package/dist/pricing/index.d.ts +52 -0
  214. package/dist/pricing/index.js +36 -0
  215. package/dist/pricing/offerPolicyReadiness.d.ts +21 -0
  216. package/dist/pricing/offerPolicyReadiness.js +79 -0
  217. package/dist/pricing/offerPolicySchemas.d.ts +25 -0
  218. package/dist/pricing/offerPolicySchemas.js +15 -0
  219. package/dist/pricing/offerPricingSchemas.d.ts +315 -0
  220. package/dist/pricing/offerPricingSchemas.js +65 -0
  221. package/dist/pricing/ports.d.ts +13 -0
  222. package/dist/pricing/ports.js +9 -0
  223. package/dist/pricing/pricingPolicyToken.d.ts +39 -0
  224. package/dist/pricing/pricingPolicyToken.js +84 -0
  225. package/dist/pricing/quoteAcquisitionTerms.d.ts +2 -0
  226. package/dist/pricing/quoteAcquisitionTerms.js +4 -0
  227. package/dist/pricing/quoteCodeRejectionDetails.d.ts +20 -0
  228. package/dist/pricing/quoteCodeRejectionDetails.js +22 -0
  229. package/dist/pricing/quotePorts.d.ts +30 -0
  230. package/dist/pricing/quotePorts.js +20 -0
  231. package/dist/pricing/quotePrimitives.d.ts +13 -0
  232. package/dist/pricing/quotePrimitives.js +18 -0
  233. package/dist/pricing/quotePromotionEvidence.d.ts +39 -0
  234. package/dist/pricing/quotePromotionEvidence.js +73 -0
  235. package/dist/pricing/quoteSchemas.d.ts +1176 -0
  236. package/dist/pricing/quoteSchemas.js +196 -0
  237. package/dist/pricing/quoteShippingPromotions.d.ts +20 -0
  238. package/dist/pricing/quoteShippingPromotions.js +1 -0
  239. package/dist/pricing/subscriptionPricePolicy.d.ts +52 -0
  240. package/dist/pricing/subscriptionPricePolicy.js +96 -0
  241. package/dist/pricing/taxProfileGuard.d.ts +2 -0
  242. package/dist/pricing/taxProfileGuard.js +24 -0
  243. package/dist/pricing/validation.d.ts +2 -0
  244. package/dist/pricing/validation.js +3 -0
  245. package/dist/promotions/adminBindings.d.ts +72 -0
  246. package/dist/promotions/adminBindings.js +1 -0
  247. package/dist/promotions/adminPromotionCodesContracts.d.ts +498 -0
  248. package/dist/promotions/adminPromotionCodesContracts.js +211 -0
  249. package/dist/promotions/adminPromotionCodesDataPort.d.ts +47 -0
  250. package/dist/promotions/adminPromotionCodesDataPort.js +1 -0
  251. package/dist/promotions/adminPromotionCodesHandler.d.ts +14 -0
  252. package/dist/promotions/adminPromotionCodesHandler.js +194 -0
  253. package/dist/promotions/adminPromotionsContracts.d.ts +235 -0
  254. package/dist/promotions/adminPromotionsContracts.js +99 -0
  255. package/dist/promotions/adminPromotionsDataPort.d.ts +42 -0
  256. package/dist/promotions/adminPromotionsDataPort.js +1 -0
  257. package/dist/promotions/adminPromotionsHandler.d.ts +16 -0
  258. package/dist/promotions/adminPromotionsHandler.js +47 -0
  259. package/dist/promotions/commerceQuoteReadPreparation.d.ts +3 -0
  260. package/dist/promotions/commerceQuoteReadPreparation.js +27 -0
  261. package/dist/promotions/contracts/index.d.ts +387 -0
  262. package/dist/promotions/contracts/index.js +1 -0
  263. package/dist/promotions/index.d.ts +25 -0
  264. package/dist/promotions/index.js +22 -0
  265. package/dist/promotions/promoDataPort.d.ts +47 -0
  266. package/dist/promotions/promoDataPort.js +14 -0
  267. package/dist/promotions/promotionAcceptanceTelemetry.d.ts +29 -0
  268. package/dist/promotions/promotionAcceptanceTelemetry.js +45 -0
  269. package/dist/promotions/promotionBenefitDefinition.d.ts +37 -0
  270. package/dist/promotions/promotionBenefitDefinition.js +33 -0
  271. package/dist/promotions/promotionClaimSweepPort.d.ts +14 -0
  272. package/dist/promotions/promotionClaimSweepPort.js +8 -0
  273. package/dist/promotions/promotionClaims.d.ts +5 -0
  274. package/dist/promotions/promotionClaims.js +57 -0
  275. package/dist/promotions/promotionCodePreview.d.ts +11 -0
  276. package/dist/promotions/promotionCodePreview.js +154 -0
  277. package/dist/promotions/promotionCodeQuotePort.d.ts +25 -0
  278. package/dist/promotions/promotionCodeQuotePort.js +1 -0
  279. package/dist/promotions/promotionQuoteAcceptance.d.ts +70 -0
  280. package/dist/promotions/promotionQuoteAcceptance.js +202 -0
  281. package/dist/promotions/promotionQuoteBinding.d.ts +73 -0
  282. package/dist/promotions/promotionQuoteBinding.js +87 -0
  283. package/dist/promotions/quoteAcquisitionBinding.d.ts +6 -0
  284. package/dist/promotions/quoteAcquisitionBinding.js +1 -0
  285. package/dist/promotions/quoteAutomaticPromotions.d.ts +26 -0
  286. package/dist/promotions/quoteAutomaticPromotions.js +60 -0
  287. package/dist/promotions/quotePromoDiscounts.d.ts +36 -0
  288. package/dist/promotions/quotePromoDiscounts.js +146 -0
  289. package/dist/promotions/quotePromotionCodeAdjustments.d.ts +27 -0
  290. package/dist/promotions/quotePromotionCodeAdjustments.js +223 -0
  291. package/dist/promotions/quotePromotionV2.d.ts +30 -0
  292. package/dist/promotions/quotePromotionV2.js +186 -0
  293. package/dist/promotions/quoteShippingPolicy.d.ts +23 -0
  294. package/dist/promotions/quoteShippingPolicy.js +47 -0
  295. package/dist/promotions/sql.d.ts +14 -0
  296. package/dist/promotions/sql.js +5 -0
  297. package/dist/promotions/validation.d.ts +2 -0
  298. package/dist/promotions/validation.js +3 -0
  299. package/dist/shipping/addressCanonLookupHandler.d.ts +7 -0
  300. package/dist/shipping/addressCanonLookupHandler.js +105 -0
  301. package/dist/shipping/addressCanonical.d.ts +2 -0
  302. package/dist/shipping/addressCanonical.js +26 -0
  303. package/dist/shipping/addressPorts.d.ts +39 -0
  304. package/dist/shipping/addressPorts.js +1 -0
  305. package/dist/shipping/addressSchemas.d.ts +30 -0
  306. package/dist/shipping/addressSchemas.js +1 -0
  307. package/dist/shipping/adminShippingRateHandler.d.ts +4 -0
  308. package/dist/shipping/adminShippingRateHandler.js +64 -0
  309. package/dist/shipping/bindings.d.ts +57 -0
  310. package/dist/shipping/bindings.js +46 -0
  311. package/dist/shipping/contracts/address.d.ts +144 -0
  312. package/dist/shipping/contracts/address.js +1 -0
  313. package/dist/shipping/contracts/delivery.d.ts +110 -0
  314. package/dist/shipping/contracts/delivery.js +1 -0
  315. package/dist/shipping/contracts/index.d.ts +4 -0
  316. package/dist/shipping/contracts/index.js +1 -0
  317. package/dist/shipping/contracts/shippingRate.d.ts +11 -0
  318. package/dist/shipping/contracts/shippingRate.js +1 -0
  319. package/dist/shipping/contracts/threshold.d.ts +22 -0
  320. package/dist/shipping/contracts/threshold.js +1 -0
  321. package/dist/shipping/customerAddressesHandler.d.ts +5 -0
  322. package/dist/shipping/customerAddressesHandler.js +80 -0
  323. package/dist/shipping/customerSelfServiceAddressModels.d.ts +27 -0
  324. package/dist/shipping/customerSelfServiceAddressModels.js +101 -0
  325. package/dist/shipping/deliverySelectionHandler.d.ts +10 -0
  326. package/dist/shipping/deliverySelectionHandler.js +77 -0
  327. package/dist/shipping/deliverySelectionPort.d.ts +8 -0
  328. package/dist/shipping/deliverySelectionPort.js +1 -0
  329. package/dist/shipping/deliverySelectionSummary.d.ts +2 -0
  330. package/dist/shipping/deliverySelectionSummary.js +53 -0
  331. package/dist/shipping/handlerSchemas.d.ts +21 -0
  332. package/dist/shipping/handlerSchemas.js +1 -0
  333. package/dist/shipping/index.d.ts +20 -0
  334. package/dist/shipping/index.js +10 -0
  335. package/dist/shipping/pickupPointSearchPort.d.ts +4 -0
  336. package/dist/shipping/pickupPointSearchPort.js +1 -0
  337. package/dist/shipping/readDeliverySelectionEvidence.d.ts +2 -0
  338. package/dist/shipping/readDeliverySelectionEvidence.js +44 -0
  339. package/dist/shipping/shippingRatePorts.d.ts +52 -0
  340. package/dist/shipping/shippingRatePorts.js +1 -0
  341. package/dist/shipping/thresholdPolicy.d.ts +42 -0
  342. package/dist/shipping/thresholdPolicy.js +60 -0
  343. package/package.json +62 -2
  344. package/release-gates.json +263 -53
  345. package/sql/20260807140000_read_parity_catalog.sql +94 -0
  346. package/sql/20260810120000_storefront_catalog_attributes.sql +51 -0
  347. package/sql/20260812140000_sellable_bundle_catalog.sql +124 -0
  348. package/sql/20260812210000_bundle_operator_write_boundary.sql +567 -0
  349. package/sql/20260814000000_fulfillment_stock_evidence.sql +239 -0
  350. package/sql/20260815120000_automatic_subscription_renewal.sql +1083 -0
  351. package/sql/20260817180000_promotion_claim_lifecycle.sql +591 -0
  352. package/sql/20260817180100_promotion_claim_lifecycle_validation.sql +23 -0
  353. package/sql/20260827220000_catalog_document_revision_foundation.sql +226 -0
  354. package/sql/20260827220001_catalog_document_revision_foundation_validate.sql +10 -0
  355. package/sql/20260908100000_catalog_draft_foundation.sql +217 -0
  356. package/src/catalog/activeSkuSelection.ts +20 -0
  357. package/src/catalog/adminBindings.ts +59 -0
  358. package/src/catalog/adminBundleHandler.ts +165 -0
  359. package/src/catalog/adminBundleReadHandler.ts +263 -0
  360. package/src/catalog/adminBundleWritePort.ts +102 -0
  361. package/src/catalog/bundleAvailability.ts +129 -0
  362. package/src/catalog/bundleAvailabilityService.ts +171 -0
  363. package/src/catalog/bundleBindings.ts +29 -0
  364. package/src/catalog/bundleCatalogQueries.ts +98 -0
  365. package/src/catalog/bundleCatalogReadPort.ts +181 -0
  366. package/src/catalog/bundleCatalogStore.ts +274 -0
  367. package/src/catalog/bundlePriceSelection.ts +25 -0
  368. package/src/catalog/bundleRuleCodes.ts +134 -0
  369. package/src/catalog/bundleRules.ts +153 -0
  370. package/src/catalog/catalogDraftStore.ts +71 -0
  371. package/src/catalog/catalogSkuEnvelope.ts +214 -0
  372. package/src/catalog/catalogSkuEnvelopeMapper.ts +160 -0
  373. package/src/catalog/contracts/bundleAdmin.ts +20 -0
  374. package/src/catalog/contracts/bundleAvailability.ts +5 -0
  375. package/src/catalog/contracts/bundleRead.ts +13 -0
  376. package/src/catalog/contracts/draft.ts +69 -0
  377. package/src/catalog/contracts/foundation.ts +104 -0
  378. package/src/catalog/contracts/index.ts +14 -0
  379. package/src/catalog/contracts/lifecycle.ts +74 -0
  380. package/src/catalog/contracts/productMediaContracts.ts +170 -0
  381. package/src/catalog/contracts/productTypes.ts +35 -0
  382. package/src/catalog/contracts/resolveProductMedia.ts +85 -0
  383. package/src/catalog/contracts/sellable.ts +12 -0
  384. package/src/catalog/draftHandler.ts +105 -0
  385. package/src/catalog/draftPorts.ts +18 -0
  386. package/src/catalog/draftSchemas.ts +88 -0
  387. package/src/catalog/draftValidation.ts +100 -0
  388. package/src/catalog/effectiveBundleCatalogQueries.ts +80 -0
  389. package/src/catalog/effectiveBundleCatalogStore.ts +208 -0
  390. package/src/catalog/foundationSchemas.ts +123 -0
  391. package/src/catalog/index.ts +44 -0
  392. package/src/catalog/mediaSourcePack.ts +219 -0
  393. package/src/catalog/productTypeSchemas.ts +70 -0
  394. package/src/catalog/publicationPorts.ts +44 -0
  395. package/src/catalog/readPorts.ts +61 -0
  396. package/src/catalog/referenceCatalogHandler.ts +39 -0
  397. package/src/catalog/resolvedSkuProjection.ts +76 -0
  398. package/src/catalog/sellableBundleHandler.ts +133 -0
  399. package/src/catalog/sellableSchemas.ts +33 -0
  400. package/src/catalog/sql.ts +14 -0
  401. package/src/catalog/validation.ts +3 -0
  402. package/src/communications/contracts/index.ts +1 -0
  403. package/src/communications/contracts/marketingSync.ts +109 -0
  404. package/src/communications/index.ts +1 -0
  405. package/src/communications/klaviyo/consentPush.ts +19 -0
  406. package/src/communications/klaviyo/index.ts +649 -0
  407. package/src/communications/resend/index.ts +350 -0
  408. package/src/composition/catalogContribution.ts +32 -0
  409. package/src/composition/index.ts +3 -0
  410. package/src/composition/inventoryContribution.ts +24 -0
  411. package/src/composition/shippingContribution.ts +24 -0
  412. package/src/inventory/adminInventory.ts +251 -0
  413. package/src/inventory/bindings.ts +61 -0
  414. package/src/inventory/contracts/forecast.ts +96 -0
  415. package/src/inventory/contracts/index.ts +18 -0
  416. package/src/inventory/contracts/inventory.ts +14 -0
  417. package/src/inventory/contracts/newPurchaseStock.ts +23 -0
  418. package/src/inventory/contracts/reservation.ts +20 -0
  419. package/src/inventory/forecast.ts +239 -0
  420. package/src/inventory/index.ts +22 -0
  421. package/src/inventory/inventoryHandlers.ts +215 -0
  422. package/src/inventory/newPurchaseStockAvailability.ts +120 -0
  423. package/src/inventory/ports.ts +46 -0
  424. package/src/inventory/renewalReservation.ts +88 -0
  425. package/src/inventory/reservationPolicy.ts +27 -0
  426. package/src/inventory/schemas.ts +128 -0
  427. package/src/inventory/sql.ts +5 -0
  428. package/src/inventory/subscriptionForecastCalculation.ts +157 -0
  429. package/src/pricing/acquisitionFinancialPolicy.ts +26 -0
  430. package/src/pricing/acquisitionOfferPricing.ts +38 -0
  431. package/src/pricing/acquisitionOfferPricingHandler.ts +157 -0
  432. package/src/pricing/acquisitionOfferPricingSchemas.ts +35 -0
  433. package/src/pricing/acquisitionQuoteBinding.ts +12 -0
  434. package/src/pricing/acquisitionReadiness.ts +148 -0
  435. package/src/pricing/acquisitionTerms.ts +125 -0
  436. package/src/pricing/acquisitionTermsSchemas.ts +52 -0
  437. package/src/pricing/catalogFactsProvenance.ts +102 -0
  438. package/src/pricing/catalogFactsSchemas.ts +69 -0
  439. package/src/pricing/commerceOfferPricing.ts +224 -0
  440. package/src/pricing/commerceOfferPricingCache.ts +53 -0
  441. package/src/pricing/commerceOfferPricingHandler.ts +137 -0
  442. package/src/pricing/commercePriceAuthority.ts +169 -0
  443. package/src/pricing/commercePricingPolicyErrors.ts +88 -0
  444. package/src/pricing/commerceQuoteBatchHandler.ts +129 -0
  445. package/src/pricing/commerceQuoteCatalogReadPort.ts +42 -0
  446. package/src/pricing/commerceQuoteHandler.ts +199 -0
  447. package/src/pricing/commerceQuoteSnapshotExpect.ts +48 -0
  448. package/src/pricing/contracts/acquisitionTerms.ts +26 -0
  449. package/src/pricing/contracts/authority.ts +44 -0
  450. package/src/pricing/contracts/evidence.ts +25 -0
  451. package/src/pricing/contracts/index.ts +17 -0
  452. package/src/pricing/contracts/money.ts +32 -0
  453. package/src/pricing/contracts/offer.ts +42 -0
  454. package/src/pricing/contracts/offerPolicy.ts +17 -0
  455. package/src/pricing/contracts/policy.ts +26 -0
  456. package/src/pricing/contracts/provenance.ts +19 -0
  457. package/src/pricing/contracts/quote.ts +106 -0
  458. package/src/pricing/dbBackedCommerceQuoteHelpers.ts +256 -0
  459. package/src/pricing/dbBackedCommerceQuotePort.ts +280 -0
  460. package/src/pricing/dbBackedCommerceQuoteSnapshotVerifier.ts +49 -0
  461. package/src/pricing/index.ts +53 -0
  462. package/src/pricing/offerPolicyReadiness.ts +110 -0
  463. package/src/pricing/offerPolicySchemas.ts +23 -0
  464. package/src/pricing/offerPricingSchemas.ts +92 -0
  465. package/src/pricing/ports.ts +17 -0
  466. package/src/pricing/pricingPolicyToken.ts +119 -0
  467. package/src/pricing/quoteAcquisitionTerms.ts +10 -0
  468. package/src/pricing/quoteCodeRejectionDetails.ts +23 -0
  469. package/src/pricing/quotePorts.ts +58 -0
  470. package/src/pricing/quotePrimitives.ts +21 -0
  471. package/src/pricing/quotePromotionEvidence.ts +82 -0
  472. package/src/pricing/quoteSchemas.ts +230 -0
  473. package/src/pricing/quoteShippingPromotions.ts +21 -0
  474. package/src/pricing/subscriptionPricePolicy.ts +113 -0
  475. package/src/pricing/taxProfileGuard.ts +33 -0
  476. package/src/pricing/validation.ts +3 -0
  477. package/src/promotions/adminBindings.ts +53 -0
  478. package/src/promotions/adminPromotionCodesContracts.ts +244 -0
  479. package/src/promotions/adminPromotionCodesDataPort.ts +56 -0
  480. package/src/promotions/adminPromotionCodesHandler.ts +254 -0
  481. package/src/promotions/adminPromotionsContracts.ts +121 -0
  482. package/src/promotions/adminPromotionsDataPort.ts +48 -0
  483. package/src/promotions/adminPromotionsHandler.ts +72 -0
  484. package/src/promotions/commerceQuoteReadPreparation.ts +29 -0
  485. package/src/promotions/contracts/index.ts +387 -0
  486. package/src/promotions/index.ts +25 -0
  487. package/src/promotions/promoDataPort.ts +65 -0
  488. package/src/promotions/promotionAcceptanceTelemetry.ts +73 -0
  489. package/src/promotions/promotionBenefitDefinition.ts +48 -0
  490. package/src/promotions/promotionClaimSweepPort.ts +23 -0
  491. package/src/promotions/promotionClaims.ts +70 -0
  492. package/src/promotions/promotionCodePreview.ts +183 -0
  493. package/src/promotions/promotionCodeQuotePort.ts +35 -0
  494. package/src/promotions/promotionQuoteAcceptance.ts +291 -0
  495. package/src/promotions/promotionQuoteBinding.ts +163 -0
  496. package/src/promotions/quoteAcquisitionBinding.ts +7 -0
  497. package/src/promotions/quoteAutomaticPromotions.ts +84 -0
  498. package/src/promotions/quotePromoDiscounts.ts +194 -0
  499. package/src/promotions/quotePromotionCodeAdjustments.ts +277 -0
  500. package/src/promotions/quotePromotionV2.ts +239 -0
  501. package/src/promotions/quoteShippingPolicy.ts +61 -0
  502. package/src/promotions/sql.ts +5 -0
  503. package/src/promotions/validation.ts +3 -0
  504. package/src/shipping/addressCanonLookupHandler.ts +114 -0
  505. package/src/shipping/addressCanonical.ts +31 -0
  506. package/src/shipping/addressPorts.ts +48 -0
  507. package/src/shipping/addressSchemas.ts +28 -0
  508. package/src/shipping/adminShippingRateHandler.ts +72 -0
  509. package/src/shipping/bindings.ts +74 -0
  510. package/src/shipping/contracts/address.ts +71 -0
  511. package/src/shipping/contracts/delivery.ts +114 -0
  512. package/src/shipping/contracts/index.ts +19 -0
  513. package/src/shipping/contracts/shippingRate.ts +7 -0
  514. package/src/shipping/contracts/threshold.ts +22 -0
  515. package/src/shipping/customerAddressesHandler.ts +100 -0
  516. package/src/shipping/customerSelfServiceAddressModels.ts +124 -0
  517. package/src/shipping/deliverySelectionHandler.ts +94 -0
  518. package/src/shipping/deliverySelectionPort.ts +10 -0
  519. package/src/shipping/deliverySelectionSummary.ts +56 -0
  520. package/src/shipping/handlerSchemas.ts +19 -0
  521. package/src/shipping/index.ts +26 -0
  522. package/src/shipping/pickupPointSearchPort.ts +8 -0
  523. package/src/shipping/readDeliverySelectionEvidence.ts +51 -0
  524. package/src/shipping/shippingRatePorts.ts +36 -0
  525. package/src/shipping/thresholdPolicy.ts +65 -0
@@ -0,0 +1,171 @@
1
+ import type {
2
+ BundleAvailability,
3
+ BundleAvailabilityComponent,
4
+ } from "./bundleAvailability.js";
5
+ import type {
6
+ BundleStockAvailability as CommerceOfferAvailability,
7
+ BundleStockPort as CommerceOfferAvailabilityPort,
8
+ BundleStockRequestItem as CommerceOfferAvailabilityRequestItem,
9
+ } from "./bundleBindings.js";
10
+ import type {
11
+ ActiveBundleComposition,
12
+ BundleCatalogReadPort,
13
+ BundleComponentRow,
14
+ } from "./bundleCatalogReadPort.js";
15
+
16
+ /**
17
+ * Derived bundle stock, composed from the two ports that already know the halves:
18
+ * the bundle read port knows the bill of materials, the EXISTING commerce offer
19
+ * availability port knows what a unit's stock is. Nothing here re-derives stock and
20
+ * nothing here opens a database handle.
21
+ *
22
+ * ONE BATCHED CALL, ALWAYS. Every component of every bundle in the request is
23
+ * asked for in a single `getAvailability`, deduplicated by sku, because the
24
+ * underlying port answers a set in three queries — asking per bundle would turn a
25
+ * catalogue listing into a query storm and would let two bundles sharing a unit
26
+ * disagree about its stock inside one response.
27
+ *
28
+ * A sku the availability port does not answer for is a MISSING figure, not zero:
29
+ * it is folded in as `sellableNow: null`, so the pure kernel reports the bundle as
30
+ * unknown and names the component rather than quietly overselling or hiding it.
31
+ */
32
+
33
+ export interface BundleAvailabilityServiceDeps {
34
+ bundleCatalogReadPort: BundleCatalogReadPort;
35
+ offerAvailabilityPort: CommerceOfferAvailabilityPort;
36
+ /** Threshold handed to the pure kernel; its own default applies when omitted. */
37
+ lowStockThreshold?: number;
38
+ includeAddonsInStock?: boolean;
39
+ }
40
+
41
+ export interface BundleAvailabilityRow {
42
+ composition: ActiveBundleComposition;
43
+ availability: BundleAvailability;
44
+ /**
45
+ * The EXACT rows the kernel was given, carried out again rather than recomputed.
46
+ *
47
+ * The bundle-level answer names one limiting component; an operator staring at a bundle that
48
+ * cannot ship needs to know how far off every OTHER component is too, so they can tell "order one
49
+ * more of this" from "this bundle is months away". These rows are the only place that figure
50
+ * exists — the kernel folds them into a single number and the sellable feed's components carry
51
+ * price, never stock. Returning them costs nothing here and is the alternative to a second stock
52
+ * derivation somewhere that can disagree with this one.
53
+ */
54
+ components: readonly BundleAvailabilityComponent[];
55
+ }
56
+
57
+ export interface BundleAvailabilityService {
58
+ /** Fold stock into a set of compositions the caller already holds. */
59
+ describeCompositions(
60
+ compositions: readonly ActiveBundleComposition[],
61
+ ): Promise<BundleAvailabilityRow[]>;
62
+ /** Read the live sellable set and fold stock into it. */
63
+ describeActiveBundles(input?: { currency?: string }): Promise<BundleAvailabilityRow[]>;
64
+ }
65
+
66
+ export function createBundleAvailabilityServices({ deriveBundleAvailability }: { deriveBundleAvailability: (input: import("./bundleAvailability.js").DeriveBundleAvailabilityInput) => BundleAvailability }) {
67
+ function createBundleAvailabilityService(
68
+ deps: BundleAvailabilityServiceDeps,
69
+ ): BundleAvailabilityService {
70
+ async function describeCompositions(
71
+ compositions: readonly ActiveBundleComposition[],
72
+ ): Promise<BundleAvailabilityRow[]> {
73
+ if (compositions.length === 0) return [];
74
+
75
+ const items = requestItems(compositions);
76
+ const stock = items.length === 0
77
+ ? new Map<string, number | null>()
78
+ : sellableBySku(await deps.offerAvailabilityPort.getAvailability({ items }));
79
+
80
+ return compositions.map((composition) => {
81
+ const components = composition.components.map((component) => ({
82
+ sku: component.sku,
83
+ quantity: component.quantity,
84
+ isAddon: component.isAddon,
85
+ // `has` distinguishes "answered null" from "never answered"; both fold to
86
+ // null, and neither is allowed to become a number here.
87
+ sellableNow: stock.has(component.sku) ? (stock.get(component.sku) ?? null) : null,
88
+ }));
89
+ return {
90
+ composition,
91
+ components,
92
+ availability: deriveBundleAvailability({
93
+ components,
94
+ lowStockThreshold: deps.lowStockThreshold,
95
+ includeAddonsInStock: deps.includeAddonsInStock,
96
+ }),
97
+ };
98
+ });
99
+ }
100
+
101
+ return {
102
+ describeCompositions,
103
+ async describeActiveBundles(input: { currency?: string } = {}) {
104
+ return describeCompositions(
105
+ await deps.bundleCatalogReadPort.listActiveBundleCompositions(input),
106
+ );
107
+ },
108
+ };
109
+ }
110
+
111
+ return { createBundleAvailabilityService };
112
+ }
113
+
114
+ /**
115
+ * The port to use where no stock source is bound at all.
116
+ *
117
+ * It answers every item with `sellableNow: null`, which the kernel reads as
118
+ * unknown — so a deployment without an inventory rail publishes bundles whose
119
+ * price is exact and whose stock is honestly unstated. The alternative, omitting
120
+ * the availability block, would have made "we do not know" indistinguishable from
121
+ * "we did not ask", and the alternative to THAT — defaulting to available —
122
+ * oversells on a deployment that never counted anything.
123
+ */
124
+ export function createUnknownOfferAvailabilityPort(): CommerceOfferAvailabilityPort {
125
+ return {
126
+ getAvailability({ items }) {
127
+ return Promise.resolve(
128
+ items.map((item) => ({
129
+ sku: item.sku,
130
+ productSlug: item.productSlug,
131
+ variantId: item.variantId,
132
+ status: "unknown" as const,
133
+ visibleInConfigurator: true,
134
+ sellableNow: null,
135
+ reasonCode: "stock_unknown",
136
+ source: "unbound",
137
+ })),
138
+ );
139
+ },
140
+ };
141
+ }
142
+
143
+ /**
144
+ * One request item per distinct sku across every bundle. `requestedQuantity` stays
145
+ * at the port's own default of one: the question asked is "how many units exist",
146
+ * and the multiplication by the bill of materials belongs to the pure kernel,
147
+ * which is the only place that knows how many bundles a figure buys.
148
+ */
149
+ function requestItems(
150
+ compositions: readonly ActiveBundleComposition[],
151
+ ): CommerceOfferAvailabilityRequestItem[] {
152
+ const bySku = new Map<string, BundleComponentRow>();
153
+ for (const composition of compositions) {
154
+ for (const component of composition.components) {
155
+ if (!bySku.has(component.sku)) bySku.set(component.sku, component);
156
+ }
157
+ }
158
+ return [...bySku.values()].map((component) => ({
159
+ sku: component.sku,
160
+ productSlug: component.productSlug,
161
+ variantId: component.variantId,
162
+ requestedQuantity: 1,
163
+ checkoutMode: "one_time" as const,
164
+ }));
165
+ }
166
+
167
+ function sellableBySku(
168
+ answers: readonly CommerceOfferAvailability[],
169
+ ): Map<string, number | null> {
170
+ return new Map(answers.map((answer) => [answer.sku, answer.sellableNow ?? null]));
171
+ }
@@ -0,0 +1,29 @@
1
+ import type { BundleActorKind } from "./bundleRuleCodes.js";
2
+
3
+ /** The host's normalized stock seam; no inventory implementation is owned here. */
4
+ export type BundleStockStatus = "available" | "low_stock" | "out_of_stock" | "unknown";
5
+ export interface BundleStockRequestItem {
6
+ sku: string;
7
+ productSlug: string;
8
+ variantId: string;
9
+ requestedQuantity: number;
10
+ checkoutMode: "one_time" | "subscription";
11
+ }
12
+ export interface BundleStockAvailability {
13
+ sku: string;
14
+ productSlug: string;
15
+ variantId: string;
16
+ status: BundleStockStatus;
17
+ visibleInConfigurator: boolean;
18
+ sellableNow: number | null;
19
+ reasonCode: string;
20
+ source: string;
21
+ }
22
+ export interface BundleStockPort {
23
+ getAvailability(input: { items: readonly BundleStockRequestItem[] }): Promise<BundleStockAvailability[]>;
24
+ }
25
+ export interface BundleRuleBindings {
26
+ assertActivateNotMachineActor(input: { operation: string; actorKind: BundleActorKind }): "DRAFT_ONLY_FOR_MACHINE" | null;
27
+ offerAvailabilityStatusFor(sellableNow: number | null, lowStockThreshold?: number): BundleStockStatus;
28
+ offerAvailabilityReasonCode(status: BundleStockStatus): string;
29
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * The statements the direct-Postgres bundle read adapter renders.
3
+ *
4
+ * They live beside the adapter rather than inside it because they are the part a
5
+ * reader comes here to check — which relations are touched, which columns are
6
+ * asked for, and how a component's reference price is resolved — and reading them
7
+ * should not mean scrolling past the row marshalling that consumes them.
8
+ */
9
+
10
+ export const SUMMARY_COLUMNS = `
11
+ b.id, b.code, b.title, b.status, b.fulfillment_mode, b.updated_at,
12
+ b.composition_constraint, b.metadata,
13
+ (SELECT count(*) FROM public.catalog_bundle_components c WHERE c.bundle_id = b.id)
14
+ AS component_count,
15
+ EXISTS (SELECT 1 FROM public.catalog_bundle_prices p WHERE p.bundle_id = b.id AND p.active)
16
+ AS has_active_target_price`;
17
+
18
+ export const LIST_FILTER = `
19
+ WHERE ($1::text = 'all' OR b.status = $1::text)
20
+ AND ($2::text IS NULL OR b.code ILIKE '%' || $2 || '%' OR b.title ILIKE '%' || $2 || '%')`;
21
+
22
+ export const LIST_SQL = `SELECT ${SUMMARY_COLUMNS} FROM public.catalog_bundles b ${LIST_FILTER}
23
+ ORDER BY b.code LIMIT $3 OFFSET $4`;
24
+
25
+ export const COUNT_SQL = `SELECT count(*) AS total FROM public.catalog_bundles b ${LIST_FILTER}`;
26
+
27
+ export const DETAIL_SQL = `SELECT ${SUMMARY_COLUMNS} FROM public.catalog_bundles b WHERE b.code = $1`;
28
+
29
+ /**
30
+ * The unit's reference price in ONE named list: the lowest tier that is active,
31
+ * newest window first. A unit the list prices nothing for resolves to NULL rather
32
+ * than dropping the component, so a caller sees an unpriced part instead of a
33
+ * shorter bill of materials.
34
+ */
35
+ export const REFERENCE_PRICE = `(
36
+ SELECT pe.unit_price_minor FROM public.price_entries pe
37
+ WHERE pe.variant_id = s.id AND pe.price_list_id = %LIST% AND pe.active
38
+ ORDER BY pe.min_qty ASC, pe.valid_from DESC LIMIT 1)`;
39
+
40
+ export const COMPONENT_SQL = `
41
+ SELECT c.bundle_id, s.sku, s.title, pr.slug AS product_slug, s.id AS variant_id,
42
+ c.quantity, c.is_addon, c.sort_order,
43
+ ${REFERENCE_PRICE.replace("%LIST%", "$2::uuid")} AS reference_unit_price_minor
44
+ FROM public.catalog_bundle_components c
45
+ JOIN public.catalog_skus s ON s.id = c.catalog_sku_id
46
+ JOIN public.catalog_products pr ON pr.id = s.product_id
47
+ WHERE c.bundle_id = $1::uuid
48
+ ORDER BY c.sort_order, s.sku`;
49
+
50
+ // One statement for the whole feed: each bundle carries its own price list, so the
51
+ // per-bundle list is zipped in rather than looped over.
52
+ export const FEED_COMPONENT_SQL = `
53
+ SELECT c.bundle_id, s.sku, s.title, pr.slug AS product_slug, s.id AS variant_id,
54
+ c.quantity, c.is_addon, c.sort_order,
55
+ ${REFERENCE_PRICE.replace("%LIST%", "selected.price_list_id")} AS reference_unit_price_minor
56
+ FROM unnest($1::uuid[], $2::uuid[]) AS selected(bundle_id, price_list_id)
57
+ JOIN public.catalog_bundle_components c ON c.bundle_id = selected.bundle_id
58
+ JOIN public.catalog_skus s ON s.id = c.catalog_sku_id
59
+ JOIN public.catalog_products pr ON pr.id = s.product_id
60
+ ORDER BY c.bundle_id, c.sort_order, s.sku`;
61
+
62
+ export const PRICE_SQL = `
63
+ SELECT p.mode, p.target_price_minor, list.currency, p.amount_kind, p.active,
64
+ p.valid_from, p.valid_to
65
+ FROM public.catalog_bundle_prices p
66
+ JOIN public.price_lists AS list ON list.id = p.price_list_id
67
+ WHERE p.bundle_id = $1::uuid
68
+ ORDER BY p.valid_from DESC`;
69
+
70
+ export const OWN_LIST_SQL = `
71
+ SELECT list.id, list.currency
72
+ FROM public.catalog_bundle_prices p
73
+ JOIN public.price_lists AS list ON list.id = p.price_list_id
74
+ WHERE p.bundle_id = $1::uuid AND p.active AND ($2::text IS NULL OR p.mode = $2::text)
75
+ ORDER BY p.valid_from DESC LIMIT 1`;
76
+
77
+ export const CURRENCY_LIST_SQL = `
78
+ SELECT id, currency FROM public.price_lists
79
+ WHERE currency = $1::text AND status = 'active'
80
+ ORDER BY created_at DESC LIMIT 1`;
81
+
82
+ export const FEED_SQL = `
83
+ SELECT b.id, b.code, b.title, b.fulfillment_mode, p.mode, p.target_price_minor,
84
+ p.price_list_id, list.currency
85
+ FROM public.catalog_bundles b
86
+ JOIN public.catalog_bundle_prices p ON p.bundle_id = b.id AND p.active
87
+ JOIN public.price_lists AS list ON list.id = p.price_list_id
88
+ WHERE b.status = 'active' AND ($1::text IS NULL OR list.currency = $1::text)
89
+ ORDER BY b.code, p.valid_from DESC`;
90
+
91
+ export const HISTORY_SQL = `
92
+ SELECT id, bundle_code, action, before_state, after_state, created_at
93
+ FROM public.catalog_bundle_write_events
94
+ WHERE bundle_code = $1::text
95
+ ORDER BY created_at DESC LIMIT $2 OFFSET $3`;
96
+
97
+ export const HISTORY_COUNT_SQL = `
98
+ SELECT count(*) AS total FROM public.catalog_bundle_write_events WHERE bundle_code = $1::text`;
@@ -0,0 +1,181 @@
1
+ /**
2
+ * The semantic READ port for bundles.
3
+ *
4
+ * This file names the CAPABILITY, never the storage: no table, no routine, no
5
+ * data-client type and no vendor appears here, and the domain layer opens no
6
+ * database handle of its own. Both shipped read adapters implement exactly this
7
+ * interface and are proved against ONE shared scenario table, so a caller cannot
8
+ * tell them apart. It is the same shape the write port
9
+ * (`adminBundleWritePort.ts`) established in the previous wave.
10
+ *
11
+ * Reads are plain SELECTs rather than security-definer routines: the write
12
+ * boundary is where authority lives, and a read that re-implemented it would be a
13
+ * second place for the same rules to be written down. The admin surface reads the
14
+ * whole lifecycle (draft, active, archived); the sellable feed asks a separate
15
+ * question and gets only what is live.
16
+ *
17
+ * COMPONENT PRICES ARE RESOLVED, NOT STORED. A bundle stores one target price for
18
+ * the whole set; a component's REFERENCE unit price is whatever the selected
19
+ * price list says today. The adapters therefore join the catalogue and the price
20
+ * list themselves, and hand back a resolved figure (or `null` when the list
21
+ * prices nothing for that unit) so the allocator upstream never re-reads storage.
22
+ */
23
+
24
+ /**
25
+ * A read that FAILED, as opposed to a read that found nothing.
26
+ *
27
+ * Both adapters raise this rather than returning an empty page, because the two
28
+ * outcomes are opposite: an empty catalogue is a fact a storefront may cache and
29
+ * show, and a failed query is not. The class lives on the port so neither chain
30
+ * owns the distinction.
31
+ */
32
+ export class BundleCatalogReadError extends Error {
33
+ constructor(message: string) {
34
+ super(message);
35
+ this.name = "BundleCatalogReadError";
36
+ }
37
+ }
38
+
39
+ /** Which lifecycle rows an admin list asks for. `all` is the admin default. */
40
+ export type BundleListStatusFilter = "draft" | "active" | "archived" | "all";
41
+
42
+ export interface ListBundlesInput {
43
+ status: BundleListStatusFilter;
44
+ /** Free-text match over code and title; absent means no narrowing. */
45
+ query?: string;
46
+ limit: number;
47
+ offset: number;
48
+ }
49
+
50
+ export interface BundleSummary {
51
+ code: string;
52
+ title: string;
53
+ status: string;
54
+ fulfillmentMode: string;
55
+ componentCount: number;
56
+ hasActiveTargetPrice: boolean;
57
+ updatedAt: string;
58
+ }
59
+
60
+ export interface ListBundlesResult {
61
+ bundles: BundleSummary[];
62
+ total: number;
63
+ }
64
+
65
+ /**
66
+ * One line of the bill of materials, already joined to the catalogue.
67
+ *
68
+ * `productSlug` and `variantId` are carried because the availability port
69
+ * addresses stock by all three coordinates; a caller that had only the sku would
70
+ * have to re-open the catalogue to ask about stock, which is exactly the
71
+ * round-trip this DTO exists to remove.
72
+ */
73
+ export interface BundleComponentRow {
74
+ sku: string;
75
+ title: string | null;
76
+ productSlug: string;
77
+ variantId: string;
78
+ quantity: number;
79
+ isAddon: boolean;
80
+ sortOrder: number;
81
+ /** Resolved from the selected price list; `null` when it prices no such unit. */
82
+ referenceUnitPriceMinor: number | null;
83
+ }
84
+
85
+ export interface BundleTargetPriceRow {
86
+ mode: string;
87
+ targetPriceMinor: number;
88
+ currency: string;
89
+ amountKind: string;
90
+ active: boolean;
91
+ validFrom: string;
92
+ validTo: string | null;
93
+ }
94
+
95
+ export interface BundleDetail extends BundleSummary {
96
+ /** The opaque `{kind, version, data}` envelope; `null` for an unconstrained bundle. */
97
+ compositionConstraint: { kind: string; version: number; data: Record<string, unknown> } | null;
98
+ metadata: Record<string, unknown>;
99
+ components: BundleComponentRow[];
100
+ prices: BundleTargetPriceRow[];
101
+ /** Present only when the host selects effective price authority. */
102
+ resolvedTargetPrice?: BundleTargetPriceRow | null;
103
+ /** The currency whose list resolved `referenceUnitPriceMinor`; `null` if none did. */
104
+ resolvedCurrency: string | null;
105
+ /**
106
+ * The price list those reference figures came from. Carried because a price
107
+ * preview has to name the list it priced against — an amount without the list
108
+ * that gave it meaning is not reproducible.
109
+ */
110
+ resolvedPriceListId: string | null;
111
+ }
112
+
113
+ export interface GetBundleInput {
114
+ code: string;
115
+ /**
116
+ * Price the components against THIS currency's active list. Omitted means "the
117
+ * list this bundle's own active target price is written into", which is the
118
+ * only currency an operator has actually chosen for it.
119
+ */
120
+ currency?: string;
121
+ /** Narrow the target price whose list is selected; omitted means any mode (the opt-in effective store defaults to one_time). */
122
+ mode?: string;
123
+ regionCode?: string;
124
+ atTime?: string;
125
+ }
126
+
127
+ /**
128
+ * One live, sellable bundle: active status, an active target price, and its
129
+ * components priced in that price's own currency. This is the feed's row, and it
130
+ * is deliberately a different question from `getBundle` — the storefront must
131
+ * never be able to see a draft by asking the read port nicely.
132
+ */
133
+ export interface ActiveBundleComposition {
134
+ code: string;
135
+ title: string;
136
+ fulfillmentMode: string;
137
+ currency: string;
138
+ targetPriceMinor: number;
139
+ mode: string;
140
+ components: BundleComponentRow[];
141
+ }
142
+
143
+ export interface BundleHistoryEvent {
144
+ id: string;
145
+ action: string;
146
+ actorKind: string | null;
147
+ actorEmail: string | null;
148
+ entityId: string | null;
149
+ oldValue: unknown;
150
+ newValue: unknown;
151
+ occurredAt: string;
152
+ }
153
+
154
+ export interface BundleHistoryInput {
155
+ code: string;
156
+ limit: number;
157
+ offset: number;
158
+ }
159
+
160
+ export interface BundleHistoryResult {
161
+ events: BundleHistoryEvent[];
162
+ total: number;
163
+ }
164
+
165
+ export interface BundleCatalogReadPort {
166
+ /** Admin list across the whole lifecycle, newest-agnostic and code-ordered. */
167
+ listBundles(input: ListBundlesInput): Promise<ListBundlesResult>;
168
+ /** Full admin detail, or `null` when no bundle carries that code. */
169
+ getBundle(input: GetBundleInput): Promise<BundleDetail | null>;
170
+ /**
171
+ * Every bundle a storefront may sell right now. Never returns a draft or an
172
+ * archived bundle, and never a bundle without an active target price.
173
+ */
174
+ listActiveBundleCompositions(input?: { currency?: string; regionCode?: string; mode?: "one_time" | "subscription"; atTime?: string }): Promise<ActiveBundleComposition[]>;
175
+ /**
176
+ * The operator trail for one bundle. The two chains answer from different
177
+ * ledgers — a managed audit table and the platform's neutral write-event
178
+ * relation — which is why this is a port method rather than a shared query.
179
+ */
180
+ listBundleHistory(input: BundleHistoryInput): Promise<BundleHistoryResult>;
181
+ }