@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,214 @@
1
+ import {
2
+ CatalogSkuAuthorityError,
3
+ catalogSkuEnvelopeSelectorSchema,
4
+ type CatalogSkuEnvelopeSelector,
5
+ type NeutralSkuEnvelopeV1,
6
+ } from "./foundationSchemas.js";
7
+ import { parseCatalogActiveSkuSelection } from "./activeSkuSelection.js";
8
+ import type {
9
+ CatalogActiveSkuEnvelopeListQuery,
10
+ CatalogSkuEnvelopeListQuery,
11
+ CatalogSkuEnvelopePage,
12
+ PublicCatalogSkuEnvelopeReadPort,
13
+ } from "./readPorts.js";
14
+ import type { PgQueryExecutor } from "../data/index.js";
15
+ import {
16
+ mapPostgresCatalogSkuEnvelope,
17
+ readPostgresCatalogSkuIdentifiers,
18
+ requirePostgresCatalogSkuEnvelopeRow,
19
+ type PostgresCatalogSkuEnvelopeRow,
20
+ } from "./catalogSkuEnvelopeMapper.js";
21
+
22
+ const ENVELOPE_COLUMNS_SQL = `
23
+ product.id AS product_id,
24
+ product.slug AS product_slug,
25
+ product.primary_sku_id,
26
+ product.current_document_revision_id,
27
+ sku.id AS sku_id,
28
+ sku.product_id AS sku_product_id,
29
+ sku.sku AS sku_code,
30
+ sku.net_weight_g AS net_content_unscaled,
31
+ sku.status AS sku_status,
32
+ sku.sellable_standalone AS sellable_one_time,
33
+ sku.sellable_in_subscription AS sellable_subscription,
34
+ sku.is_addon,
35
+ sku.asset_ref,
36
+ revision.id AS document_revision_id,
37
+ revision.product_id AS document_product_id,
38
+ revision.revision_no AS document_revision_no,
39
+ revision.schema_id AS document_schema_id,
40
+ revision.document_ref AS document_ref,
41
+ revision.source_ref AS document_source_ref,
42
+ revision.digest AS document_digest`;
43
+
44
+ const SKU_ENVELOPE_FROM_SQL = `
45
+ SELECT ${ENVELOPE_COLUMNS_SQL}
46
+ FROM public.catalog_skus AS sku
47
+ JOIN public.catalog_products AS product
48
+ ON product.id = sku.product_id
49
+ LEFT JOIN public.catalog_product_document_revisions AS revision
50
+ ON revision.id = product.current_document_revision_id`;
51
+
52
+ const LIST_ENVELOPES_SQL = `${SKU_ENVELOPE_FROM_SQL}
53
+ WHERE ($1::uuid IS NULL OR sku.id > $1::uuid)
54
+ ORDER BY sku.id
55
+ LIMIT $2::integer`;
56
+
57
+ const LIST_ACTIVE_ENVELOPES_SQL = `${SKU_ENVELOPE_FROM_SQL}
58
+ WHERE sku.status = 'active'
59
+ AND (sku.sellable_standalone OR sku.sellable_in_subscription)
60
+ AND ($3::text[] IS NULL OR sku.sku = ANY($3::text[]))
61
+ AND ($1::uuid IS NULL OR sku.id > $1::uuid)
62
+ ORDER BY sku.id
63
+ LIMIT $2::integer`;
64
+
65
+ const LIST_PUBLIC_ACTIVE_ENVELOPES_SQL = `${SKU_ENVELOPE_FROM_SQL}
66
+ WHERE sku.status = 'active'
67
+ AND ($1::uuid IS NULL OR sku.id > $1::uuid)
68
+ ORDER BY sku.id
69
+ LIMIT $2::integer`;
70
+
71
+ const LIST_PUBLIC_ACTIVE_PRODUCT_ENVELOPES_SQL = `${SKU_ENVELOPE_FROM_SQL}
72
+ WHERE sku.product_id = $1::uuid
73
+ AND sku.status = 'active'
74
+ AND ($2::uuid IS NULL OR sku.id > $2::uuid)
75
+ ORDER BY sku.id
76
+ LIMIT $3::integer`;
77
+
78
+ const DETAIL_ENVELOPE_BY_ID_SQL = `${SKU_ENVELOPE_FROM_SQL}
79
+ WHERE sku.id = $1::uuid`;
80
+
81
+ const DETAIL_ENVELOPE_BY_SKU_CODE_SQL = `${SKU_ENVELOPE_FROM_SQL}
82
+ WHERE sku.sku = $1
83
+ LIMIT 2`;
84
+
85
+ const DETAIL_ENVELOPE_BY_PRIMARY_PRODUCT_SLUG_SQL = `
86
+ SELECT ${ENVELOPE_COLUMNS_SQL}
87
+ FROM public.catalog_products AS product
88
+ LEFT JOIN public.catalog_skus AS sku
89
+ ON sku.id = product.primary_sku_id
90
+ LEFT JOIN public.catalog_product_document_revisions AS revision
91
+ ON revision.id = product.current_document_revision_id
92
+ WHERE product.slug = $1
93
+ LIMIT 2`;
94
+
95
+ /**
96
+ * Portable W2a envelope reader. It reads only product/SKU/revision references
97
+ * and neutral identifiers; application document content never crosses this seam.
98
+ */
99
+ export function createPostgresCatalogSkuEnvelopeReadPort(
100
+ executor: PgQueryExecutor,
101
+ ): PublicCatalogSkuEnvelopeReadPort {
102
+ return {
103
+ async listSkuEnvelopes(query: CatalogSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage> {
104
+ return listEnvelopes(executor, query, LIST_ENVELOPES_SQL);
105
+ },
106
+
107
+ async listActiveSkuEnvelopes(query: CatalogActiveSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage> {
108
+ const skuCodes = parseCatalogActiveSkuSelection(query.skuCodes);
109
+ return listEnvelopes(executor, query, LIST_ACTIVE_ENVELOPES_SQL, [], [skuCodes ?? null]);
110
+ },
111
+
112
+ async listPublicActiveSkuEnvelopes(query: CatalogSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage> {
113
+ return listEnvelopes(executor, query, LIST_PUBLIC_ACTIVE_ENVELOPES_SQL);
114
+ },
115
+
116
+ async listPublicActiveProductSkuEnvelopes(
117
+ productId: string,
118
+ query: CatalogSkuEnvelopeListQuery,
119
+ ): Promise<CatalogSkuEnvelopePage> {
120
+ return listEnvelopes(executor, query, LIST_PUBLIC_ACTIVE_PRODUCT_ENVELOPES_SQL, [productId]);
121
+ },
122
+
123
+ async getSkuEnvelope(selector: CatalogSkuEnvelopeSelector): Promise<NeutralSkuEnvelopeV1 | null> {
124
+ const parsed = catalogSkuEnvelopeSelectorSchema.parse(selector);
125
+ const rows = await readRows(
126
+ executor,
127
+ parsed.kind === "sku_code"
128
+ ? DETAIL_ENVELOPE_BY_SKU_CODE_SQL
129
+ : DETAIL_ENVELOPE_BY_PRIMARY_PRODUCT_SLUG_SQL,
130
+ [parsed.kind === "sku_code" ? parsed.skuCode : parsed.productSlug],
131
+ );
132
+ const row = uniqueDetailRow(
133
+ rows,
134
+ parsed.kind === "sku_code"
135
+ ? "catalog_sku_authority_sku_absent"
136
+ : "catalog_sku_authority_product_absent",
137
+ );
138
+ requirePostgresCatalogSkuEnvelopeRow(
139
+ row,
140
+ parsed.kind === "primary_product_slug"
141
+ ? "catalog_sku_authority_primary_sku_invalid"
142
+ : "catalog_sku_authority_current_document_invalid",
143
+ );
144
+ if (
145
+ parsed.kind === "primary_product_slug"
146
+ && (row.primary_sku_id !== row.sku_id || row.product_id !== row.sku_product_id)
147
+ ) {
148
+ throw new CatalogSkuAuthorityError("catalog_sku_authority_primary_sku_invalid");
149
+ }
150
+ const identifiers = await readPostgresCatalogSkuIdentifiers(executor, [row.sku_id]);
151
+ return mapPostgresCatalogSkuEnvelope(row, identifiers.get(row.sku_id) ?? []);
152
+ },
153
+
154
+ async getSkuEnvelopeById(skuId: string): Promise<NeutralSkuEnvelopeV1 | null> {
155
+ const row = uniqueDetailRow(
156
+ await readRows(executor, DETAIL_ENVELOPE_BY_ID_SQL, [skuId]),
157
+ "catalog_sku_authority_sku_absent",
158
+ );
159
+ requirePostgresCatalogSkuEnvelopeRow(row, "catalog_sku_authority_current_document_invalid");
160
+ const identifiers = await readPostgresCatalogSkuIdentifiers(executor, [row.sku_id]);
161
+ return mapPostgresCatalogSkuEnvelope(row, identifiers.get(row.sku_id) ?? []);
162
+ },
163
+ };
164
+ }
165
+
166
+ async function listEnvelopes(
167
+ executor: PgQueryExecutor,
168
+ query: CatalogSkuEnvelopeListQuery,
169
+ sql: string,
170
+ prefixValues: unknown[] = [],
171
+ suffixValues: unknown[] = [],
172
+ ): Promise<CatalogSkuEnvelopePage> {
173
+ const rows = await readRows(
174
+ executor,
175
+ sql,
176
+ [...prefixValues, query.cursor, checkedLimit(query.limit) + 1, ...suffixValues],
177
+ );
178
+ const pageRows = rows.slice(0, query.limit).map((row) => {
179
+ requirePostgresCatalogSkuEnvelopeRow(row, "catalog_sku_authority_current_document_invalid");
180
+ return row;
181
+ });
182
+ const identifiers = await readPostgresCatalogSkuIdentifiers(executor, pageRows.map((row) => row.sku_id));
183
+ return {
184
+ items: pageRows.map((row) => mapPostgresCatalogSkuEnvelope(row, identifiers.get(row.sku_id) ?? [])),
185
+ nextCursor: rows.length > query.limit ? pageRows[pageRows.length - 1]?.sku_id ?? null : null,
186
+ };
187
+ }
188
+
189
+ function uniqueDetailRow(
190
+ rows: readonly PostgresCatalogSkuEnvelopeRow[],
191
+ absent: CatalogSkuAuthorityError["code"],
192
+ ): PostgresCatalogSkuEnvelopeRow {
193
+ if (rows.length === 0) throw new CatalogSkuAuthorityError(absent);
194
+ if (rows.length !== 1) {
195
+ throw new CatalogSkuAuthorityError("catalog_sku_authority_selector_ambiguous");
196
+ }
197
+ return rows[0]!;
198
+ }
199
+
200
+ async function readRows(
201
+ executor: PgQueryExecutor,
202
+ sql: string,
203
+ values: unknown[],
204
+ ): Promise<PostgresCatalogSkuEnvelopeRow[]> {
205
+ const { rows } = await executor.query(sql, values);
206
+ return rows as unknown as PostgresCatalogSkuEnvelopeRow[];
207
+ }
208
+
209
+ function checkedLimit(limit: number): number {
210
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 500) {
211
+ throw new RangeError("catalog_sku_envelope_invalid_limit");
212
+ }
213
+ return limit;
214
+ }
@@ -0,0 +1,160 @@
1
+ import {
2
+ CATALOG_FOUNDATION_CONTRACT_VERSION,
3
+ CatalogSkuAuthorityError,
4
+ assertPrimaryUnitGtinAuthority,
5
+ neutralSkuEnvelopeV1Schema,
6
+ requireCurrentCatalogDocumentAuthority,
7
+ type CatalogSkuIdentifier,
8
+ type NeutralSkuEnvelopeV1,
9
+ } from "./foundationSchemas.js";
10
+ import type { PgQueryExecutor } from "../data/index.js";
11
+
12
+ const IDENTIFIERS_SQL = `
13
+ SELECT catalog_sku_id, issuer, identifier_kind, normalized_value,
14
+ pack_kind, quantity, is_primary
15
+ FROM public.catalog_sku_identifiers
16
+ WHERE catalog_sku_id = ANY($1::uuid[])
17
+ ORDER BY catalog_sku_id, identifier_kind, is_primary DESC, issuer, normalized_value`;
18
+
19
+ export interface PostgresCatalogSkuEnvelopeRow {
20
+ product_id: string;
21
+ product_slug: string;
22
+ primary_sku_id: string | null;
23
+ current_document_revision_id: string | null;
24
+ sku_id: string | null;
25
+ sku_product_id: string | null;
26
+ sku_code: string | null;
27
+ net_content_unscaled: number | null;
28
+ sku_status: "draft" | "active" | "archived" | null;
29
+ sellable_one_time: boolean | null;
30
+ sellable_subscription: boolean | null;
31
+ is_addon: boolean | null;
32
+ asset_ref: string | null;
33
+ document_revision_id: string | null;
34
+ document_product_id: string | null;
35
+ document_revision_no: number | null;
36
+ document_schema_id: string | null;
37
+ document_ref: string | null;
38
+ document_source_ref: string | null;
39
+ document_digest: string | null;
40
+ }
41
+
42
+ interface IdentifierRow {
43
+ catalog_sku_id: string;
44
+ issuer: string;
45
+ identifier_kind: "gtin" | "other";
46
+ normalized_value: string;
47
+ pack_kind: "unit" | "collective";
48
+ quantity: number;
49
+ is_primary: boolean;
50
+ }
51
+
52
+ export type CompletePostgresCatalogSkuEnvelopeRow = PostgresCatalogSkuEnvelopeRow & {
53
+ primary_sku_id: string;
54
+ sku_id: string;
55
+ sku_product_id: string;
56
+ sku_code: string;
57
+ net_content_unscaled: number;
58
+ sku_status: "draft" | "active" | "archived";
59
+ sellable_one_time: boolean;
60
+ sellable_subscription: boolean;
61
+ is_addon: boolean;
62
+ };
63
+
64
+ export function requirePostgresCatalogSkuEnvelopeRow(
65
+ row: PostgresCatalogSkuEnvelopeRow,
66
+ refusal: CatalogSkuAuthorityError["code"],
67
+ ): asserts row is CompletePostgresCatalogSkuEnvelopeRow {
68
+ if (!row.primary_sku_id) {
69
+ throw new CatalogSkuAuthorityError("catalog_sku_authority_primary_sku_invalid");
70
+ }
71
+ if (
72
+ !row.sku_id
73
+ || !row.sku_product_id
74
+ || !row.sku_code
75
+ || row.net_content_unscaled === null
76
+ || row.sku_status === null
77
+ || row.sellable_one_time === null
78
+ || row.sellable_subscription === null
79
+ || row.is_addon === null
80
+ ) {
81
+ throw new CatalogSkuAuthorityError(refusal);
82
+ }
83
+ }
84
+
85
+ export async function readPostgresCatalogSkuIdentifiers(
86
+ executor: PgQueryExecutor,
87
+ skuIds: string[],
88
+ ): Promise<Map<string, CatalogSkuIdentifier[]>> {
89
+ if (skuIds.length === 0) return new Map();
90
+ const { rows } = await executor.query(IDENTIFIERS_SQL, [skuIds]);
91
+ const grouped = new Map<string, CatalogSkuIdentifier[]>();
92
+ for (const row of rows as unknown as IdentifierRow[]) {
93
+ const identifiers = grouped.get(row.catalog_sku_id) ?? [];
94
+ identifiers.push({
95
+ issuer: row.issuer,
96
+ normalizedValue: row.normalized_value,
97
+ kind: row.identifier_kind,
98
+ packKind: row.pack_kind,
99
+ packQuantity: row.quantity,
100
+ isPrimary: row.is_primary,
101
+ });
102
+ grouped.set(row.catalog_sku_id, identifiers);
103
+ }
104
+ return grouped;
105
+ }
106
+
107
+ export function mapPostgresCatalogSkuEnvelope(
108
+ row: CompletePostgresCatalogSkuEnvelopeRow,
109
+ identifiers: CatalogSkuIdentifier[],
110
+ ): NeutralSkuEnvelopeV1 {
111
+ assertPrimaryUnitGtinAuthority(identifiers);
112
+ const revision = requireCurrentCatalogDocumentAuthority(
113
+ row.product_id,
114
+ row.current_document_revision_id,
115
+ row.document_revision_id
116
+ && row.document_product_id
117
+ && row.document_revision_no !== null
118
+ && row.document_schema_id
119
+ && row.document_ref
120
+ && row.document_source_ref
121
+ && row.document_digest
122
+ ? {
123
+ id: row.document_revision_id,
124
+ productId: row.document_product_id,
125
+ revisionNo: row.document_revision_no,
126
+ schemaId: row.document_schema_id,
127
+ documentRef: row.document_ref,
128
+ sourceRef: row.document_source_ref,
129
+ digest: row.document_digest,
130
+ }
131
+ : null,
132
+ );
133
+ return neutralSkuEnvelopeV1Schema.parse({
134
+ contractVersion: CATALOG_FOUNDATION_CONTRACT_VERSION,
135
+ product: { id: row.product_id, slug: row.product_slug, primarySkuId: row.primary_sku_id },
136
+ sku: {
137
+ id: row.sku_id,
138
+ productId: row.sku_product_id,
139
+ code: row.sku_code,
140
+ netContent: { unscaled: row.net_content_unscaled, scale: 0, unit: "GRAM" },
141
+ sellability: {
142
+ status: row.sku_status,
143
+ oneTime: row.sellable_one_time,
144
+ subscription: row.sellable_subscription,
145
+ },
146
+ isAddon: row.is_addon,
147
+ assetRef: row.asset_ref,
148
+ },
149
+ documentRevision: {
150
+ id: revision.id,
151
+ productId: revision.productId,
152
+ revisionNo: revision.revisionNo,
153
+ schemaId: revision.schemaId,
154
+ documentRef: revision.documentRef,
155
+ sourceRef: revision.sourceRef,
156
+ digest: revision.digest,
157
+ },
158
+ identifiers,
159
+ });
160
+ }
@@ -0,0 +1,20 @@
1
+ /** Plain bundle transport DTOs. The host owns parsing, defaults and wire-version values. */
2
+ export type CreateBundleDraftRequest = { bundle: { code: string; title: string; fulfillmentMode: "virtual" | "kitted"; compositionConstraint?: { kind: string; version: number; data: Record<string, unknown>; } | undefined; metadata?: Record<string, unknown> | undefined; }; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
3
+ export type CreateBundleDraftResponse = { code: string; bundleId: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
4
+ export type UpdateBundleDraftRequest = { code: string; updates: { title?: string | undefined; fulfillmentMode?: "virtual" | "kitted" | undefined; compositionConstraint?: { kind: string; version: number; data: Record<string, unknown>; } | undefined; metadata?: Record<string, unknown> | undefined; }; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
5
+ export type UpdateBundleDraftResponse = { code: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
6
+ export type BundleComponent = { sku: string; quantity: number; isAddon: boolean; sortOrder: number; };
7
+ export type SetBundleCompositionRequest = { code: string; components: { sku: string; quantity: number; isAddon: boolean; sortOrder: number; }[]; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
8
+ export type SetBundleCompositionResponse = { code: string; componentCount: number; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
9
+ export type SetBundleTargetPriceRequest = { code: string; price: { mode: "any" | "one_time" | "subscription"; targetPriceMinor: number; currency: string; amountKind: "gross" | "net"; }; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
10
+ export type SetBundleTargetPriceResponse = { code: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
11
+ export type ArchiveBundleRequest = { code: string; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
12
+ export type ArchiveBundleResponse = { code: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
13
+ export type RestoreBundleRequest = { code: string; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
14
+ export type RestoreBundleResponse = { code: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
15
+ export type CloneBundleDraftRequest = { sourceCode: string; code: string; mode: "commit" | "dry_run"; title?: string | undefined; idempotencyKey?: string | undefined; };
16
+ export type CloneBundleDraftResponse = { code: string; bundleId: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
17
+ export type ActivateBundleRequest = { code: string; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
18
+ export type ActivateBundleResponse = { code: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
19
+ export type DeactivateBundleRequest = { code: string; mode: "commit" | "dry_run"; idempotencyKey?: string | undefined; };
20
+ export type DeactivateBundleResponse = { code: string; contractVersion: "commerce.v0"; dryRun: boolean; idempotent: boolean; };
@@ -0,0 +1,5 @@
1
+ /** Plain bundle transport DTOs. The host owns parsing, defaults and wire-version values. */
2
+ export type SellableBundle = { code: string; title: string; fulfillmentMode: string; price: { amountMinor: number; currency: string; }; components: { sku: string; quantity: number; effectiveUnitPriceMinor: number; lineSubtotalMinor: number; discountBps: number; }[]; availability: { status: "unknown" | "available" | "low_stock" | "out_of_stock"; sellableNow: number | null; limitingSku: string | null; reasonCode: string; }; };
3
+ export type SellableBundleComponent = { sku: string; quantity: number; effectiveUnitPriceMinor: number; lineSubtotalMinor: number; discountBps: number; };
4
+ export type SellableBundleAvailability = { status: "unknown" | "available" | "low_stock" | "out_of_stock"; sellableNow: number | null; limitingSku: string | null; reasonCode: string; };
5
+ export type SellableBundleListResponse = { contractVersion: "catalog.sellable-bundle.v1"; bundles: { code: string; title: string; fulfillmentMode: string; price: { amountMinor: number; currency: string; }; components: { sku: string; quantity: number; effectiveUnitPriceMinor: number; lineSubtotalMinor: number; discountBps: number; }[]; availability: { status: "unknown" | "available" | "low_stock" | "out_of_stock"; sellableNow: number | null; limitingSku: string | null; reasonCode: string; }; }[]; };
@@ -0,0 +1,13 @@
1
+ /** Plain bundle transport DTOs. The host owns parsing, defaults and wire-version values. */
2
+ export type ListBundlesRequest = { limit: number; offset: number; status: "draft" | "active" | "archived" | "all"; query?: string | undefined; };
3
+ export type ListBundlesResponse = { bundles: { code: string; title: string; status: string; fulfillmentMode: string; componentCount: number; hasActiveTargetPrice: boolean; updatedAt: string; }[]; total: number; contractVersion: "commerce.v0"; };
4
+ export type BundleSummaryView = { code: string; title: string; status: string; fulfillmentMode: string; componentCount: number; hasActiveTargetPrice: boolean; updatedAt: string; };
5
+ export type GetBundleRequest = { code: string; currency?: string | undefined; mode?: "any" | "one_time" | "subscription" | undefined; };
6
+ export type GetBundleResponse = { bundle: { code: string; title: string; status: string; fulfillmentMode: string; componentCount: number; hasActiveTargetPrice: boolean; updatedAt: string; compositionConstraint: { kind: string; version: number; data: Record<string, unknown>; } | null; metadata: Record<string, unknown>; components: { sku: string; title: string | null; productSlug: string; quantity: number; isAddon: boolean; sortOrder: number; referenceUnitPriceMinor: number | null; }[]; prices: { mode: string; targetPriceMinor: number; currency: string; amountKind: string; active: boolean; validFrom: string; validTo: string | null; }[]; resolvedTargetPrice?: { mode: string; targetPriceMinor: number; currency: string; amountKind: string; active: boolean; validFrom: string; validTo: string | null; } | null; resolvedCurrency: string | null; availability: { sellableNow: number | null; status: string; reasonCode: string; limitingSku: string | null; components: { sku: string; quantity: number; isAddon: boolean; sellableNow: number | null; }[]; } | null; }; contractVersion: "commerce.v0"; };
7
+ export type BundleDetailView = { code: string; title: string; status: string; fulfillmentMode: string; componentCount: number; hasActiveTargetPrice: boolean; updatedAt: string; compositionConstraint: { kind: string; version: number; data: Record<string, unknown>; } | null; metadata: Record<string, unknown>; components: { sku: string; title: string | null; productSlug: string; quantity: number; isAddon: boolean; sortOrder: number; referenceUnitPriceMinor: number | null; }[]; prices: { mode: string; targetPriceMinor: number; currency: string; amountKind: string; active: boolean; validFrom: string; validTo: string | null; }[]; resolvedTargetPrice?: { mode: string; targetPriceMinor: number; currency: string; amountKind: string; active: boolean; validFrom: string; validTo: string | null; } | null; resolvedCurrency: string | null; availability: { sellableNow: number | null; status: string; reasonCode: string; limitingSku: string | null; components: { sku: string; quantity: number; isAddon: boolean; sellableNow: number | null; }[]; } | null; };
8
+ export type BundleAvailabilityView = { sellableNow: number | null; status: string; reasonCode: string; limitingSku: string | null; components: { sku: string; quantity: number; isAddon: boolean; sellableNow: number | null; }[]; };
9
+ export type BundleHistoryRequest = { limit: number; offset: number; code: string; };
10
+ export type BundleHistoryResponse = { events: { id: string; action: string; actorKind: string | null; actorEmail: string | null; entityId: string | null; oldValue: unknown; newValue: unknown; occurredAt: string; }[]; total: number; contractVersion: "commerce.v0"; };
11
+ export type PreviewBundlePriceRequest = { code: string; currency?: string | undefined; mode?: "any" | "one_time" | "subscription" | undefined; targetPriceMinor?: number | undefined; };
12
+ export type PreviewBundlePriceResponse = { preview: { bundleCode: string; priceListId: string; mode: string; currency: string; referenceTotalMinor: number; targetPriceMinor: number; discountTotalMinor: number; discountBps: number; floorApplied: boolean; componentTargets: { sku: string; quantity: number; referenceUnitPriceMinor: number; referenceSubtotalMinor: number; targetSubtotalMinor: number; discountAllocatedMinor: number; discountBps: number; hasSplitPricing: boolean; }[]; allocatedLines: { sku: string; quantity: number; effectiveUnitPriceMinor: number; lineSubtotalMinor: number; }[]; }; contractVersion: "commerce.v0"; };
13
+ export type BundlePricePreview = { bundleCode: string; priceListId: string; mode: string; currency: string; referenceTotalMinor: number; targetPriceMinor: number; discountTotalMinor: number; discountBps: number; floorApplied: boolean; componentTargets: { sku: string; quantity: number; referenceUnitPriceMinor: number; referenceSubtotalMinor: number; targetSubtotalMinor: number; discountAllocatedMinor: number; discountBps: number; hasSplitPricing: boolean; }[]; allocatedLines: { sku: string; quantity: number; effectiveUnitPriceMinor: number; lineSubtotalMinor: number; }[]; };
@@ -0,0 +1,69 @@
1
+ import type { CatalogDocumentRevisionRef } from "./foundation.js";
2
+ import type { CatalogProductTypeRef, CatalogOptionValue, CatalogQuantity } from "./productTypes.js";
3
+ export const CATALOG_DRAFT_MAX_BYTES = 1_048_576;
4
+ export const CATALOG_DRAFT_MAX_PAGE = 100;
5
+ export interface CatalogDraftPayload {
6
+ schemaVersion: 1;
7
+ product: {
8
+ id: string; type: CatalogProductTypeRef; slug?: string; primarySkuId?: string;
9
+ dimensions: string[]; sharedContent?: unknown; documentRevision?: CatalogDocumentRevisionRef;
10
+ };
11
+ skus: {
12
+ id: string; productId: string; code?: string; options: Record<string, CatalogOptionValue>;
13
+ netContent?: CatalogQuantity;
14
+ identifiers?: { scheme: string; issuer: string; value: string; packagingLevel: "unit" | "case"; quantity?: number }[];
15
+ assetRefs?: string[]; grossMass?: CatalogQuantity; priceRef?: string; logisticsRef?: string;
16
+ }[];
17
+ }
18
+ export interface CatalogDraftCommand {
19
+ schemaVersion: 1; action: "create" | "revise" | "abandon";
20
+ draftId: string; commandKey: string; expectedRevision: number; payload?: CatalogDraftPayload;
21
+ }
22
+ export interface CatalogDraftSummary {
23
+ draftId: string; productId: string; revision: number; status: "open" | "abandoned";
24
+ commandKey: string; fingerprint: string; actorId: string; createdAt: string;
25
+ }
26
+ export interface CatalogDraftRecord extends CatalogDraftSummary { payload: CatalogDraftPayload }
27
+ export interface CatalogDraftPage { items: CatalogDraftSummary[]; nextCursor: string | null }
28
+ export interface CatalogDraftRefusal {
29
+ outcome: "conflict" | "validation_issue" | "unauthorized" | "dependency_unavailable";
30
+ reason: string; currentRevision?: number;
31
+ }
32
+ export type CatalogDraftApplyResult = { outcome: "committed" | "replayed"; record: CatalogDraftRecord } | CatalogDraftRefusal;
33
+ export interface CatalogDraftGetQuery { draftId: string; revision?: number; commandKey?: string }
34
+ export interface CatalogDraftListQuery { afterDraftId?: string; limit: number }
35
+
36
+ /** Reject lossy JSON inputs, prototype keys and excessive recursion before validation or hashing. */
37
+ export function canonicalCatalogDraftJson(input: unknown): string {
38
+ const ancestors = new Set<object>();
39
+ function visit(value: unknown, depth: number): unknown {
40
+ if (depth > 48) throw new Error("draft_json_depth");
41
+ if (typeof value === "string") {
42
+ if (value.includes("\u0000") || /[\uD800-\uDFFF]/u.test(value)) throw new Error("draft_json_invalid");
43
+ return value;
44
+ }
45
+ if (value === null || typeof value === "boolean") return value;
46
+ if (typeof value === "number" && Number.isFinite(value) && !Object.is(value, -0)) return value;
47
+ if (typeof value !== "object" || ancestors.has(value)) throw new Error("draft_json_invalid");
48
+ if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new Error("draft_json_invalid");
49
+ ancestors.add(value);
50
+ const keys = Reflect.ownKeys(value);
51
+ if (keys.some((key) => typeof key !== "string" || ["__proto__", "constructor", "prototype"].includes(key))) throw new Error("draft_json_invalid");
52
+ for (const key of keys) {
53
+ visit(key, depth + 1);
54
+ if (Object.getOwnPropertyDescriptor(value, key)?.get || Object.getOwnPropertyDescriptor(value, key)?.set) throw new Error("draft_json_invalid");
55
+ }
56
+ let result: unknown;
57
+ if (Array.isArray(value)) {
58
+ if (keys.length !== value.length + 1) throw new Error("draft_json_invalid");
59
+ result = Array.from(value, (item) => visit(item, depth + 1));
60
+ } else {
61
+ result = Object.fromEntries((keys as string[]).sort().map((key) => [key, visit((value as Record<string, unknown>)[key], depth + 1)]));
62
+ }
63
+ ancestors.delete(value);
64
+ return result;
65
+ }
66
+ const text = JSON.stringify(visit(input, 0));
67
+ if (new TextEncoder().encode(text).byteLength > CATALOG_DRAFT_MAX_BYTES) throw new Error("draft_payload_too_large");
68
+ return text;
69
+ }
@@ -0,0 +1,104 @@
1
+ /** Portable, payload-free catalog references and identifier authority. */
2
+ export const CATALOG_FOUNDATION_CONTRACT_VERSION = "catalog.foundation.v1";
3
+ export interface CatalogDocumentRevisionRef {
4
+ id: string; productId: string; revisionNo: number; schemaId: string;
5
+ documentRef: string; sourceRef: string; digest: string;
6
+ }
7
+ export interface CatalogSkuIdentifier {
8
+ issuer: string; normalizedValue: string; kind: "gtin" | "other";
9
+ packKind: "unit" | "collective"; packQuantity: number; isPrimary: boolean;
10
+ }
11
+ export type CatalogSkuEnvelopeSelector =
12
+ | { kind: "sku_code"; skuCode: string }
13
+ | { kind: "primary_product_slug"; productSlug: string };
14
+ export interface NeutralSkuEnvelopeV1 {
15
+ contractVersion: typeof CATALOG_FOUNDATION_CONTRACT_VERSION;
16
+ product: { id: string; slug: string; primarySkuId: string };
17
+ sku: {
18
+ id: string; productId: string; code: string;
19
+ netContent: { unscaled: number; scale: number; unit: string };
20
+ sellability: { status: "draft" | "active" | "archived"; oneTime: boolean; subscription: boolean };
21
+ isAddon: boolean; assetRef: string | null;
22
+ };
23
+ documentRevision: CatalogDocumentRevisionRef; identifiers: CatalogSkuIdentifier[];
24
+ }
25
+ export interface CatalogPriceContext {
26
+ priceListId: string; regionCode: string; currency: string; channel: string; atTime: string;
27
+ }
28
+
29
+ /** Refusal vocabulary shared by managed and portable catalog readers. */
30
+ export type CatalogSkuAuthorityRefusal =
31
+ | "catalog_sku_authority_sku_absent"
32
+ | "catalog_sku_authority_product_absent"
33
+ | "catalog_sku_authority_primary_sku_invalid"
34
+ | "catalog_sku_authority_selector_ambiguous"
35
+ | "catalog_sku_authority_current_document_absent"
36
+ | "catalog_sku_authority_current_document_invalid"
37
+ | "catalog_sku_identifier_authority_absent"
38
+ | "catalog_sku_identifier_authority_ambiguous"
39
+ | "catalog_sku_identifier_authority_invalid";
40
+
41
+ export class CatalogSkuAuthorityError extends Error {
42
+ constructor(readonly code: CatalogSkuAuthorityRefusal) {
43
+ super(code);
44
+ this.name = "CatalogSkuAuthorityError";
45
+ }
46
+ }
47
+
48
+ /** Accepts only GS1 GTIN-8/12/13/14 values with a valid modulo-10 check digit. */
49
+ export function isValidGtin(value: string): boolean {
50
+ if (!/^\d{8}$|^\d{12}$|^\d{13}$|^\d{14}$/u.test(value)) return false;
51
+ const digits = [...value].map(Number);
52
+ const checkDigit = digits.pop();
53
+ if (checkDigit === undefined) return false;
54
+ const weighted = digits.reverse().reduce(
55
+ (sum, digit, index) => sum + digit * (index % 2 === 0 ? 3 : 1),
56
+ 0,
57
+ );
58
+ return (weighted + checkDigit) % 10 === 0;
59
+ }
60
+
61
+ /**
62
+ * Makes a read adapter fail closed when source rows cannot state one valid,
63
+ * primary unit GTIN. The neutral envelope itself remains payload and DB agnostic.
64
+ */
65
+ export function assertPrimaryUnitGtinAuthority(
66
+ identifiers: readonly CatalogSkuIdentifier[],
67
+ ): void {
68
+ const primary = identifiers.filter((identifier) => identifier.isPrimary);
69
+ if (primary.length === 0) {
70
+ throw new CatalogSkuAuthorityError("catalog_sku_identifier_authority_absent");
71
+ }
72
+ if (primary.length !== 1) {
73
+ throw new CatalogSkuAuthorityError("catalog_sku_identifier_authority_ambiguous");
74
+ }
75
+ const [identifier] = primary;
76
+ if (
77
+ identifier.kind !== "gtin"
78
+ || identifier.packKind !== "unit"
79
+ || identifier.packQuantity !== 1
80
+ || !isValidGtin(identifier.normalizedValue)
81
+ ) {
82
+ throw new CatalogSkuAuthorityError("catalog_sku_identifier_authority_invalid");
83
+ }
84
+ }
85
+
86
+ /** Returns the product-scoped revision only when the declared current authority is sound. */
87
+ export function requireCurrentCatalogDocumentAuthority<T extends { id: string; productId: string }>(
88
+ productId: string,
89
+ currentDocumentRevisionId: string | null,
90
+ revision: T | null | undefined,
91
+ ): T {
92
+ if (currentDocumentRevisionId === null) {
93
+ throw new CatalogSkuAuthorityError("catalog_sku_authority_current_document_absent");
94
+ }
95
+ if (
96
+ !revision
97
+ || revision.id !== currentDocumentRevisionId
98
+ || revision.productId !== productId
99
+ ) {
100
+ throw new CatalogSkuAuthorityError("catalog_sku_authority_current_document_invalid");
101
+ }
102
+ return revision;
103
+ }
104
+
@@ -0,0 +1,14 @@
1
+ export { CATALOG_DRAFT_MAX_BYTES, CATALOG_DRAFT_MAX_PAGE, canonicalCatalogDraftJson } from "./draft.js";
2
+ export type { CatalogDraftPayload, CatalogDraftCommand, CatalogDraftSummary, CatalogDraftRecord, CatalogDraftPage, CatalogDraftRefusal, CatalogDraftApplyResult, CatalogDraftGetQuery, CatalogDraftListQuery } from "./draft.js";
3
+ export { CATALOG_FOUNDATION_CONTRACT_VERSION, CatalogSkuAuthorityError, isValidGtin, assertPrimaryUnitGtinAuthority, requireCurrentCatalogDocumentAuthority } from "./foundation.js";
4
+ export type { CatalogDocumentRevisionRef, CatalogSkuIdentifier, CatalogSkuEnvelopeSelector, NeutralSkuEnvelopeV1, CatalogPriceContext, CatalogSkuAuthorityRefusal } from "./foundation.js";
5
+ export { validateCatalogQuantity, canonicalCatalogOption } from "./productTypes.js";
6
+ export type { CatalogQuantityDimension, CatalogQuantity, CatalogOptionValue, CatalogDraftIssue, CatalogProductTypeRef, CatalogProductTypeDefinition, CatalogProductTypeRegistry } from "./productTypes.js";
7
+ export { SELLABLE_CATALOG_CONTRACT_VERSION } from "./sellable.js";
8
+ export type { SellableCatalogItem, SellableCatalogProfile, SellableCatalogListResponse } from "./sellable.js";
9
+ export * from "./productMediaContracts.js";
10
+ export { resolveProductMedia } from "./resolveProductMedia.js";
11
+ export type { CatalogVariantState, CatalogHeadRef, CatalogLifecycleObservation, CatalogPublishCommand, CatalogPublicationReceipt, CatalogPublicationRefusal, CatalogPublicationReadResult, CatalogPublicationReceiptResult, CatalogHistoryResult } from "./lifecycle.js";
12
+ export type { CreateBundleDraftRequest, CreateBundleDraftResponse, UpdateBundleDraftRequest, UpdateBundleDraftResponse, BundleComponent, SetBundleCompositionRequest, SetBundleCompositionResponse, SetBundleTargetPriceRequest, SetBundleTargetPriceResponse, ArchiveBundleRequest, ArchiveBundleResponse, RestoreBundleRequest, RestoreBundleResponse, CloneBundleDraftRequest, CloneBundleDraftResponse, ActivateBundleRequest, ActivateBundleResponse, DeactivateBundleRequest, DeactivateBundleResponse } from "./bundleAdmin.js";
13
+ export type { ListBundlesRequest, ListBundlesResponse, BundleSummaryView, GetBundleRequest, GetBundleResponse, BundleDetailView, BundleAvailabilityView, BundleHistoryRequest, BundleHistoryResponse, PreviewBundlePriceRequest, PreviewBundlePriceResponse, BundlePricePreview } from "./bundleRead.js";
14
+ export type { SellableBundle, SellableBundleComponent, SellableBundleAvailability, SellableBundleListResponse } from "./bundleAvailability.js";