@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.
- package/CHANGELOG.md +143 -0
- package/README.md +299 -6
- package/dist/catalog/activeSkuSelection.d.ts +2 -0
- package/dist/catalog/activeSkuSelection.js +20 -0
- package/dist/catalog/adminBindings.d.ts +72 -0
- package/dist/catalog/adminBindings.js +1 -0
- package/dist/catalog/adminBundleHandler.d.ts +26 -0
- package/dist/catalog/adminBundleHandler.js +111 -0
- package/dist/catalog/adminBundleReadHandler.d.ts +21 -0
- package/dist/catalog/adminBundleReadHandler.js +185 -0
- package/dist/catalog/adminBundleWritePort.d.ts +85 -0
- package/dist/catalog/adminBundleWritePort.js +1 -0
- package/dist/catalog/bundleAvailability.d.ts +63 -0
- package/dist/catalog/bundleAvailability.js +78 -0
- package/dist/catalog/bundleAvailabilityService.d.ts +65 -0
- package/dist/catalog/bundleAvailabilityService.js +89 -0
- package/dist/catalog/bundleBindings.d.ts +33 -0
- package/dist/catalog/bundleBindings.js +1 -0
- package/dist/catalog/bundleCatalogQueries.d.ts +28 -0
- package/dist/catalog/bundleCatalogQueries.js +84 -0
- package/dist/catalog/bundleCatalogReadPort.d.ts +173 -0
- package/dist/catalog/bundleCatalogReadPort.js +36 -0
- package/dist/catalog/bundleCatalogStore.d.ts +5 -0
- package/dist/catalog/bundleCatalogStore.js +156 -0
- package/dist/catalog/bundlePriceSelection.d.ts +13 -0
- package/dist/catalog/bundlePriceSelection.js +26 -0
- package/dist/catalog/bundleRuleCodes.d.ts +41 -0
- package/dist/catalog/bundleRuleCodes.js +110 -0
- package/dist/catalog/bundleRules.d.ts +69 -0
- package/dist/catalog/bundleRules.js +102 -0
- package/dist/catalog/catalogDraftStore.d.ts +4 -0
- package/dist/catalog/catalogDraftStore.js +63 -0
- package/dist/catalog/catalogSkuEnvelope.d.ts +7 -0
- package/dist/catalog/catalogSkuEnvelope.js +142 -0
- package/dist/catalog/catalogSkuEnvelopeMapper.d.ts +38 -0
- package/dist/catalog/catalogSkuEnvelopeMapper.js +88 -0
- package/dist/catalog/contracts/bundleAdmin.d.ts +143 -0
- package/dist/catalog/contracts/bundleAdmin.js +1 -0
- package/dist/catalog/contracts/bundleAvailability.d.ts +61 -0
- package/dist/catalog/contracts/bundleAvailability.js +1 -0
- package/dist/catalog/contracts/bundleRead.d.ts +241 -0
- package/dist/catalog/contracts/bundleRead.js +1 -0
- package/dist/catalog/contracts/draft.d.ts +79 -0
- package/dist/catalog/contracts/draft.js +47 -0
- package/dist/catalog/contracts/foundation.d.ts +78 -0
- package/dist/catalog/contracts/foundation.js +53 -0
- package/dist/catalog/contracts/index.d.ts +14 -0
- package/dist/catalog/contracts/index.js +6 -0
- package/dist/catalog/contracts/lifecycle.d.ts +77 -0
- package/dist/catalog/contracts/lifecycle.js +1 -0
- package/dist/catalog/contracts/productMediaContracts.d.ts +77 -0
- package/dist/catalog/contracts/productMediaContracts.js +149 -0
- package/dist/catalog/contracts/productTypes.d.ts +54 -0
- package/dist/catalog/contracts/productTypes.js +16 -0
- package/dist/catalog/contracts/resolveProductMedia.d.ts +3 -0
- package/dist/catalog/contracts/resolveProductMedia.js +78 -0
- package/dist/catalog/contracts/sellable.d.ts +23 -0
- package/dist/catalog/contracts/sellable.js +1 -0
- package/dist/catalog/draftHandler.d.ts +25 -0
- package/dist/catalog/draftHandler.js +118 -0
- package/dist/catalog/draftPorts.d.ts +18 -0
- package/dist/catalog/draftPorts.js +8 -0
- package/dist/catalog/draftSchemas.d.ts +423 -0
- package/dist/catalog/draftSchemas.js +89 -0
- package/dist/catalog/draftValidation.d.ts +21 -0
- package/dist/catalog/draftValidation.js +125 -0
- package/dist/catalog/effectiveBundleCatalogQueries.d.ts +8 -0
- package/dist/catalog/effectiveBundleCatalogQueries.js +79 -0
- package/dist/catalog/effectiveBundleCatalogStore.d.ts +4 -0
- package/dist/catalog/effectiveBundleCatalogStore.js +156 -0
- package/dist/catalog/foundationSchemas.d.ts +98 -0
- package/dist/catalog/foundationSchemas.js +110 -0
- package/dist/catalog/index.d.ts +44 -0
- package/dist/catalog/index.js +26 -0
- package/dist/catalog/mediaSourcePack.d.ts +51 -0
- package/dist/catalog/mediaSourcePack.js +247 -0
- package/dist/catalog/productTypeSchemas.d.ts +46 -0
- package/dist/catalog/productTypeSchemas.js +72 -0
- package/dist/catalog/publicationPorts.d.ts +42 -0
- package/dist/catalog/publicationPorts.js +1 -0
- package/dist/catalog/readPorts.d.ts +51 -0
- package/dist/catalog/readPorts.js +1 -0
- package/dist/catalog/referenceCatalogHandler.d.ts +7 -0
- package/dist/catalog/referenceCatalogHandler.js +27 -0
- package/dist/catalog/resolvedSkuProjection.d.ts +88 -0
- package/dist/catalog/resolvedSkuProjection.js +60 -0
- package/dist/catalog/sellableBundleHandler.d.ts +46 -0
- package/dist/catalog/sellableBundleHandler.js +84 -0
- package/dist/catalog/sellableSchemas.d.ts +46 -0
- package/dist/catalog/sellableSchemas.js +27 -0
- package/dist/catalog/sql.d.ts +46 -0
- package/dist/catalog/sql.js +13 -0
- package/dist/catalog/validation.d.ts +2 -0
- package/dist/catalog/validation.js +3 -0
- package/dist/communications/contracts/index.d.ts +1 -0
- package/dist/communications/contracts/marketingSync.d.ts +194 -0
- package/dist/communications/contracts/marketingSync.js +1 -0
- package/dist/communications/index.d.ts +1 -0
- package/dist/communications/klaviyo/consentPush.d.ts +51 -0
- package/dist/communications/klaviyo/consentPush.js +19 -0
- package/dist/communications/klaviyo/index.d.ts +110 -0
- package/dist/communications/klaviyo/index.js +860 -0
- package/dist/communications/newsletterIntegrationContracts.d.ts +3 -3
- package/dist/communications/resend/index.d.ts +40 -0
- package/dist/communications/resend/index.js +310 -0
- package/dist/composition/catalogContribution.d.ts +18 -0
- package/dist/composition/catalogContribution.js +21 -0
- package/dist/composition/index.d.ts +3 -0
- package/dist/composition/index.js +3 -0
- package/dist/composition/inventoryContribution.d.ts +16 -0
- package/dist/composition/inventoryContribution.js +17 -0
- package/dist/composition/shippingContribution.d.ts +16 -0
- package/dist/composition/shippingContribution.js +17 -0
- package/dist/identity/customerContracts.d.ts +2 -2
- package/dist/inventory/adminInventory.d.ts +13 -0
- package/dist/inventory/adminInventory.js +214 -0
- package/dist/inventory/bindings.d.ts +35 -0
- package/dist/inventory/bindings.js +45 -0
- package/dist/inventory/contracts/forecast.d.ts +86 -0
- package/dist/inventory/contracts/forecast.js +1 -0
- package/dist/inventory/contracts/index.d.ts +4 -0
- package/dist/inventory/contracts/index.js +1 -0
- package/dist/inventory/contracts/inventory.d.ts +157 -0
- package/dist/inventory/contracts/inventory.js +1 -0
- package/dist/inventory/contracts/newPurchaseStock.d.ts +20 -0
- package/dist/inventory/contracts/newPurchaseStock.js +1 -0
- package/dist/inventory/contracts/reservation.d.ts +18 -0
- package/dist/inventory/contracts/reservation.js +1 -0
- package/dist/inventory/forecast.d.ts +24 -0
- package/dist/inventory/forecast.js +200 -0
- package/dist/inventory/index.d.ts +14 -0
- package/dist/inventory/index.js +11 -0
- package/dist/inventory/inventoryHandlers.d.ts +53 -0
- package/dist/inventory/inventoryHandlers.js +151 -0
- package/dist/inventory/newPurchaseStockAvailability.d.ts +47 -0
- package/dist/inventory/newPurchaseStockAvailability.js +75 -0
- package/dist/inventory/ports.d.ts +21 -0
- package/dist/inventory/ports.js +16 -0
- package/dist/inventory/renewalReservation.d.ts +27 -0
- package/dist/inventory/renewalReservation.js +61 -0
- package/dist/inventory/reservationPolicy.d.ts +6 -0
- package/dist/inventory/reservationPolicy.js +19 -0
- package/dist/inventory/schemas.d.ts +137 -0
- package/dist/inventory/schemas.js +112 -0
- package/dist/inventory/sql.d.ts +14 -0
- package/dist/inventory/sql.js +5 -0
- package/dist/inventory/subscriptionForecastCalculation.d.ts +4 -0
- package/dist/inventory/subscriptionForecastCalculation.js +133 -0
- package/dist/pricing/acquisitionFinancialPolicy.d.ts +26 -0
- package/dist/pricing/acquisitionFinancialPolicy.js +1 -0
- package/dist/pricing/acquisitionOfferPricing.d.ts +27 -0
- package/dist/pricing/acquisitionOfferPricing.js +25 -0
- package/dist/pricing/acquisitionOfferPricingHandler.d.ts +20 -0
- package/dist/pricing/acquisitionOfferPricingHandler.js +105 -0
- package/dist/pricing/acquisitionOfferPricingSchemas.d.ts +31 -0
- package/dist/pricing/acquisitionOfferPricingSchemas.js +33 -0
- package/dist/pricing/acquisitionQuoteBinding.d.ts +12 -0
- package/dist/pricing/acquisitionQuoteBinding.js +12 -0
- package/dist/pricing/acquisitionReadiness.d.ts +31 -0
- package/dist/pricing/acquisitionReadiness.js +117 -0
- package/dist/pricing/acquisitionTerms.d.ts +19 -0
- package/dist/pricing/acquisitionTerms.js +126 -0
- package/dist/pricing/acquisitionTermsSchemas.d.ts +59 -0
- package/dist/pricing/acquisitionTermsSchemas.js +42 -0
- package/dist/pricing/catalogFactsProvenance.d.ts +33 -0
- package/dist/pricing/catalogFactsProvenance.js +64 -0
- package/dist/pricing/catalogFactsSchemas.d.ts +45 -0
- package/dist/pricing/catalogFactsSchemas.js +58 -0
- package/dist/pricing/commerceOfferPricing.d.ts +25 -0
- package/dist/pricing/commerceOfferPricing.js +139 -0
- package/dist/pricing/commerceOfferPricingCache.d.ts +10 -0
- package/dist/pricing/commerceOfferPricingCache.js +44 -0
- package/dist/pricing/commerceOfferPricingHandler.d.ts +21 -0
- package/dist/pricing/commerceOfferPricingHandler.js +78 -0
- package/dist/pricing/commercePriceAuthority.d.ts +28 -0
- package/dist/pricing/commercePriceAuthority.js +140 -0
- package/dist/pricing/commercePricingPolicyErrors.d.ts +40 -0
- package/dist/pricing/commercePricingPolicyErrors.js +67 -0
- package/dist/pricing/commerceQuoteBatchHandler.d.ts +37 -0
- package/dist/pricing/commerceQuoteBatchHandler.js +83 -0
- package/dist/pricing/commerceQuoteCatalogReadPort.d.ts +27 -0
- package/dist/pricing/commerceQuoteCatalogReadPort.js +8 -0
- package/dist/pricing/commerceQuoteHandler.d.ts +35 -0
- package/dist/pricing/commerceQuoteHandler.js +122 -0
- package/dist/pricing/commerceQuoteSnapshotExpect.d.ts +9 -0
- package/dist/pricing/commerceQuoteSnapshotExpect.js +22 -0
- package/dist/pricing/contracts/acquisitionTerms.d.ts +32 -0
- package/dist/pricing/contracts/acquisitionTerms.js +2 -0
- package/dist/pricing/contracts/authority.d.ts +27 -0
- package/dist/pricing/contracts/authority.js +1 -0
- package/dist/pricing/contracts/evidence.d.ts +33 -0
- package/dist/pricing/contracts/evidence.js +1 -0
- package/dist/pricing/contracts/index.d.ts +17 -0
- package/dist/pricing/contracts/index.js +7 -0
- package/dist/pricing/contracts/money.d.ts +27 -0
- package/dist/pricing/contracts/money.js +1 -0
- package/dist/pricing/contracts/offer.d.ts +52 -0
- package/dist/pricing/contracts/offer.js +4 -0
- package/dist/pricing/contracts/offerPolicy.d.ts +16 -0
- package/dist/pricing/contracts/offerPolicy.js +5 -0
- package/dist/pricing/contracts/policy.d.ts +22 -0
- package/dist/pricing/contracts/policy.js +3 -0
- package/dist/pricing/contracts/provenance.d.ts +24 -0
- package/dist/pricing/contracts/provenance.js +2 -0
- package/dist/pricing/contracts/quote.d.ts +94 -0
- package/dist/pricing/contracts/quote.js +1 -0
- package/dist/pricing/dbBackedCommerceQuoteHelpers.d.ts +78 -0
- package/dist/pricing/dbBackedCommerceQuoteHelpers.js +146 -0
- package/dist/pricing/dbBackedCommerceQuotePort.d.ts +74 -0
- package/dist/pricing/dbBackedCommerceQuotePort.js +223 -0
- package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.d.ts +4 -0
- package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.js +25 -0
- package/dist/pricing/index.d.ts +52 -0
- package/dist/pricing/index.js +36 -0
- package/dist/pricing/offerPolicyReadiness.d.ts +21 -0
- package/dist/pricing/offerPolicyReadiness.js +79 -0
- package/dist/pricing/offerPolicySchemas.d.ts +25 -0
- package/dist/pricing/offerPolicySchemas.js +15 -0
- package/dist/pricing/offerPricingSchemas.d.ts +315 -0
- package/dist/pricing/offerPricingSchemas.js +65 -0
- package/dist/pricing/ports.d.ts +13 -0
- package/dist/pricing/ports.js +9 -0
- package/dist/pricing/pricingPolicyToken.d.ts +39 -0
- package/dist/pricing/pricingPolicyToken.js +84 -0
- package/dist/pricing/quoteAcquisitionTerms.d.ts +2 -0
- package/dist/pricing/quoteAcquisitionTerms.js +4 -0
- package/dist/pricing/quoteCodeRejectionDetails.d.ts +20 -0
- package/dist/pricing/quoteCodeRejectionDetails.js +22 -0
- package/dist/pricing/quotePorts.d.ts +30 -0
- package/dist/pricing/quotePorts.js +20 -0
- package/dist/pricing/quotePrimitives.d.ts +13 -0
- package/dist/pricing/quotePrimitives.js +18 -0
- package/dist/pricing/quotePromotionEvidence.d.ts +39 -0
- package/dist/pricing/quotePromotionEvidence.js +73 -0
- package/dist/pricing/quoteSchemas.d.ts +1176 -0
- package/dist/pricing/quoteSchemas.js +196 -0
- package/dist/pricing/quoteShippingPromotions.d.ts +20 -0
- package/dist/pricing/quoteShippingPromotions.js +1 -0
- package/dist/pricing/subscriptionPricePolicy.d.ts +52 -0
- package/dist/pricing/subscriptionPricePolicy.js +96 -0
- package/dist/pricing/taxProfileGuard.d.ts +2 -0
- package/dist/pricing/taxProfileGuard.js +24 -0
- package/dist/pricing/validation.d.ts +2 -0
- package/dist/pricing/validation.js +3 -0
- package/dist/promotions/adminBindings.d.ts +72 -0
- package/dist/promotions/adminBindings.js +1 -0
- package/dist/promotions/adminPromotionCodesContracts.d.ts +498 -0
- package/dist/promotions/adminPromotionCodesContracts.js +211 -0
- package/dist/promotions/adminPromotionCodesDataPort.d.ts +47 -0
- package/dist/promotions/adminPromotionCodesDataPort.js +1 -0
- package/dist/promotions/adminPromotionCodesHandler.d.ts +14 -0
- package/dist/promotions/adminPromotionCodesHandler.js +194 -0
- package/dist/promotions/adminPromotionsContracts.d.ts +235 -0
- package/dist/promotions/adminPromotionsContracts.js +99 -0
- package/dist/promotions/adminPromotionsDataPort.d.ts +42 -0
- package/dist/promotions/adminPromotionsDataPort.js +1 -0
- package/dist/promotions/adminPromotionsHandler.d.ts +16 -0
- package/dist/promotions/adminPromotionsHandler.js +47 -0
- package/dist/promotions/commerceQuoteReadPreparation.d.ts +3 -0
- package/dist/promotions/commerceQuoteReadPreparation.js +27 -0
- package/dist/promotions/contracts/index.d.ts +387 -0
- package/dist/promotions/contracts/index.js +1 -0
- package/dist/promotions/index.d.ts +25 -0
- package/dist/promotions/index.js +22 -0
- package/dist/promotions/promoDataPort.d.ts +47 -0
- package/dist/promotions/promoDataPort.js +14 -0
- package/dist/promotions/promotionAcceptanceTelemetry.d.ts +29 -0
- package/dist/promotions/promotionAcceptanceTelemetry.js +45 -0
- package/dist/promotions/promotionBenefitDefinition.d.ts +37 -0
- package/dist/promotions/promotionBenefitDefinition.js +33 -0
- package/dist/promotions/promotionClaimSweepPort.d.ts +14 -0
- package/dist/promotions/promotionClaimSweepPort.js +8 -0
- package/dist/promotions/promotionClaims.d.ts +5 -0
- package/dist/promotions/promotionClaims.js +57 -0
- package/dist/promotions/promotionCodePreview.d.ts +11 -0
- package/dist/promotions/promotionCodePreview.js +154 -0
- package/dist/promotions/promotionCodeQuotePort.d.ts +25 -0
- package/dist/promotions/promotionCodeQuotePort.js +1 -0
- package/dist/promotions/promotionQuoteAcceptance.d.ts +70 -0
- package/dist/promotions/promotionQuoteAcceptance.js +202 -0
- package/dist/promotions/promotionQuoteBinding.d.ts +73 -0
- package/dist/promotions/promotionQuoteBinding.js +87 -0
- package/dist/promotions/quoteAcquisitionBinding.d.ts +6 -0
- package/dist/promotions/quoteAcquisitionBinding.js +1 -0
- package/dist/promotions/quoteAutomaticPromotions.d.ts +26 -0
- package/dist/promotions/quoteAutomaticPromotions.js +60 -0
- package/dist/promotions/quotePromoDiscounts.d.ts +36 -0
- package/dist/promotions/quotePromoDiscounts.js +146 -0
- package/dist/promotions/quotePromotionCodeAdjustments.d.ts +27 -0
- package/dist/promotions/quotePromotionCodeAdjustments.js +223 -0
- package/dist/promotions/quotePromotionV2.d.ts +30 -0
- package/dist/promotions/quotePromotionV2.js +186 -0
- package/dist/promotions/quoteShippingPolicy.d.ts +23 -0
- package/dist/promotions/quoteShippingPolicy.js +47 -0
- package/dist/promotions/sql.d.ts +14 -0
- package/dist/promotions/sql.js +5 -0
- package/dist/promotions/validation.d.ts +2 -0
- package/dist/promotions/validation.js +3 -0
- package/dist/shipping/addressCanonLookupHandler.d.ts +7 -0
- package/dist/shipping/addressCanonLookupHandler.js +105 -0
- package/dist/shipping/addressCanonical.d.ts +2 -0
- package/dist/shipping/addressCanonical.js +26 -0
- package/dist/shipping/addressPorts.d.ts +39 -0
- package/dist/shipping/addressPorts.js +1 -0
- package/dist/shipping/addressSchemas.d.ts +30 -0
- package/dist/shipping/addressSchemas.js +1 -0
- package/dist/shipping/adminShippingRateHandler.d.ts +4 -0
- package/dist/shipping/adminShippingRateHandler.js +64 -0
- package/dist/shipping/bindings.d.ts +57 -0
- package/dist/shipping/bindings.js +46 -0
- package/dist/shipping/contracts/address.d.ts +144 -0
- package/dist/shipping/contracts/address.js +1 -0
- package/dist/shipping/contracts/delivery.d.ts +110 -0
- package/dist/shipping/contracts/delivery.js +1 -0
- package/dist/shipping/contracts/index.d.ts +4 -0
- package/dist/shipping/contracts/index.js +1 -0
- package/dist/shipping/contracts/shippingRate.d.ts +11 -0
- package/dist/shipping/contracts/shippingRate.js +1 -0
- package/dist/shipping/contracts/threshold.d.ts +22 -0
- package/dist/shipping/contracts/threshold.js +1 -0
- package/dist/shipping/customerAddressesHandler.d.ts +5 -0
- package/dist/shipping/customerAddressesHandler.js +80 -0
- package/dist/shipping/customerSelfServiceAddressModels.d.ts +27 -0
- package/dist/shipping/customerSelfServiceAddressModels.js +101 -0
- package/dist/shipping/deliverySelectionHandler.d.ts +10 -0
- package/dist/shipping/deliverySelectionHandler.js +77 -0
- package/dist/shipping/deliverySelectionPort.d.ts +8 -0
- package/dist/shipping/deliverySelectionPort.js +1 -0
- package/dist/shipping/deliverySelectionSummary.d.ts +2 -0
- package/dist/shipping/deliverySelectionSummary.js +53 -0
- package/dist/shipping/handlerSchemas.d.ts +21 -0
- package/dist/shipping/handlerSchemas.js +1 -0
- package/dist/shipping/index.d.ts +20 -0
- package/dist/shipping/index.js +10 -0
- package/dist/shipping/pickupPointSearchPort.d.ts +4 -0
- package/dist/shipping/pickupPointSearchPort.js +1 -0
- package/dist/shipping/readDeliverySelectionEvidence.d.ts +2 -0
- package/dist/shipping/readDeliverySelectionEvidence.js +44 -0
- package/dist/shipping/shippingRatePorts.d.ts +52 -0
- package/dist/shipping/shippingRatePorts.js +1 -0
- package/dist/shipping/thresholdPolicy.d.ts +42 -0
- package/dist/shipping/thresholdPolicy.js +60 -0
- package/package.json +62 -2
- package/release-gates.json +263 -53
- package/sql/20260807140000_read_parity_catalog.sql +94 -0
- package/sql/20260810120000_storefront_catalog_attributes.sql +51 -0
- package/sql/20260812140000_sellable_bundle_catalog.sql +124 -0
- package/sql/20260812210000_bundle_operator_write_boundary.sql +567 -0
- package/sql/20260814000000_fulfillment_stock_evidence.sql +239 -0
- package/sql/20260815120000_automatic_subscription_renewal.sql +1083 -0
- package/sql/20260817180000_promotion_claim_lifecycle.sql +591 -0
- package/sql/20260817180100_promotion_claim_lifecycle_validation.sql +23 -0
- package/sql/20260827220000_catalog_document_revision_foundation.sql +226 -0
- package/sql/20260827220001_catalog_document_revision_foundation_validate.sql +10 -0
- package/sql/20260908100000_catalog_draft_foundation.sql +217 -0
- package/src/catalog/activeSkuSelection.ts +20 -0
- package/src/catalog/adminBindings.ts +59 -0
- package/src/catalog/adminBundleHandler.ts +165 -0
- package/src/catalog/adminBundleReadHandler.ts +263 -0
- package/src/catalog/adminBundleWritePort.ts +102 -0
- package/src/catalog/bundleAvailability.ts +129 -0
- package/src/catalog/bundleAvailabilityService.ts +171 -0
- package/src/catalog/bundleBindings.ts +29 -0
- package/src/catalog/bundleCatalogQueries.ts +98 -0
- package/src/catalog/bundleCatalogReadPort.ts +181 -0
- package/src/catalog/bundleCatalogStore.ts +274 -0
- package/src/catalog/bundlePriceSelection.ts +25 -0
- package/src/catalog/bundleRuleCodes.ts +134 -0
- package/src/catalog/bundleRules.ts +153 -0
- package/src/catalog/catalogDraftStore.ts +71 -0
- package/src/catalog/catalogSkuEnvelope.ts +214 -0
- package/src/catalog/catalogSkuEnvelopeMapper.ts +160 -0
- package/src/catalog/contracts/bundleAdmin.ts +20 -0
- package/src/catalog/contracts/bundleAvailability.ts +5 -0
- package/src/catalog/contracts/bundleRead.ts +13 -0
- package/src/catalog/contracts/draft.ts +69 -0
- package/src/catalog/contracts/foundation.ts +104 -0
- package/src/catalog/contracts/index.ts +14 -0
- package/src/catalog/contracts/lifecycle.ts +74 -0
- package/src/catalog/contracts/productMediaContracts.ts +170 -0
- package/src/catalog/contracts/productTypes.ts +35 -0
- package/src/catalog/contracts/resolveProductMedia.ts +85 -0
- package/src/catalog/contracts/sellable.ts +12 -0
- package/src/catalog/draftHandler.ts +105 -0
- package/src/catalog/draftPorts.ts +18 -0
- package/src/catalog/draftSchemas.ts +88 -0
- package/src/catalog/draftValidation.ts +100 -0
- package/src/catalog/effectiveBundleCatalogQueries.ts +80 -0
- package/src/catalog/effectiveBundleCatalogStore.ts +208 -0
- package/src/catalog/foundationSchemas.ts +123 -0
- package/src/catalog/index.ts +44 -0
- package/src/catalog/mediaSourcePack.ts +219 -0
- package/src/catalog/productTypeSchemas.ts +70 -0
- package/src/catalog/publicationPorts.ts +44 -0
- package/src/catalog/readPorts.ts +61 -0
- package/src/catalog/referenceCatalogHandler.ts +39 -0
- package/src/catalog/resolvedSkuProjection.ts +76 -0
- package/src/catalog/sellableBundleHandler.ts +133 -0
- package/src/catalog/sellableSchemas.ts +33 -0
- package/src/catalog/sql.ts +14 -0
- package/src/catalog/validation.ts +3 -0
- package/src/communications/contracts/index.ts +1 -0
- package/src/communications/contracts/marketingSync.ts +109 -0
- package/src/communications/index.ts +1 -0
- package/src/communications/klaviyo/consentPush.ts +19 -0
- package/src/communications/klaviyo/index.ts +649 -0
- package/src/communications/resend/index.ts +350 -0
- package/src/composition/catalogContribution.ts +32 -0
- package/src/composition/index.ts +3 -0
- package/src/composition/inventoryContribution.ts +24 -0
- package/src/composition/shippingContribution.ts +24 -0
- package/src/inventory/adminInventory.ts +251 -0
- package/src/inventory/bindings.ts +61 -0
- package/src/inventory/contracts/forecast.ts +96 -0
- package/src/inventory/contracts/index.ts +18 -0
- package/src/inventory/contracts/inventory.ts +14 -0
- package/src/inventory/contracts/newPurchaseStock.ts +23 -0
- package/src/inventory/contracts/reservation.ts +20 -0
- package/src/inventory/forecast.ts +239 -0
- package/src/inventory/index.ts +22 -0
- package/src/inventory/inventoryHandlers.ts +215 -0
- package/src/inventory/newPurchaseStockAvailability.ts +120 -0
- package/src/inventory/ports.ts +46 -0
- package/src/inventory/renewalReservation.ts +88 -0
- package/src/inventory/reservationPolicy.ts +27 -0
- package/src/inventory/schemas.ts +128 -0
- package/src/inventory/sql.ts +5 -0
- package/src/inventory/subscriptionForecastCalculation.ts +157 -0
- package/src/pricing/acquisitionFinancialPolicy.ts +26 -0
- package/src/pricing/acquisitionOfferPricing.ts +38 -0
- package/src/pricing/acquisitionOfferPricingHandler.ts +157 -0
- package/src/pricing/acquisitionOfferPricingSchemas.ts +35 -0
- package/src/pricing/acquisitionQuoteBinding.ts +12 -0
- package/src/pricing/acquisitionReadiness.ts +148 -0
- package/src/pricing/acquisitionTerms.ts +125 -0
- package/src/pricing/acquisitionTermsSchemas.ts +52 -0
- package/src/pricing/catalogFactsProvenance.ts +102 -0
- package/src/pricing/catalogFactsSchemas.ts +69 -0
- package/src/pricing/commerceOfferPricing.ts +224 -0
- package/src/pricing/commerceOfferPricingCache.ts +53 -0
- package/src/pricing/commerceOfferPricingHandler.ts +137 -0
- package/src/pricing/commercePriceAuthority.ts +169 -0
- package/src/pricing/commercePricingPolicyErrors.ts +88 -0
- package/src/pricing/commerceQuoteBatchHandler.ts +129 -0
- package/src/pricing/commerceQuoteCatalogReadPort.ts +42 -0
- package/src/pricing/commerceQuoteHandler.ts +199 -0
- package/src/pricing/commerceQuoteSnapshotExpect.ts +48 -0
- package/src/pricing/contracts/acquisitionTerms.ts +26 -0
- package/src/pricing/contracts/authority.ts +44 -0
- package/src/pricing/contracts/evidence.ts +25 -0
- package/src/pricing/contracts/index.ts +17 -0
- package/src/pricing/contracts/money.ts +32 -0
- package/src/pricing/contracts/offer.ts +42 -0
- package/src/pricing/contracts/offerPolicy.ts +17 -0
- package/src/pricing/contracts/policy.ts +26 -0
- package/src/pricing/contracts/provenance.ts +19 -0
- package/src/pricing/contracts/quote.ts +106 -0
- package/src/pricing/dbBackedCommerceQuoteHelpers.ts +256 -0
- package/src/pricing/dbBackedCommerceQuotePort.ts +280 -0
- package/src/pricing/dbBackedCommerceQuoteSnapshotVerifier.ts +49 -0
- package/src/pricing/index.ts +53 -0
- package/src/pricing/offerPolicyReadiness.ts +110 -0
- package/src/pricing/offerPolicySchemas.ts +23 -0
- package/src/pricing/offerPricingSchemas.ts +92 -0
- package/src/pricing/ports.ts +17 -0
- package/src/pricing/pricingPolicyToken.ts +119 -0
- package/src/pricing/quoteAcquisitionTerms.ts +10 -0
- package/src/pricing/quoteCodeRejectionDetails.ts +23 -0
- package/src/pricing/quotePorts.ts +58 -0
- package/src/pricing/quotePrimitives.ts +21 -0
- package/src/pricing/quotePromotionEvidence.ts +82 -0
- package/src/pricing/quoteSchemas.ts +230 -0
- package/src/pricing/quoteShippingPromotions.ts +21 -0
- package/src/pricing/subscriptionPricePolicy.ts +113 -0
- package/src/pricing/taxProfileGuard.ts +33 -0
- package/src/pricing/validation.ts +3 -0
- package/src/promotions/adminBindings.ts +53 -0
- package/src/promotions/adminPromotionCodesContracts.ts +244 -0
- package/src/promotions/adminPromotionCodesDataPort.ts +56 -0
- package/src/promotions/adminPromotionCodesHandler.ts +254 -0
- package/src/promotions/adminPromotionsContracts.ts +121 -0
- package/src/promotions/adminPromotionsDataPort.ts +48 -0
- package/src/promotions/adminPromotionsHandler.ts +72 -0
- package/src/promotions/commerceQuoteReadPreparation.ts +29 -0
- package/src/promotions/contracts/index.ts +387 -0
- package/src/promotions/index.ts +25 -0
- package/src/promotions/promoDataPort.ts +65 -0
- package/src/promotions/promotionAcceptanceTelemetry.ts +73 -0
- package/src/promotions/promotionBenefitDefinition.ts +48 -0
- package/src/promotions/promotionClaimSweepPort.ts +23 -0
- package/src/promotions/promotionClaims.ts +70 -0
- package/src/promotions/promotionCodePreview.ts +183 -0
- package/src/promotions/promotionCodeQuotePort.ts +35 -0
- package/src/promotions/promotionQuoteAcceptance.ts +291 -0
- package/src/promotions/promotionQuoteBinding.ts +163 -0
- package/src/promotions/quoteAcquisitionBinding.ts +7 -0
- package/src/promotions/quoteAutomaticPromotions.ts +84 -0
- package/src/promotions/quotePromoDiscounts.ts +194 -0
- package/src/promotions/quotePromotionCodeAdjustments.ts +277 -0
- package/src/promotions/quotePromotionV2.ts +239 -0
- package/src/promotions/quoteShippingPolicy.ts +61 -0
- package/src/promotions/sql.ts +5 -0
- package/src/promotions/validation.ts +3 -0
- package/src/shipping/addressCanonLookupHandler.ts +114 -0
- package/src/shipping/addressCanonical.ts +31 -0
- package/src/shipping/addressPorts.ts +48 -0
- package/src/shipping/addressSchemas.ts +28 -0
- package/src/shipping/adminShippingRateHandler.ts +72 -0
- package/src/shipping/bindings.ts +74 -0
- package/src/shipping/contracts/address.ts +71 -0
- package/src/shipping/contracts/delivery.ts +114 -0
- package/src/shipping/contracts/index.ts +19 -0
- package/src/shipping/contracts/shippingRate.ts +7 -0
- package/src/shipping/contracts/threshold.ts +22 -0
- package/src/shipping/customerAddressesHandler.ts +100 -0
- package/src/shipping/customerSelfServiceAddressModels.ts +124 -0
- package/src/shipping/deliverySelectionHandler.ts +94 -0
- package/src/shipping/deliverySelectionPort.ts +10 -0
- package/src/shipping/deliverySelectionSummary.ts +56 -0
- package/src/shipping/handlerSchemas.ts +19 -0
- package/src/shipping/index.ts +26 -0
- package/src/shipping/pickupPointSearchPort.ts +8 -0
- package/src/shipping/readDeliverySelectionEvidence.ts +51 -0
- package/src/shipping/shippingRatePorts.ts +36 -0
- package/src/shipping/thresholdPolicy.ts +65 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SellableCatalogItem, SellableCatalogProfile, CatalogSkuEnvelopeSelector, NeutralSkuEnvelopeV1 } from "./contracts/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal neutral catalog seam used by the local reference storefront. It is
|
|
4
|
+
* independent of richer application catalog read ports.
|
|
5
|
+
*/
|
|
6
|
+
export interface SellableCatalogPort {
|
|
7
|
+
getStorefrontProfile(): Promise<SellableCatalogProfile>;
|
|
8
|
+
listSellableItems(): Promise<SellableCatalogItem[]>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Dark W2a read seam. Its row-safe return value deliberately contains document
|
|
12
|
+
* references, never a document payload or a SKU-level document override.
|
|
13
|
+
*/
|
|
14
|
+
export interface CatalogSkuEnvelopeReadPort {
|
|
15
|
+
listSkuEnvelopes(query: CatalogSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage>;
|
|
16
|
+
/**
|
|
17
|
+
* Page only active trade items that are sellable in at least one commerce
|
|
18
|
+
* channel. This is intentionally distinct from the neutral inventory-style
|
|
19
|
+
* listing above: consumers such as compatibility must not discover dormant
|
|
20
|
+
* SKUs and then try to filter them with a second authority.
|
|
21
|
+
*/
|
|
22
|
+
listActiveSkuEnvelopes(query: CatalogActiveSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage>;
|
|
23
|
+
getSkuEnvelope(selector: CatalogSkuEnvelopeSelector): Promise<NeutralSkuEnvelopeV1 | null>;
|
|
24
|
+
/** Compatibility lookup for callers that already persist the neutral SKU UUID. */
|
|
25
|
+
getSkuEnvelopeById(skuId: string): Promise<NeutralSkuEnvelopeV1 | null>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Additive discovery capability. Existing commerce consumers remain typed to
|
|
29
|
+
* {@link CatalogSkuEnvelopeReadPort} and therefore cannot accidentally use it.
|
|
30
|
+
*/
|
|
31
|
+
export interface PublicCatalogSkuEnvelopeReadPort extends CatalogSkuEnvelopeReadPort {
|
|
32
|
+
/**
|
|
33
|
+
* Public discovery's active-only page. Unlike the commerce method above it
|
|
34
|
+
* intentionally includes temporarily unsellable active variants.
|
|
35
|
+
*/
|
|
36
|
+
listPublicActiveSkuEnvelopes(query: CatalogSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage>;
|
|
37
|
+
/** Active-only cursor page restricted to one already-authoritative product. */
|
|
38
|
+
listPublicActiveProductSkuEnvelopes(productId: string, query: CatalogSkuEnvelopeListQuery): Promise<CatalogSkuEnvelopePage>;
|
|
39
|
+
}
|
|
40
|
+
export interface CatalogSkuEnvelopeListQuery {
|
|
41
|
+
cursor: string | null;
|
|
42
|
+
limit: number;
|
|
43
|
+
}
|
|
44
|
+
export interface CatalogActiveSkuEnvelopeListQuery extends CatalogSkuEnvelopeListQuery {
|
|
45
|
+
/** Optional server-selected scope; supplied selections contain 1–100 unique SKU codes. */
|
|
46
|
+
skuCodes?: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
export interface CatalogSkuEnvelopePage {
|
|
49
|
+
items: NeutralSkuEnvelopeV1[];
|
|
50
|
+
nextCursor: string | null;
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HttpRequest, HttpResponse } from "../http/index.js";
|
|
2
|
+
import type { BffResponder } from "../bff/index.js";
|
|
3
|
+
import type { SellableCatalogPort } from "./readPorts.js";
|
|
4
|
+
export declare function createReferenceCatalogItemsHandler({ catalogPort, responder, }: {
|
|
5
|
+
catalogPort: SellableCatalogPort;
|
|
6
|
+
responder: BffResponder;
|
|
7
|
+
}): (req: HttpRequest, res: HttpResponse) => Promise<void>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SELLABLE_CATALOG_CONTRACT_VERSION, sellableCatalogListResponseSchema, } from "./sellableSchemas.js";
|
|
2
|
+
export function createReferenceCatalogItemsHandler({ catalogPort, responder, }) {
|
|
3
|
+
const { sendBffError, sendBffSuccess, sendMethodNotAllowed } = responder;
|
|
4
|
+
return async function handler(req, res) {
|
|
5
|
+
if (req.method !== "GET") {
|
|
6
|
+
sendMethodNotAllowed(res, ["GET"]);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
const response = sellableCatalogListResponseSchema.safeParse({
|
|
11
|
+
contractVersion: SELLABLE_CATALOG_CONTRACT_VERSION,
|
|
12
|
+
profile: await catalogPort.getStorefrontProfile(),
|
|
13
|
+
items: await catalogPort.listSellableItems(),
|
|
14
|
+
});
|
|
15
|
+
if (!response.success) {
|
|
16
|
+
sendBffError(res, "INVALID_RESPONSE", "Reference catalog returned invalid items");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
sendBffSuccess(res, response.data, { contractVersion: SELLABLE_CATALOG_CONTRACT_VERSION }, {
|
|
20
|
+
cacheControl: "no-store",
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
sendBffError(res, "UPSTREAM_UNAVAILABLE", "Reference catalog is unavailable");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from "./validation.js";
|
|
2
|
+
import { type NeutralSkuEnvelopeV1 } from "./foundationSchemas.js";
|
|
3
|
+
/**
|
|
4
|
+
* Server-only, read-safe projection. It intentionally composes opaque document
|
|
5
|
+
* references with resolved prices and never selects or exposes document payload.
|
|
6
|
+
*/
|
|
7
|
+
export declare const RESOLVED_SKU_PROJECTION_VERSION = "catalog.resolved-sku.v1";
|
|
8
|
+
export declare const resolvedSkuProjectionSchema: z.ZodObject<{
|
|
9
|
+
contractVersion: z.ZodLiteral<"catalog.resolved-sku.v1">;
|
|
10
|
+
envelope: z.ZodObject<{
|
|
11
|
+
contractVersion: z.ZodLiteral<"catalog.foundation.v1">;
|
|
12
|
+
product: z.ZodObject<{
|
|
13
|
+
id: z.ZodGUID;
|
|
14
|
+
slug: z.ZodString;
|
|
15
|
+
primarySkuId: z.ZodGUID;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
sku: z.ZodObject<{
|
|
18
|
+
id: z.ZodGUID;
|
|
19
|
+
productId: z.ZodGUID;
|
|
20
|
+
code: z.ZodString;
|
|
21
|
+
netContent: z.ZodObject<{
|
|
22
|
+
unscaled: z.ZodNumber;
|
|
23
|
+
scale: z.ZodNumber;
|
|
24
|
+
unit: z.ZodString;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
sellability: z.ZodObject<{
|
|
27
|
+
status: z.ZodEnum<{
|
|
28
|
+
draft: "draft";
|
|
29
|
+
active: "active";
|
|
30
|
+
archived: "archived";
|
|
31
|
+
}>;
|
|
32
|
+
oneTime: z.ZodBoolean;
|
|
33
|
+
subscription: z.ZodBoolean;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
isAddon: z.ZodBoolean;
|
|
36
|
+
assetRef: z.ZodNullable<z.ZodString>;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
documentRevision: z.ZodObject<{
|
|
39
|
+
id: z.ZodGUID;
|
|
40
|
+
productId: z.ZodGUID;
|
|
41
|
+
revisionNo: z.ZodNumber;
|
|
42
|
+
schemaId: z.ZodString;
|
|
43
|
+
documentRef: z.ZodString;
|
|
44
|
+
sourceRef: z.ZodString;
|
|
45
|
+
digest: z.ZodString;
|
|
46
|
+
}, z.core.$strict>;
|
|
47
|
+
identifiers: z.ZodArray<z.ZodObject<{
|
|
48
|
+
issuer: z.ZodString;
|
|
49
|
+
normalizedValue: z.ZodString;
|
|
50
|
+
kind: z.ZodEnum<{
|
|
51
|
+
gtin: "gtin";
|
|
52
|
+
other: "other";
|
|
53
|
+
}>;
|
|
54
|
+
packKind: z.ZodEnum<{
|
|
55
|
+
unit: "unit";
|
|
56
|
+
collective: "collective";
|
|
57
|
+
}>;
|
|
58
|
+
packQuantity: z.ZodNumber;
|
|
59
|
+
isPrimary: z.ZodBoolean;
|
|
60
|
+
}, z.core.$strict>>;
|
|
61
|
+
}, z.core.$strict>;
|
|
62
|
+
priceContext: z.ZodObject<{
|
|
63
|
+
priceListId: z.ZodGUID;
|
|
64
|
+
regionCode: z.ZodString;
|
|
65
|
+
currency: z.ZodString;
|
|
66
|
+
channel: z.ZodString;
|
|
67
|
+
atTime: z.ZodString;
|
|
68
|
+
}, z.core.$strict>;
|
|
69
|
+
pricing: z.ZodObject<{
|
|
70
|
+
base: z.ZodObject<{
|
|
71
|
+
priceEntryId: z.ZodGUID;
|
|
72
|
+
amountMinor: z.ZodNumber;
|
|
73
|
+
}, z.core.$strict>;
|
|
74
|
+
subscription: z.ZodNullable<z.ZodObject<{
|
|
75
|
+
policyRevisionId: z.ZodGUID;
|
|
76
|
+
policyDigest: z.ZodString;
|
|
77
|
+
amountMinor: z.ZodNumber;
|
|
78
|
+
}, z.core.$strict>>;
|
|
79
|
+
}, z.core.$strict>;
|
|
80
|
+
}, z.core.$strict>;
|
|
81
|
+
export type ResolvedSkuProjection = z.infer<typeof resolvedSkuProjectionSchema>;
|
|
82
|
+
/** Row-safe constructor boundary for adapters; it accepts no raw document row/payload. */
|
|
83
|
+
export interface ResolvedSkuProjectionInput {
|
|
84
|
+
envelope: NeutralSkuEnvelopeV1;
|
|
85
|
+
priceContext: ResolvedSkuProjection["priceContext"];
|
|
86
|
+
pricing: ResolvedSkuProjection["pricing"];
|
|
87
|
+
}
|
|
88
|
+
export declare function buildResolvedSkuProjection(input: ResolvedSkuProjectionInput): ResolvedSkuProjection;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "./validation.js";
|
|
2
|
+
import { CatalogSkuAuthorityError, assertPrimaryUnitGtinAuthority, neutralSkuEnvelopeV1Schema, } from "./foundationSchemas.js";
|
|
3
|
+
const uuidSchema = z.guid();
|
|
4
|
+
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
5
|
+
const currencySchema = z.string().regex(/^[A-Z]{3}$/u);
|
|
6
|
+
const moneyMinorSchema = z.number().int().nonnegative();
|
|
7
|
+
/**
|
|
8
|
+
* Server-only, read-safe projection. It intentionally composes opaque document
|
|
9
|
+
* references with resolved prices and never selects or exposes document payload.
|
|
10
|
+
*/
|
|
11
|
+
export const RESOLVED_SKU_PROJECTION_VERSION = "catalog.resolved-sku.v1";
|
|
12
|
+
export const resolvedSkuProjectionSchema = z.object({
|
|
13
|
+
contractVersion: z.literal(RESOLVED_SKU_PROJECTION_VERSION),
|
|
14
|
+
envelope: neutralSkuEnvelopeV1Schema,
|
|
15
|
+
priceContext: z.object({
|
|
16
|
+
priceListId: uuidSchema,
|
|
17
|
+
regionCode: z.string().regex(/^[A-Z]{2,3}$/u),
|
|
18
|
+
currency: currencySchema,
|
|
19
|
+
channel: z.string().trim().min(1).max(64),
|
|
20
|
+
atTime: z.string().datetime({ offset: true }),
|
|
21
|
+
}).strict(),
|
|
22
|
+
pricing: z.object({
|
|
23
|
+
base: z.object({
|
|
24
|
+
priceEntryId: uuidSchema,
|
|
25
|
+
amountMinor: moneyMinorSchema,
|
|
26
|
+
}).strict(),
|
|
27
|
+
subscription: z.object({
|
|
28
|
+
policyRevisionId: uuidSchema,
|
|
29
|
+
policyDigest: digestSchema,
|
|
30
|
+
amountMinor: moneyMinorSchema,
|
|
31
|
+
}).strict().nullable(),
|
|
32
|
+
}).strict(),
|
|
33
|
+
}).strict().superRefine((projection, context) => {
|
|
34
|
+
try {
|
|
35
|
+
assertPrimaryUnitGtinAuthority(projection.envelope.identifiers);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (!(error instanceof CatalogSkuAuthorityError))
|
|
39
|
+
throw error;
|
|
40
|
+
context.addIssue({
|
|
41
|
+
code: z.ZodIssueCode.custom,
|
|
42
|
+
path: ["envelope", "identifiers"],
|
|
43
|
+
message: error.code,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const subscriptionSellable = projection.envelope.sku.sellability.subscription;
|
|
47
|
+
if (subscriptionSellable && projection.pricing.subscription === null) {
|
|
48
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["pricing", "subscription"], message: "subscription-sellable SKUs require a subscription price" });
|
|
49
|
+
}
|
|
50
|
+
if (!subscriptionSellable && projection.pricing.subscription !== null) {
|
|
51
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ["pricing", "subscription"], message: "one-time-only SKUs must not carry a subscription price" });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
export function buildResolvedSkuProjection(input) {
|
|
55
|
+
assertPrimaryUnitGtinAuthority(input.envelope.identifiers);
|
|
56
|
+
return resolvedSkuProjectionSchema.parse({
|
|
57
|
+
contractVersion: RESOLVED_SKU_PROJECTION_VERSION,
|
|
58
|
+
...input,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { HttpRequest, HttpResponse } from "../http/index.js";
|
|
2
|
+
import type { BffResponder } from "../bff/index.js";
|
|
3
|
+
import type { BundleResponseSchema } from "./adminBindings.js";
|
|
4
|
+
import type { SellableBundle } from "./contracts/bundleAvailability.js";
|
|
5
|
+
import type { BundleAvailability } from "./bundleAvailability.js";
|
|
6
|
+
import type { ActiveBundleComposition } from "./bundleCatalogReadPort.js";
|
|
7
|
+
import type { BundleAvailabilityService } from "./bundleAvailabilityService.js";
|
|
8
|
+
/**
|
|
9
|
+
* The public sellable-bundle feed handler, shaped after the reference catalog
|
|
10
|
+
* handler: GET-only, one
|
|
11
|
+
* port call, validate the body before sending, and never serve an unvalidated
|
|
12
|
+
* shape.
|
|
13
|
+
*
|
|
14
|
+
* It composes rather than computes twice: the availability service already folds
|
|
15
|
+
* one batched stock answer into the live compositions, and the pricing kernel
|
|
16
|
+
* turns the stored target price into per-component money. This module only decides
|
|
17
|
+
* what a storefront is allowed to see.
|
|
18
|
+
*
|
|
19
|
+
* A bundle whose money cannot be derived is DROPPED from the feed, not published
|
|
20
|
+
* with a guessed figure. Three cases reach that door — an unpriced component, an
|
|
21
|
+
* empty composition, and a target price the kernel refuses — and all three mean
|
|
22
|
+
* the same thing to a storefront: this is not sellable today. Publishing it with a
|
|
23
|
+
* partial price would put a number on a shelf that no order line could reproduce.
|
|
24
|
+
*/
|
|
25
|
+
export interface SellableBundleHandlerDeps {
|
|
26
|
+
availabilityService: BundleAvailabilityService;
|
|
27
|
+
/** Narrow the feed to one currency; omitted means every currency an operator priced. */
|
|
28
|
+
currency?: string;
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function createSellableBundleHandlers({ responder, sellableBundleListResponseSchema, SELLABLE_BUNDLE_CONTRACT_VERSION }: {
|
|
32
|
+
responder: BffResponder;
|
|
33
|
+
sellableBundleListResponseSchema: BundleResponseSchema;
|
|
34
|
+
SELLABLE_BUNDLE_CONTRACT_VERSION: "catalog.sellable-bundle.v1";
|
|
35
|
+
}): {
|
|
36
|
+
createSellableBundleHandler: (deps: SellableBundleHandlerDeps) => (req: HttpRequest, res: HttpResponse) => Promise<void>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Derive the row a storefront sees, or `null` when the money cannot be stated.
|
|
40
|
+
*
|
|
41
|
+
* The allocator emits TWO lines for a quantity whose subtotal does not divide
|
|
42
|
+
* evenly, which is exactly why the feed carries lines rather than a unit price per
|
|
43
|
+
* component: `unitPrice x quantity === lineSubtotal` holds on every line, and the
|
|
44
|
+
* lines sum to the bundle's price with no remainder.
|
|
45
|
+
*/
|
|
46
|
+
export declare function toSellableBundle(composition: ActiveBundleComposition, availability: BundleAvailability): SellableBundle | null;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { allocateBundleTargetPrice } from "@openlup/core/pricing";
|
|
2
|
+
export function createSellableBundleHandlers({ responder, sellableBundleListResponseSchema, SELLABLE_BUNDLE_CONTRACT_VERSION }) {
|
|
3
|
+
const { sendBffError, sendBffSuccess, sendMethodNotAllowed } = responder;
|
|
4
|
+
function createSellableBundleHandler(deps) {
|
|
5
|
+
return async function handler(req, res) {
|
|
6
|
+
if (req.method !== "GET") {
|
|
7
|
+
sendMethodNotAllowed(res, ["GET"]);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (!deps.enabled) {
|
|
11
|
+
sendBffError(res, "UPSTREAM_UNAVAILABLE", "Bundle reads are disabled", {
|
|
12
|
+
details: { reason: "feature_flag_disabled", featureFlag: "COMMERCE_BUNDLE_READ_ENABLED" },
|
|
13
|
+
});
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const rows = await deps.availabilityService.describeActiveBundles(deps.currency ? { currency: deps.currency } : {});
|
|
18
|
+
const response = sellableBundleListResponseSchema.safeParse({
|
|
19
|
+
contractVersion: SELLABLE_BUNDLE_CONTRACT_VERSION,
|
|
20
|
+
bundles: rows
|
|
21
|
+
.map((row) => toSellableBundle(row.composition, row.availability))
|
|
22
|
+
.filter((bundle) => bundle !== null),
|
|
23
|
+
});
|
|
24
|
+
if (!response.success) {
|
|
25
|
+
sendBffError(res, "INVALID_RESPONSE", "Sellable bundle feed returned an invalid shape");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
sendBffSuccess(res, response.data, { contractVersion: SELLABLE_BUNDLE_CONTRACT_VERSION }, { cacheControl: "no-store" });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
sendBffError(res, "UPSTREAM_UNAVAILABLE", "Sellable bundles are unavailable");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return { createSellableBundleHandler };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Derive the row a storefront sees, or `null` when the money cannot be stated.
|
|
39
|
+
*
|
|
40
|
+
* The allocator emits TWO lines for a quantity whose subtotal does not divide
|
|
41
|
+
* evenly, which is exactly why the feed carries lines rather than a unit price per
|
|
42
|
+
* component: `unitPrice x quantity === lineSubtotal` holds on every line, and the
|
|
43
|
+
* lines sum to the bundle's price with no remainder.
|
|
44
|
+
*/
|
|
45
|
+
export function toSellableBundle(composition, availability) {
|
|
46
|
+
if (composition.components.length === 0)
|
|
47
|
+
return null;
|
|
48
|
+
if (composition.components.some((component) => component.referenceUnitPriceMinor === null)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const allocation = allocateBundleTargetPrice({
|
|
52
|
+
components: composition.components.map((component) => ({
|
|
53
|
+
sku: component.sku,
|
|
54
|
+
quantity: component.quantity,
|
|
55
|
+
unitPriceMinor: component.referenceUnitPriceMinor,
|
|
56
|
+
})),
|
|
57
|
+
targetPriceMinor: composition.targetPriceMinor,
|
|
58
|
+
});
|
|
59
|
+
if (!allocation.ok)
|
|
60
|
+
return null;
|
|
61
|
+
// Basis points come from the per-component allocation, so a component split
|
|
62
|
+
// across two lines reports the same discount on both halves rather than two
|
|
63
|
+
// rounded figures that disagree.
|
|
64
|
+
const discountBpsBySku = new Map(allocation.components.map((component) => [component.sku, component.discountBps]));
|
|
65
|
+
return {
|
|
66
|
+
code: composition.code,
|
|
67
|
+
title: composition.title,
|
|
68
|
+
fulfillmentMode: composition.fulfillmentMode,
|
|
69
|
+
price: { amountMinor: composition.targetPriceMinor, currency: composition.currency },
|
|
70
|
+
components: allocation.lines.map((line) => ({
|
|
71
|
+
sku: line.sku,
|
|
72
|
+
quantity: line.quantity,
|
|
73
|
+
effectiveUnitPriceMinor: line.effectiveUnitPriceMinor,
|
|
74
|
+
lineSubtotalMinor: line.lineSubtotalMinor,
|
|
75
|
+
discountBps: discountBpsBySku.get(line.sku) ?? 0,
|
|
76
|
+
})),
|
|
77
|
+
availability: {
|
|
78
|
+
status: availability.status,
|
|
79
|
+
sellableNow: availability.sellableNow,
|
|
80
|
+
limitingSku: availability.limitingSku,
|
|
81
|
+
reasonCode: availability.reasonCode,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "./validation.js";
|
|
2
|
+
export { SELLABLE_CATALOG_CONTRACT_VERSION } from "./contracts/sellable.js";
|
|
3
|
+
export type { SellableCatalogItem, SellableCatalogProfile, SellableCatalogListResponse } from "./contracts/sellable.js";
|
|
4
|
+
export declare const sellableCatalogItemSchema: z.ZodObject<{
|
|
5
|
+
sku: z.ZodString;
|
|
6
|
+
title: z.ZodString;
|
|
7
|
+
unitPrice: z.ZodObject<{
|
|
8
|
+
amountMinor: z.ZodNumber;
|
|
9
|
+
currency: z.ZodString;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
permittedPurchaseModes: z.ZodArray<z.ZodEnum<{
|
|
12
|
+
subscription: "subscription";
|
|
13
|
+
one_time: "one_time";
|
|
14
|
+
}>>;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
export declare const sellableCatalogProfileSchema: z.ZodObject<{
|
|
17
|
+
id: z.ZodString;
|
|
18
|
+
brand: z.ZodString;
|
|
19
|
+
country: z.ZodString;
|
|
20
|
+
currency: z.ZodString;
|
|
21
|
+
locale: z.ZodString;
|
|
22
|
+
timezone: z.ZodString;
|
|
23
|
+
}, z.core.$strict>;
|
|
24
|
+
export declare const sellableCatalogListResponseSchema: z.ZodObject<{
|
|
25
|
+
contractVersion: z.ZodLiteral<"catalog.sellable.v1">;
|
|
26
|
+
profile: z.ZodObject<{
|
|
27
|
+
id: z.ZodString;
|
|
28
|
+
brand: z.ZodString;
|
|
29
|
+
country: z.ZodString;
|
|
30
|
+
currency: z.ZodString;
|
|
31
|
+
locale: z.ZodString;
|
|
32
|
+
timezone: z.ZodString;
|
|
33
|
+
}, z.core.$strict>;
|
|
34
|
+
items: z.ZodArray<z.ZodObject<{
|
|
35
|
+
sku: z.ZodString;
|
|
36
|
+
title: z.ZodString;
|
|
37
|
+
unitPrice: z.ZodObject<{
|
|
38
|
+
amountMinor: z.ZodNumber;
|
|
39
|
+
currency: z.ZodString;
|
|
40
|
+
}, z.core.$strict>;
|
|
41
|
+
permittedPurchaseModes: z.ZodArray<z.ZodEnum<{
|
|
42
|
+
subscription: "subscription";
|
|
43
|
+
one_time: "one_time";
|
|
44
|
+
}>>;
|
|
45
|
+
}, z.core.$strict>>;
|
|
46
|
+
}, z.core.$strict>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "./validation.js";
|
|
2
|
+
import { SELLABLE_CATALOG_CONTRACT_VERSION } from "./contracts/sellable.js";
|
|
3
|
+
export { SELLABLE_CATALOG_CONTRACT_VERSION } from "./contracts/sellable.js";
|
|
4
|
+
/** Minimal neutral storefront wire schema. */
|
|
5
|
+
const sellableCatalogMoneySchema = z.object({
|
|
6
|
+
amountMinor: z.number().int().nonnegative(),
|
|
7
|
+
currency: z.string().regex(/^[A-Z]{3}$/),
|
|
8
|
+
}).strict();
|
|
9
|
+
export const sellableCatalogItemSchema = z.object({
|
|
10
|
+
sku: z.string().trim().min(1).max(128).regex(/^[a-zA-Z0-9._:-]+$/),
|
|
11
|
+
title: z.string().trim().min(1).max(160),
|
|
12
|
+
unitPrice: sellableCatalogMoneySchema,
|
|
13
|
+
permittedPurchaseModes: z.array(z.enum(["one_time", "subscription"])).min(1).max(2),
|
|
14
|
+
}).strict();
|
|
15
|
+
export const sellableCatalogProfileSchema = z.object({
|
|
16
|
+
id: z.string().trim().min(1).max(120),
|
|
17
|
+
brand: z.string().trim().min(1).max(160),
|
|
18
|
+
country: z.string().regex(/^[A-Z]{2}$/),
|
|
19
|
+
currency: z.string().regex(/^[A-Z]{3}$/),
|
|
20
|
+
locale: z.string().trim().min(2).max(35),
|
|
21
|
+
timezone: z.string().trim().min(1).max(80),
|
|
22
|
+
}).strict();
|
|
23
|
+
export const sellableCatalogListResponseSchema = z.object({
|
|
24
|
+
contractVersion: z.literal(SELLABLE_CATALOG_CONTRACT_VERSION),
|
|
25
|
+
profile: sellableCatalogProfileSchema,
|
|
26
|
+
items: z.array(sellableCatalogItemSchema).min(1),
|
|
27
|
+
}).strict();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Sparse projections of canonical units, never an install chain. */
|
|
2
|
+
export declare const BUNDLE_MIGRATIONS: readonly [{
|
|
3
|
+
readonly id: "20260812140000_sellable_bundle_catalog";
|
|
4
|
+
readonly catalogPath: "db/platform/migrations/20260812140000_sellable_bundle_catalog.sql";
|
|
5
|
+
readonly position: 16;
|
|
6
|
+
readonly sha256: "62fbf0910a3a7a2ee47e2d798933fe0a5a273fd1242cae7cc78ff237ba39e394";
|
|
7
|
+
readonly url: URL;
|
|
8
|
+
}, {
|
|
9
|
+
readonly id: "20260812210000_bundle_operator_write_boundary";
|
|
10
|
+
readonly catalogPath: "db/platform/migrations/20260812210000_bundle_operator_write_boundary.sql";
|
|
11
|
+
readonly position: 19;
|
|
12
|
+
readonly sha256: "d0ec6674d7eedf4cd3ce0d8ccd7345ebe2f93da635316a68a6bd178ec55b2679";
|
|
13
|
+
readonly url: URL;
|
|
14
|
+
}];
|
|
15
|
+
/** Catalog foundation projections; install the complete canonical catalogue. */
|
|
16
|
+
export declare const CATALOG_MIGRATIONS: readonly [{
|
|
17
|
+
readonly id: "20260807140000_read_parity_catalog";
|
|
18
|
+
readonly catalogPath: "db/platform/migrations/20260807140000_read_parity_catalog.sql";
|
|
19
|
+
readonly position: 1;
|
|
20
|
+
readonly sha256: "fcf3827028c1651ae42a7c7d7472153825a3121c936d58a3d105befc7dece9ea";
|
|
21
|
+
readonly url: URL;
|
|
22
|
+
}, {
|
|
23
|
+
readonly id: "20260810120000_storefront_catalog_attributes";
|
|
24
|
+
readonly catalogPath: "db/platform/migrations/20260810120000_storefront_catalog_attributes.sql";
|
|
25
|
+
readonly position: 8;
|
|
26
|
+
readonly sha256: "2bf938f5d0076193557bea834f86dbd9bcb7f3e2de00f99fb91cc1229b93a14b";
|
|
27
|
+
readonly url: URL;
|
|
28
|
+
}, {
|
|
29
|
+
readonly id: "20260827220000_catalog_document_revision_foundation";
|
|
30
|
+
readonly catalogPath: "db/platform/migrations/20260827220000_catalog_document_revision_foundation.sql";
|
|
31
|
+
readonly position: 58;
|
|
32
|
+
readonly sha256: "715e74d655b76d35b8a49e0d2a5625594a6c4856863f369cd1eadcd1fb1ae90e";
|
|
33
|
+
readonly url: URL;
|
|
34
|
+
}, {
|
|
35
|
+
readonly id: "20260827220001_catalog_document_revision_foundation_validate";
|
|
36
|
+
readonly catalogPath: "db/platform/migrations/20260827220001_catalog_document_revision_foundation_validate.sql";
|
|
37
|
+
readonly position: 59;
|
|
38
|
+
readonly sha256: "f3cd7fb61dcebac1cf0468cf2d7c1f9dd036817ab0094c72864266e307b269de";
|
|
39
|
+
readonly url: URL;
|
|
40
|
+
}, {
|
|
41
|
+
readonly id: "20260908100000_catalog_draft_foundation";
|
|
42
|
+
readonly catalogPath: "db/platform/migrations/20260908100000_catalog_draft_foundation.sql";
|
|
43
|
+
readonly position: 61;
|
|
44
|
+
readonly sha256: "ac0d614cdb2874df8fbdbbbda4f9455986ef95241fe1334b0b54a1fa6478ab2e";
|
|
45
|
+
readonly url: URL;
|
|
46
|
+
}];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Sparse projections of canonical units, never an install chain. */
|
|
2
|
+
export const BUNDLE_MIGRATIONS = [
|
|
3
|
+
{ id: "20260812140000_sellable_bundle_catalog", catalogPath: "db/platform/migrations/20260812140000_sellable_bundle_catalog.sql", position: 16, sha256: "62fbf0910a3a7a2ee47e2d798933fe0a5a273fd1242cae7cc78ff237ba39e394", url: new URL("../../sql/20260812140000_sellable_bundle_catalog.sql", import.meta.url) },
|
|
4
|
+
{ id: "20260812210000_bundle_operator_write_boundary", catalogPath: "db/platform/migrations/20260812210000_bundle_operator_write_boundary.sql", position: 19, sha256: "d0ec6674d7eedf4cd3ce0d8ccd7345ebe2f93da635316a68a6bd178ec55b2679", url: new URL("../../sql/20260812210000_bundle_operator_write_boundary.sql", import.meta.url) },
|
|
5
|
+
];
|
|
6
|
+
/** Catalog foundation projections; install the complete canonical catalogue. */
|
|
7
|
+
export const CATALOG_MIGRATIONS = [
|
|
8
|
+
{ id: "20260807140000_read_parity_catalog", catalogPath: "db/platform/migrations/20260807140000_read_parity_catalog.sql", position: 1, sha256: "fcf3827028c1651ae42a7c7d7472153825a3121c936d58a3d105befc7dece9ea", url: new URL("../../sql/20260807140000_read_parity_catalog.sql", import.meta.url) },
|
|
9
|
+
{ id: "20260810120000_storefront_catalog_attributes", catalogPath: "db/platform/migrations/20260810120000_storefront_catalog_attributes.sql", position: 8, sha256: "2bf938f5d0076193557bea834f86dbd9bcb7f3e2de00f99fb91cc1229b93a14b", url: new URL("../../sql/20260810120000_storefront_catalog_attributes.sql", import.meta.url) },
|
|
10
|
+
{ id: "20260827220000_catalog_document_revision_foundation", catalogPath: "db/platform/migrations/20260827220000_catalog_document_revision_foundation.sql", position: 58, sha256: "715e74d655b76d35b8a49e0d2a5625594a6c4856863f369cd1eadcd1fb1ae90e", url: new URL("../../sql/20260827220000_catalog_document_revision_foundation.sql", import.meta.url) },
|
|
11
|
+
{ id: "20260827220001_catalog_document_revision_foundation_validate", catalogPath: "db/platform/migrations/20260827220001_catalog_document_revision_foundation_validate.sql", position: 59, sha256: "f3cd7fb61dcebac1cf0468cf2d7c1f9dd036817ab0094c72864266e307b269de", url: new URL("../../sql/20260827220001_catalog_document_revision_foundation_validate.sql", import.meta.url) },
|
|
12
|
+
{ id: "20260908100000_catalog_draft_foundation", catalogPath: "db/platform/migrations/20260908100000_catalog_draft_foundation.sql", position: 61, sha256: "ac0d614cdb2874df8fbdbbbda4f9455986ef95241fe1334b0b54a1fa6478ab2e", url: new URL("../../sql/20260908100000_catalog_draft_foundation.sql", import.meta.url) },
|
|
13
|
+
];
|