@openlup/platform 0.16.0 → 0.18.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 +180 -0
- package/README.md +564 -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 +20 -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 +166 -0
- package/dist/catalog/bundleCatalogReadPort.js +36 -0
- package/dist/catalog/bundleCatalogStore.d.ts +3 -0
- package/dist/catalog/bundleCatalogStore.js +152 -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 +223 -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/foundationSchemas.d.ts +98 -0
- package/dist/catalog/foundationSchemas.js +110 -0
- package/dist/catalog/index.d.ts +43 -0
- package/dist/catalog/index.js +25 -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/accountingDocumentDelivery.d.ts +35 -0
- package/dist/communications/accountingDocumentDelivery.js +33 -0
- package/dist/communications/authEmailError.d.ts +5 -0
- package/dist/communications/authEmailError.js +8 -0
- package/dist/communications/authEmailPorts.d.ts +2 -0
- package/dist/communications/authEmailPorts.js +1 -0
- package/dist/communications/authSendEmailHook.d.ts +35 -0
- package/dist/communications/authSendEmailHook.js +250 -0
- package/dist/communications/capturedTransactionalDelivery.d.ts +13 -0
- package/dist/communications/capturedTransactionalDelivery.js +14 -0
- package/dist/communications/communicationSync.d.ts +11 -0
- package/dist/communications/communicationSync.js +79 -0
- package/dist/communications/communicationSyncWorker.d.ts +68 -0
- package/dist/communications/communicationSyncWorker.js +218 -0
- package/dist/communications/consentPolicy.d.ts +19 -0
- package/dist/communications/consentPolicy.js +43 -0
- package/dist/communications/consentPurposeRegistry.d.ts +4 -0
- package/dist/communications/consentPurposeRegistry.js +24 -0
- package/dist/communications/contracts/abandonedCart.d.ts +27 -0
- package/dist/communications/contracts/abandonedCart.js +25 -0
- package/dist/communications/contracts/authEmail.d.ts +62 -0
- package/dist/communications/contracts/authEmail.js +1 -0
- package/dist/communications/contracts/backInStock.d.ts +28 -0
- package/dist/communications/contracts/backInStock.js +28 -0
- package/dist/communications/contracts/blocks.d.ts +24 -0
- package/dist/communications/contracts/blocks.js +23 -0
- package/dist/communications/contracts/checkoutExpired.d.ts +22 -0
- package/dist/communications/contracts/checkoutExpired.js +25 -0
- package/dist/communications/contracts/checkoutRecovery.d.ts +26 -0
- package/dist/communications/contracts/checkoutRecovery.js +37 -0
- package/dist/communications/contracts/commerceEmailContent.d.ts +176 -0
- package/dist/communications/contracts/commerceEmailContent.js +1 -0
- package/dist/communications/contracts/commerceEngagementEmailContent.d.ts +95 -0
- package/dist/communications/contracts/commerceEngagementEmailContent.js +1 -0
- package/dist/communications/contracts/consent.d.ts +12 -0
- package/dist/communications/contracts/consent.js +1 -0
- package/dist/communications/contracts/email.d.ts +182 -0
- package/dist/communications/contracts/email.js +1 -0
- package/dist/communications/contracts/guideCard.d.ts +3 -0
- package/dist/communications/contracts/guideCard.js +26 -0
- package/dist/communications/contracts/index.d.ts +52 -0
- package/dist/communications/contracts/index.js +42 -0
- package/dist/communications/contracts/inquiryContent.d.ts +32 -0
- package/dist/communications/contracts/inquiryContent.js +33 -0
- package/dist/communications/contracts/invoiceDocumentContent.d.ts +26 -0
- package/dist/communications/contracts/invoiceDocumentContent.js +36 -0
- package/dist/communications/contracts/marketingAutomation.d.ts +52 -0
- package/dist/communications/contracts/marketingAutomation.js +1 -0
- package/dist/communications/contracts/marketingSync.d.ts +194 -0
- package/dist/communications/contracts/marketingSync.js +1 -0
- package/dist/communications/contracts/newsletter.d.ts +63 -0
- package/dist/communications/contracts/newsletter.js +1 -0
- package/dist/communications/contracts/newsletterWebhook.d.ts +26 -0
- package/dist/communications/contracts/newsletterWebhook.js +1 -0
- package/dist/communications/contracts/optOutContent.d.ts +11 -0
- package/dist/communications/contracts/optOutContent.js +17 -0
- package/dist/communications/contracts/orderCanceled.d.ts +25 -0
- package/dist/communications/contracts/orderCanceled.js +27 -0
- package/dist/communications/contracts/orderDraft.d.ts +46 -0
- package/dist/communications/contracts/orderDraft.js +46 -0
- package/dist/communications/contracts/orderPaid.d.ts +53 -0
- package/dist/communications/contracts/orderPaid.js +71 -0
- package/dist/communications/contracts/orderRefunded.d.ts +24 -0
- package/dist/communications/contracts/orderRefunded.js +27 -0
- package/dist/communications/contracts/paymentFailed.d.ts +24 -0
- package/dist/communications/contracts/paymentFailed.js +24 -0
- package/dist/communications/contracts/publicIntake.d.ts +49 -0
- package/dist/communications/contracts/publicIntake.js +1 -0
- package/dist/communications/contracts/render.d.ts +2 -0
- package/dist/communications/contracts/render.js +229 -0
- package/dist/communications/contracts/reorderReminder.d.ts +24 -0
- package/dist/communications/contracts/reorderReminder.js +24 -0
- package/dist/communications/contracts/returnEmails.d.ts +25 -0
- package/dist/communications/contracts/returnEmails.js +62 -0
- package/dist/communications/contracts/reviewEffects.d.ts +26 -0
- package/dist/communications/contracts/reviewEffects.js +25 -0
- package/dist/communications/contracts/reviewRequest.d.ts +26 -0
- package/dist/communications/contracts/reviewRequest.js +24 -0
- package/dist/communications/contracts/roleNotificationContent.d.ts +25 -0
- package/dist/communications/contracts/roleNotificationContent.js +46 -0
- package/dist/communications/contracts/shipmentDelivered.d.ts +23 -0
- package/dist/communications/contracts/shipmentDelivered.js +24 -0
- package/dist/communications/contracts/shipmentDispatched.d.ts +27 -0
- package/dist/communications/contracts/shipmentDispatched.js +35 -0
- package/dist/communications/contracts/shipmentException.d.ts +21 -0
- package/dist/communications/contracts/shipmentException.js +26 -0
- package/dist/communications/contracts/subscriptionActivationActionRequired.d.ts +17 -0
- package/dist/communications/contracts/subscriptionActivationActionRequired.js +22 -0
- package/dist/communications/contracts/subscriptionAddressChanged.d.ts +19 -0
- package/dist/communications/contracts/subscriptionAddressChanged.js +25 -0
- package/dist/communications/contracts/subscriptionCancelled.d.ts +19 -0
- package/dist/communications/contracts/subscriptionCancelled.js +25 -0
- package/dist/communications/contracts/subscriptionCycleSkipped.d.ts +25 -0
- package/dist/communications/contracts/subscriptionCycleSkipped.js +40 -0
- package/dist/communications/contracts/subscriptionDeliveryRescheduled.d.ts +25 -0
- package/dist/communications/contracts/subscriptionDeliveryRescheduled.js +39 -0
- package/dist/communications/contracts/subscriptionEmailContent.d.ts +145 -0
- package/dist/communications/contracts/subscriptionEmailContent.js +1 -0
- package/dist/communications/contracts/subscriptionPackageChanged.d.ts +20 -0
- package/dist/communications/contracts/subscriptionPackageChanged.js +26 -0
- package/dist/communications/contracts/subscriptionPauseReminder.d.ts +23 -0
- package/dist/communications/contracts/subscriptionPauseReminder.js +29 -0
- package/dist/communications/contracts/subscriptionPaused.d.ts +21 -0
- package/dist/communications/contracts/subscriptionPaused.js +25 -0
- package/dist/communications/contracts/subscriptionPaymentExpired.d.ts +34 -0
- package/dist/communications/contracts/subscriptionPaymentExpired.js +37 -0
- package/dist/communications/contracts/subscriptionPaymentFailed.d.ts +49 -0
- package/dist/communications/contracts/subscriptionPaymentFailed.js +56 -0
- package/dist/communications/contracts/subscriptionPaymentRecovered.d.ts +19 -0
- package/dist/communications/contracts/subscriptionPaymentRecovered.js +22 -0
- package/dist/communications/contracts/subscriptionRenewalAtRisk.d.ts +36 -0
- package/dist/communications/contracts/subscriptionRenewalAtRisk.js +36 -0
- package/dist/communications/contracts/subscriptionRenewalUpcoming.d.ts +49 -0
- package/dist/communications/contracts/subscriptionRenewalUpcoming.js +43 -0
- package/dist/communications/contracts/subscriptionResumed.d.ts +23 -0
- package/dist/communications/contracts/subscriptionResumed.js +25 -0
- package/dist/communications/contracts/subscriptionWelcome.d.ts +44 -0
- package/dist/communications/contracts/subscriptionWelcome.js +45 -0
- package/dist/communications/contracts/subscriptionWinback.d.ts +21 -0
- package/dist/communications/contracts/subscriptionWinback.js +28 -0
- package/dist/communications/contracts/transactionalDelivery.d.ts +42 -0
- package/dist/communications/contracts/transactionalDelivery.js +1 -0
- package/dist/communications/contracts/types.d.ts +46 -0
- package/dist/communications/contracts/types.js +1 -0
- package/dist/communications/contribution.d.ts +10 -0
- package/dist/communications/contribution.js +24 -0
- package/dist/communications/deliveryReconciliation.d.ts +64 -0
- package/dist/communications/deliveryReconciliation.js +60 -0
- package/dist/communications/emailEgress.d.ts +38 -0
- package/dist/communications/emailEgress.js +100 -0
- package/dist/communications/emailHealthAssessment.d.ts +39 -0
- package/dist/communications/emailHealthAssessment.js +59 -0
- package/dist/communications/emailHealthMetricsPort.d.ts +17 -0
- package/dist/communications/emailHealthMetricsPort.js +1 -0
- package/dist/communications/emailNotificationControl.d.ts +27 -0
- package/dist/communications/emailNotificationControl.js +10 -0
- package/dist/communications/emailObservation.d.ts +28 -0
- package/dist/communications/emailObservation.js +23 -0
- package/dist/communications/emailTransport.d.ts +82 -0
- package/dist/communications/emailTransport.js +95 -0
- package/dist/communications/errors.d.ts +15 -0
- package/dist/communications/errors.js +30 -0
- package/dist/communications/index.d.ts +47 -0
- package/dist/communications/index.js +38 -0
- package/dist/communications/integrationEventSignature.d.ts +15 -0
- package/dist/communications/integrationEventSignature.js +37 -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/managedTransactionalDeliveryStore.d.ts +12 -0
- package/dist/communications/managedTransactionalDeliveryStore.js +49 -0
- package/dist/communications/nativeOperations.d.ts +79 -0
- package/dist/communications/nativeOperations.js +3 -0
- package/dist/communications/newsletterIntegrationContracts.d.ts +130 -0
- package/dist/communications/newsletterIntegrationContracts.js +128 -0
- package/dist/communications/newsletterWebhookPort.d.ts +11 -0
- package/dist/communications/newsletterWebhookPort.js +84 -0
- package/dist/communications/newsletterWebhookProcessing.d.ts +17 -0
- package/dist/communications/newsletterWebhookProcessing.js +71 -0
- package/dist/communications/originPolicy.d.ts +40 -0
- package/dist/communications/originPolicy.js +100 -0
- package/dist/communications/postgresCommunicationSync.d.ts +79 -0
- package/dist/communications/postgresCommunicationSync.js +111 -0
- package/dist/communications/postgresConsentEvaluator.d.ts +19 -0
- package/dist/communications/postgresConsentEvaluator.js +43 -0
- package/dist/communications/postgresDeliveryReconciliation.d.ts +3 -0
- package/dist/communications/postgresDeliveryReconciliation.js +113 -0
- package/dist/communications/postgresNativeOperations.d.ts +13 -0
- package/dist/communications/postgresNativeOperations.js +63 -0
- package/dist/communications/postgresNotificationRecipients.d.ts +37 -0
- package/dist/communications/postgresNotificationRecipients.js +60 -0
- package/dist/communications/postgresTransactionalDeliveryStore.d.ts +7 -0
- package/dist/communications/postgresTransactionalDeliveryStore.js +55 -0
- package/dist/communications/preferencesToken.d.ts +10 -0
- package/dist/communications/preferencesToken.js +40 -0
- package/dist/communications/publicPreferenceToken.d.ts +24 -0
- package/dist/communications/publicPreferenceToken.js +53 -0
- package/dist/communications/resend/index.d.ts +40 -0
- package/dist/communications/resend/index.js +310 -0
- package/dist/communications/shipmentNotifications.d.ts +34 -0
- package/dist/communications/shipmentNotifications.js +61 -0
- package/dist/communications/sql.d.ts +26 -0
- package/dist/communications/sql.js +7 -0
- package/dist/communications/standardWebhooks.d.ts +14 -0
- package/dist/communications/standardWebhooks.js +73 -0
- package/dist/communications/status.d.ts +11 -0
- package/dist/communications/status.js +36 -0
- package/dist/communications/transactionalDelivery.d.ts +19 -0
- package/dist/communications/transactionalDelivery.js +96 -0
- package/dist/communications/transactionalDeliveryIdentifier.d.ts +3 -0
- package/dist/communications/transactionalDeliveryIdentifier.js +6 -0
- package/dist/communications/unsubscribeToken.d.ts +77 -0
- package/dist/communications/unsubscribeToken.js +150 -0
- package/dist/communications/validation.d.ts +2 -0
- package/dist/communications/validation.js +3 -0
- package/dist/composition/catalogContribution.d.ts +18 -0
- package/dist/composition/catalogContribution.js +21 -0
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.js +1 -0
- package/dist/http/webhookSignature.d.ts +42 -0
- package/dist/http/webhookSignature.js +86 -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/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 +13 -0
- package/dist/inventory/index.js +10 -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 +26 -0
- package/dist/pricing/commercePriceAuthority.js +79 -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 +31 -0
- package/dist/pricing/commerceQuoteHandler.js +110 -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 +66 -0
- package/dist/pricing/dbBackedCommerceQuotePort.js +206 -0
- package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.d.ts +4 -0
- package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.js +25 -0
- package/dist/pricing/index.d.ts +51 -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/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/contracts/index.d.ts +387 -0
- package/dist/promotions/contracts/index.js +1 -0
- package/dist/promotions/index.d.ts +22 -0
- package/dist/promotions/index.js +21 -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 +65 -0
- package/dist/promotions/promotionQuoteAcceptance.js +202 -0
- package/dist/promotions/promotionQuoteBinding.d.ts +71 -0
- package/dist/promotions/promotionQuoteBinding.js +85 -0
- package/dist/promotions/quoteAutomaticPromotions.d.ts +24 -0
- package/dist/promotions/quoteAutomaticPromotions.js +36 -0
- package/dist/promotions/quotePromoDiscounts.d.ts +32 -0
- package/dist/promotions/quotePromoDiscounts.js +140 -0
- package/dist/promotions/quotePromotionCodeAdjustments.d.ts +27 -0
- package/dist/promotions/quotePromotionCodeAdjustments.js +223 -0
- package/dist/promotions/quotePromotionV2.d.ts +29 -0
- package/dist/promotions/quotePromotionV2.js +174 -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/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 +3 -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/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 +17 -0
- package/dist/shipping/index.js +8 -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/package.json +72 -2
- package/release-gates.json +249 -8
- package/sql/20260807140000_read_parity_catalog.sql +94 -0
- package/sql/20260807190000_comms_outbox_rail.sql +329 -0
- package/sql/20260810120000_storefront_catalog_attributes.sql +51 -0
- package/sql/20260810120001_transactional_delivery_receipts.sql +209 -0
- package/sql/20260812140000_sellable_bundle_catalog.sql +124 -0
- package/sql/20260812210000_bundle_operator_write_boundary.sql +567 -0
- package/sql/20260813120000_communications_control_plane.sql +568 -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/sql/20261019200000_communications_native_operations.sql +68 -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 +261 -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 +177 -0
- package/src/catalog/bundleCatalogStore.ts +269 -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/foundationSchemas.ts +123 -0
- package/src/catalog/index.ts +43 -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/accountingDocumentDelivery.ts +63 -0
- package/src/communications/authEmailError.ts +10 -0
- package/src/communications/authEmailPorts.ts +2 -0
- package/src/communications/authSendEmailHook.ts +310 -0
- package/src/communications/capturedTransactionalDelivery.ts +29 -0
- package/src/communications/communicationSync.ts +96 -0
- package/src/communications/communicationSyncWorker.ts +302 -0
- package/src/communications/consentPolicy.ts +82 -0
- package/src/communications/consentPurposeRegistry.ts +31 -0
- package/src/communications/contracts/abandonedCart.ts +64 -0
- package/src/communications/contracts/authEmail.ts +73 -0
- package/src/communications/contracts/backInStock.ts +69 -0
- package/src/communications/contracts/blocks.ts +47 -0
- package/src/communications/contracts/checkoutExpired.ts +62 -0
- package/src/communications/contracts/checkoutRecovery.ts +68 -0
- package/src/communications/contracts/commerceEmailContent.ts +189 -0
- package/src/communications/contracts/commerceEngagementEmailContent.ts +106 -0
- package/src/communications/contracts/consent.ts +13 -0
- package/src/communications/contracts/email.ts +210 -0
- package/src/communications/contracts/guideCard.ts +34 -0
- package/src/communications/contracts/index.ts +52 -0
- package/src/communications/contracts/inquiryContent.ts +53 -0
- package/src/communications/contracts/invoiceDocumentContent.ts +57 -0
- package/src/communications/contracts/marketingAutomation.ts +45 -0
- package/src/communications/contracts/marketingSync.ts +109 -0
- package/src/communications/contracts/newsletter.ts +78 -0
- package/src/communications/contracts/newsletterWebhook.ts +23 -0
- package/src/communications/contracts/optOutContent.ts +23 -0
- package/src/communications/contracts/orderCanceled.ts +64 -0
- package/src/communications/contracts/orderDraft.ts +112 -0
- package/src/communications/contracts/orderPaid.ts +147 -0
- package/src/communications/contracts/orderRefunded.ts +63 -0
- package/src/communications/contracts/paymentFailed.ts +59 -0
- package/src/communications/contracts/publicIntake.ts +53 -0
- package/src/communications/contracts/render.ts +271 -0
- package/src/communications/contracts/reorderReminder.ts +59 -0
- package/src/communications/contracts/returnEmails.ts +113 -0
- package/src/communications/contracts/reviewEffects.ts +60 -0
- package/src/communications/contracts/reviewRequest.ts +59 -0
- package/src/communications/contracts/roleNotificationContent.ts +65 -0
- package/src/communications/contracts/shipmentDelivered.ts +59 -0
- package/src/communications/contracts/shipmentDispatched.ts +77 -0
- package/src/communications/contracts/shipmentException.ts +62 -0
- package/src/communications/contracts/subscriptionActivationActionRequired.ts +37 -0
- package/src/communications/contracts/subscriptionAddressChanged.ts +56 -0
- package/src/communications/contracts/subscriptionCancelled.ts +57 -0
- package/src/communications/contracts/subscriptionCycleSkipped.ts +80 -0
- package/src/communications/contracts/subscriptionDeliveryRescheduled.ts +79 -0
- package/src/communications/contracts/subscriptionEmailContent.ts +163 -0
- package/src/communications/contracts/subscriptionPackageChanged.ts +59 -0
- package/src/communications/contracts/subscriptionPauseReminder.ts +63 -0
- package/src/communications/contracts/subscriptionPaused.ts +58 -0
- package/src/communications/contracts/subscriptionPaymentExpired.ts +83 -0
- package/src/communications/contracts/subscriptionPaymentFailed.ts +117 -0
- package/src/communications/contracts/subscriptionPaymentRecovered.ts +50 -0
- package/src/communications/contracts/subscriptionRenewalAtRisk.ts +85 -0
- package/src/communications/contracts/subscriptionRenewalUpcoming.ts +103 -0
- package/src/communications/contracts/subscriptionResumed.ts +60 -0
- package/src/communications/contracts/subscriptionWelcome.ts +102 -0
- package/src/communications/contracts/subscriptionWinback.ts +62 -0
- package/src/communications/contracts/transactionalDelivery.ts +43 -0
- package/src/communications/contracts/types.ts +58 -0
- package/src/communications/contribution.ts +33 -0
- package/src/communications/deliveryReconciliation.ts +108 -0
- package/src/communications/emailEgress.ts +111 -0
- package/src/communications/emailHealthAssessment.ts +106 -0
- package/src/communications/emailHealthMetricsPort.ts +17 -0
- package/src/communications/emailNotificationControl.ts +28 -0
- package/src/communications/emailObservation.ts +43 -0
- package/src/communications/emailTransport.ts +167 -0
- package/src/communications/errors.ts +34 -0
- package/src/communications/index.ts +47 -0
- package/src/communications/integrationEventSignature.ts +49 -0
- package/src/communications/klaviyo/consentPush.ts +19 -0
- package/src/communications/klaviyo/index.ts +649 -0
- package/src/communications/managedTransactionalDeliveryStore.ts +59 -0
- package/src/communications/nativeOperations.ts +40 -0
- package/src/communications/newsletterIntegrationContracts.ts +154 -0
- package/src/communications/newsletterWebhookPort.ts +104 -0
- package/src/communications/newsletterWebhookProcessing.ts +102 -0
- package/src/communications/originPolicy.ts +151 -0
- package/src/communications/postgresCommunicationSync.ts +127 -0
- package/src/communications/postgresConsentEvaluator.ts +49 -0
- package/src/communications/postgresDeliveryReconciliation.ts +101 -0
- package/src/communications/postgresNativeOperations.ts +55 -0
- package/src/communications/postgresNotificationRecipients.ts +57 -0
- package/src/communications/postgresTransactionalDeliveryStore.ts +79 -0
- package/src/communications/preferencesToken.ts +62 -0
- package/src/communications/publicPreferenceToken.ts +68 -0
- package/src/communications/resend/index.ts +350 -0
- package/src/communications/shipmentNotifications.ts +78 -0
- package/src/communications/sql.ts +7 -0
- package/src/communications/standardWebhooks.ts +84 -0
- package/src/communications/status.ts +51 -0
- package/src/communications/transactionalDelivery.ts +114 -0
- package/src/communications/transactionalDeliveryIdentifier.ts +9 -0
- package/src/communications/unsubscribeToken.ts +186 -0
- package/src/communications/validation.ts +3 -0
- package/src/composition/catalogContribution.ts +32 -0
- package/src/composition/index.ts +1 -0
- package/src/http/index.ts +1 -0
- package/src/http/webhookSignature.ts +96 -0
- package/src/inventory/adminInventory.ts +251 -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 +21 -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 +104 -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 +184 -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 +260 -0
- package/src/pricing/dbBackedCommerceQuoteSnapshotVerifier.ts +49 -0
- package/src/pricing/index.ts +52 -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/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/contracts/index.ts +387 -0
- package/src/promotions/index.ts +22 -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 +284 -0
- package/src/promotions/promotionQuoteBinding.ts +158 -0
- package/src/promotions/quoteAutomaticPromotions.ts +58 -0
- package/src/promotions/quotePromoDiscounts.ts +185 -0
- package/src/promotions/quotePromotionCodeAdjustments.ts +277 -0
- package/src/promotions/quotePromotionV2.ts +223 -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/contracts/address.ts +71 -0
- package/src/shipping/contracts/delivery.ts +114 -0
- package/src/shipping/contracts/index.ts +18 -0
- package/src/shipping/contracts/shippingRate.ts +7 -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 +23 -0
- package/src/shipping/pickupPointSearchPort.ts +8 -0
- package/src/shipping/readDeliverySelectionEvidence.ts +51 -0
- package/src/shipping/shippingRatePorts.ts +36 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { BundleAvailability, BundleAvailabilityComponent } from "./bundleAvailability.js";
|
|
2
|
+
import type { BundleStockPort as CommerceOfferAvailabilityPort } from "./bundleBindings.js";
|
|
3
|
+
import type { ActiveBundleComposition, BundleCatalogReadPort } from "./bundleCatalogReadPort.js";
|
|
4
|
+
/**
|
|
5
|
+
* Derived bundle stock, composed from the two ports that already know the halves:
|
|
6
|
+
* the bundle read port knows the bill of materials, the EXISTING commerce offer
|
|
7
|
+
* availability port knows what a unit's stock is. Nothing here re-derives stock and
|
|
8
|
+
* nothing here opens a database handle.
|
|
9
|
+
*
|
|
10
|
+
* ONE BATCHED CALL, ALWAYS. Every component of every bundle in the request is
|
|
11
|
+
* asked for in a single `getAvailability`, deduplicated by sku, because the
|
|
12
|
+
* underlying port answers a set in three queries — asking per bundle would turn a
|
|
13
|
+
* catalogue listing into a query storm and would let two bundles sharing a unit
|
|
14
|
+
* disagree about its stock inside one response.
|
|
15
|
+
*
|
|
16
|
+
* A sku the availability port does not answer for is a MISSING figure, not zero:
|
|
17
|
+
* it is folded in as `sellableNow: null`, so the pure kernel reports the bundle as
|
|
18
|
+
* unknown and names the component rather than quietly overselling or hiding it.
|
|
19
|
+
*/
|
|
20
|
+
export interface BundleAvailabilityServiceDeps {
|
|
21
|
+
bundleCatalogReadPort: BundleCatalogReadPort;
|
|
22
|
+
offerAvailabilityPort: CommerceOfferAvailabilityPort;
|
|
23
|
+
/** Threshold handed to the pure kernel; its own default applies when omitted. */
|
|
24
|
+
lowStockThreshold?: number;
|
|
25
|
+
includeAddonsInStock?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface BundleAvailabilityRow {
|
|
28
|
+
composition: ActiveBundleComposition;
|
|
29
|
+
availability: BundleAvailability;
|
|
30
|
+
/**
|
|
31
|
+
* The EXACT rows the kernel was given, carried out again rather than recomputed.
|
|
32
|
+
*
|
|
33
|
+
* The bundle-level answer names one limiting component; an operator staring at a bundle that
|
|
34
|
+
* cannot ship needs to know how far off every OTHER component is too, so they can tell "order one
|
|
35
|
+
* more of this" from "this bundle is months away". These rows are the only place that figure
|
|
36
|
+
* exists — the kernel folds them into a single number and the sellable feed's components carry
|
|
37
|
+
* price, never stock. Returning them costs nothing here and is the alternative to a second stock
|
|
38
|
+
* derivation somewhere that can disagree with this one.
|
|
39
|
+
*/
|
|
40
|
+
components: readonly BundleAvailabilityComponent[];
|
|
41
|
+
}
|
|
42
|
+
export interface BundleAvailabilityService {
|
|
43
|
+
/** Fold stock into a set of compositions the caller already holds. */
|
|
44
|
+
describeCompositions(compositions: readonly ActiveBundleComposition[]): Promise<BundleAvailabilityRow[]>;
|
|
45
|
+
/** Read the live sellable set and fold stock into it. */
|
|
46
|
+
describeActiveBundles(input?: {
|
|
47
|
+
currency?: string;
|
|
48
|
+
}): Promise<BundleAvailabilityRow[]>;
|
|
49
|
+
}
|
|
50
|
+
export declare function createBundleAvailabilityServices({ deriveBundleAvailability }: {
|
|
51
|
+
deriveBundleAvailability: (input: import("./bundleAvailability.js").DeriveBundleAvailabilityInput) => BundleAvailability;
|
|
52
|
+
}): {
|
|
53
|
+
createBundleAvailabilityService: (deps: BundleAvailabilityServiceDeps) => BundleAvailabilityService;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* The port to use where no stock source is bound at all.
|
|
57
|
+
*
|
|
58
|
+
* It answers every item with `sellableNow: null`, which the kernel reads as
|
|
59
|
+
* unknown — so a deployment without an inventory rail publishes bundles whose
|
|
60
|
+
* price is exact and whose stock is honestly unstated. The alternative, omitting
|
|
61
|
+
* the availability block, would have made "we do not know" indistinguishable from
|
|
62
|
+
* "we did not ask", and the alternative to THAT — defaulting to available —
|
|
63
|
+
* oversells on a deployment that never counted anything.
|
|
64
|
+
*/
|
|
65
|
+
export declare function createUnknownOfferAvailabilityPort(): CommerceOfferAvailabilityPort;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export function createBundleAvailabilityServices({ deriveBundleAvailability }) {
|
|
2
|
+
function createBundleAvailabilityService(deps) {
|
|
3
|
+
async function describeCompositions(compositions) {
|
|
4
|
+
if (compositions.length === 0)
|
|
5
|
+
return [];
|
|
6
|
+
const items = requestItems(compositions);
|
|
7
|
+
const stock = items.length === 0
|
|
8
|
+
? new Map()
|
|
9
|
+
: sellableBySku(await deps.offerAvailabilityPort.getAvailability({ items }));
|
|
10
|
+
return compositions.map((composition) => {
|
|
11
|
+
const components = composition.components.map((component) => ({
|
|
12
|
+
sku: component.sku,
|
|
13
|
+
quantity: component.quantity,
|
|
14
|
+
isAddon: component.isAddon,
|
|
15
|
+
// `has` distinguishes "answered null" from "never answered"; both fold to
|
|
16
|
+
// null, and neither is allowed to become a number here.
|
|
17
|
+
sellableNow: stock.has(component.sku) ? (stock.get(component.sku) ?? null) : null,
|
|
18
|
+
}));
|
|
19
|
+
return {
|
|
20
|
+
composition,
|
|
21
|
+
components,
|
|
22
|
+
availability: deriveBundleAvailability({
|
|
23
|
+
components,
|
|
24
|
+
lowStockThreshold: deps.lowStockThreshold,
|
|
25
|
+
includeAddonsInStock: deps.includeAddonsInStock,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
describeCompositions,
|
|
32
|
+
async describeActiveBundles(input = {}) {
|
|
33
|
+
return describeCompositions(await deps.bundleCatalogReadPort.listActiveBundleCompositions(input));
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { createBundleAvailabilityService };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The port to use where no stock source is bound at all.
|
|
41
|
+
*
|
|
42
|
+
* It answers every item with `sellableNow: null`, which the kernel reads as
|
|
43
|
+
* unknown — so a deployment without an inventory rail publishes bundles whose
|
|
44
|
+
* price is exact and whose stock is honestly unstated. The alternative, omitting
|
|
45
|
+
* the availability block, would have made "we do not know" indistinguishable from
|
|
46
|
+
* "we did not ask", and the alternative to THAT — defaulting to available —
|
|
47
|
+
* oversells on a deployment that never counted anything.
|
|
48
|
+
*/
|
|
49
|
+
export function createUnknownOfferAvailabilityPort() {
|
|
50
|
+
return {
|
|
51
|
+
getAvailability({ items }) {
|
|
52
|
+
return Promise.resolve(items.map((item) => ({
|
|
53
|
+
sku: item.sku,
|
|
54
|
+
productSlug: item.productSlug,
|
|
55
|
+
variantId: item.variantId,
|
|
56
|
+
status: "unknown",
|
|
57
|
+
visibleInConfigurator: true,
|
|
58
|
+
sellableNow: null,
|
|
59
|
+
reasonCode: "stock_unknown",
|
|
60
|
+
source: "unbound",
|
|
61
|
+
})));
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* One request item per distinct sku across every bundle. `requestedQuantity` stays
|
|
67
|
+
* at the port's own default of one: the question asked is "how many units exist",
|
|
68
|
+
* and the multiplication by the bill of materials belongs to the pure kernel,
|
|
69
|
+
* which is the only place that knows how many bundles a figure buys.
|
|
70
|
+
*/
|
|
71
|
+
function requestItems(compositions) {
|
|
72
|
+
const bySku = new Map();
|
|
73
|
+
for (const composition of compositions) {
|
|
74
|
+
for (const component of composition.components) {
|
|
75
|
+
if (!bySku.has(component.sku))
|
|
76
|
+
bySku.set(component.sku, component);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return [...bySku.values()].map((component) => ({
|
|
80
|
+
sku: component.sku,
|
|
81
|
+
productSlug: component.productSlug,
|
|
82
|
+
variantId: component.variantId,
|
|
83
|
+
requestedQuantity: 1,
|
|
84
|
+
checkoutMode: "one_time",
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
function sellableBySku(answers) {
|
|
88
|
+
return new Map(answers.map((answer) => [answer.sku, answer.sellableNow ?? null]));
|
|
89
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { BundleActorKind } from "./bundleRuleCodes.js";
|
|
2
|
+
/** The host's normalized stock seam; no inventory implementation is owned here. */
|
|
3
|
+
export type BundleStockStatus = "available" | "low_stock" | "out_of_stock" | "unknown";
|
|
4
|
+
export interface BundleStockRequestItem {
|
|
5
|
+
sku: string;
|
|
6
|
+
productSlug: string;
|
|
7
|
+
variantId: string;
|
|
8
|
+
requestedQuantity: number;
|
|
9
|
+
checkoutMode: "one_time" | "subscription";
|
|
10
|
+
}
|
|
11
|
+
export interface BundleStockAvailability {
|
|
12
|
+
sku: string;
|
|
13
|
+
productSlug: string;
|
|
14
|
+
variantId: string;
|
|
15
|
+
status: BundleStockStatus;
|
|
16
|
+
visibleInConfigurator: boolean;
|
|
17
|
+
sellableNow: number | null;
|
|
18
|
+
reasonCode: string;
|
|
19
|
+
source: string;
|
|
20
|
+
}
|
|
21
|
+
export interface BundleStockPort {
|
|
22
|
+
getAvailability(input: {
|
|
23
|
+
items: readonly BundleStockRequestItem[];
|
|
24
|
+
}): Promise<BundleStockAvailability[]>;
|
|
25
|
+
}
|
|
26
|
+
export interface BundleRuleBindings {
|
|
27
|
+
assertActivateNotMachineActor(input: {
|
|
28
|
+
operation: string;
|
|
29
|
+
actorKind: BundleActorKind;
|
|
30
|
+
}): "DRAFT_ONLY_FOR_MACHINE" | null;
|
|
31
|
+
offerAvailabilityStatusFor(sellableNow: number | null, lowStockThreshold?: number): BundleStockStatus;
|
|
32
|
+
offerAvailabilityReasonCode(status: BundleStockStatus): string;
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The statements the direct-Postgres bundle read adapter renders.
|
|
3
|
+
*
|
|
4
|
+
* They live beside the adapter rather than inside it because they are the part a
|
|
5
|
+
* reader comes here to check — which relations are touched, which columns are
|
|
6
|
+
* asked for, and how a component's reference price is resolved — and reading them
|
|
7
|
+
* should not mean scrolling past the row marshalling that consumes them.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SUMMARY_COLUMNS = "\n b.id, b.code, b.title, b.status, b.fulfillment_mode, b.updated_at,\n b.composition_constraint, b.metadata,\n (SELECT count(*) FROM public.catalog_bundle_components c WHERE c.bundle_id = b.id)\n AS component_count,\n EXISTS (SELECT 1 FROM public.catalog_bundle_prices p WHERE p.bundle_id = b.id AND p.active)\n AS has_active_target_price";
|
|
10
|
+
export declare const LIST_FILTER = "\n WHERE ($1::text = 'all' OR b.status = $1::text)\n AND ($2::text IS NULL OR b.code ILIKE '%' || $2 || '%' OR b.title ILIKE '%' || $2 || '%')";
|
|
11
|
+
export declare const LIST_SQL = "SELECT \n b.id, b.code, b.title, b.status, b.fulfillment_mode, b.updated_at,\n b.composition_constraint, b.metadata,\n (SELECT count(*) FROM public.catalog_bundle_components c WHERE c.bundle_id = b.id)\n AS component_count,\n EXISTS (SELECT 1 FROM public.catalog_bundle_prices p WHERE p.bundle_id = b.id AND p.active)\n AS has_active_target_price FROM public.catalog_bundles b \n WHERE ($1::text = 'all' OR b.status = $1::text)\n AND ($2::text IS NULL OR b.code ILIKE '%' || $2 || '%' OR b.title ILIKE '%' || $2 || '%')\n ORDER BY b.code LIMIT $3 OFFSET $4";
|
|
12
|
+
export declare const COUNT_SQL = "SELECT count(*) AS total FROM public.catalog_bundles b \n WHERE ($1::text = 'all' OR b.status = $1::text)\n AND ($2::text IS NULL OR b.code ILIKE '%' || $2 || '%' OR b.title ILIKE '%' || $2 || '%')";
|
|
13
|
+
export declare const DETAIL_SQL = "SELECT \n b.id, b.code, b.title, b.status, b.fulfillment_mode, b.updated_at,\n b.composition_constraint, b.metadata,\n (SELECT count(*) FROM public.catalog_bundle_components c WHERE c.bundle_id = b.id)\n AS component_count,\n EXISTS (SELECT 1 FROM public.catalog_bundle_prices p WHERE p.bundle_id = b.id AND p.active)\n AS has_active_target_price FROM public.catalog_bundles b WHERE b.code = $1";
|
|
14
|
+
/**
|
|
15
|
+
* The unit's reference price in ONE named list: the lowest tier that is active,
|
|
16
|
+
* newest window first. A unit the list prices nothing for resolves to NULL rather
|
|
17
|
+
* than dropping the component, so a caller sees an unpriced part instead of a
|
|
18
|
+
* shorter bill of materials.
|
|
19
|
+
*/
|
|
20
|
+
export declare const REFERENCE_PRICE = "(\n SELECT pe.unit_price_minor FROM public.price_entries pe\n WHERE pe.variant_id = s.id AND pe.price_list_id = %LIST% AND pe.active\n ORDER BY pe.min_qty ASC, pe.valid_from DESC LIMIT 1)";
|
|
21
|
+
export declare const COMPONENT_SQL: string;
|
|
22
|
+
export declare const FEED_COMPONENT_SQL: string;
|
|
23
|
+
export declare const PRICE_SQL = "\n SELECT p.mode, p.target_price_minor, list.currency, p.amount_kind, p.active,\n p.valid_from, p.valid_to\n FROM public.catalog_bundle_prices p\n JOIN public.price_lists AS list ON list.id = p.price_list_id\n WHERE p.bundle_id = $1::uuid\n ORDER BY p.valid_from DESC";
|
|
24
|
+
export declare const OWN_LIST_SQL = "\n SELECT list.id, list.currency\n FROM public.catalog_bundle_prices p\n JOIN public.price_lists AS list ON list.id = p.price_list_id\n WHERE p.bundle_id = $1::uuid AND p.active AND ($2::text IS NULL OR p.mode = $2::text)\n ORDER BY p.valid_from DESC LIMIT 1";
|
|
25
|
+
export declare const CURRENCY_LIST_SQL = "\n SELECT id, currency FROM public.price_lists\n WHERE currency = $1::text AND status = 'active'\n ORDER BY created_at DESC LIMIT 1";
|
|
26
|
+
export declare const FEED_SQL = "\n SELECT b.id, b.code, b.title, b.fulfillment_mode, p.mode, p.target_price_minor,\n p.price_list_id, list.currency\n FROM public.catalog_bundles b\n JOIN public.catalog_bundle_prices p ON p.bundle_id = b.id AND p.active\n JOIN public.price_lists AS list ON list.id = p.price_list_id\n WHERE b.status = 'active' AND ($1::text IS NULL OR list.currency = $1::text)\n ORDER BY b.code, p.valid_from DESC";
|
|
27
|
+
export declare const HISTORY_SQL = "\n SELECT id, bundle_code, action, before_state, after_state, created_at\n FROM public.catalog_bundle_write_events\n WHERE bundle_code = $1::text\n ORDER BY created_at DESC LIMIT $2 OFFSET $3";
|
|
28
|
+
export declare const HISTORY_COUNT_SQL = "\n SELECT count(*) AS total FROM public.catalog_bundle_write_events WHERE bundle_code = $1::text";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The statements the direct-Postgres bundle read adapter renders.
|
|
3
|
+
*
|
|
4
|
+
* They live beside the adapter rather than inside it because they are the part a
|
|
5
|
+
* reader comes here to check — which relations are touched, which columns are
|
|
6
|
+
* asked for, and how a component's reference price is resolved — and reading them
|
|
7
|
+
* should not mean scrolling past the row marshalling that consumes them.
|
|
8
|
+
*/
|
|
9
|
+
export const SUMMARY_COLUMNS = `
|
|
10
|
+
b.id, b.code, b.title, b.status, b.fulfillment_mode, b.updated_at,
|
|
11
|
+
b.composition_constraint, b.metadata,
|
|
12
|
+
(SELECT count(*) FROM public.catalog_bundle_components c WHERE c.bundle_id = b.id)
|
|
13
|
+
AS component_count,
|
|
14
|
+
EXISTS (SELECT 1 FROM public.catalog_bundle_prices p WHERE p.bundle_id = b.id AND p.active)
|
|
15
|
+
AS has_active_target_price`;
|
|
16
|
+
export const LIST_FILTER = `
|
|
17
|
+
WHERE ($1::text = 'all' OR b.status = $1::text)
|
|
18
|
+
AND ($2::text IS NULL OR b.code ILIKE '%' || $2 || '%' OR b.title ILIKE '%' || $2 || '%')`;
|
|
19
|
+
export const LIST_SQL = `SELECT ${SUMMARY_COLUMNS} FROM public.catalog_bundles b ${LIST_FILTER}
|
|
20
|
+
ORDER BY b.code LIMIT $3 OFFSET $4`;
|
|
21
|
+
export const COUNT_SQL = `SELECT count(*) AS total FROM public.catalog_bundles b ${LIST_FILTER}`;
|
|
22
|
+
export const DETAIL_SQL = `SELECT ${SUMMARY_COLUMNS} FROM public.catalog_bundles b WHERE b.code = $1`;
|
|
23
|
+
/**
|
|
24
|
+
* The unit's reference price in ONE named list: the lowest tier that is active,
|
|
25
|
+
* newest window first. A unit the list prices nothing for resolves to NULL rather
|
|
26
|
+
* than dropping the component, so a caller sees an unpriced part instead of a
|
|
27
|
+
* shorter bill of materials.
|
|
28
|
+
*/
|
|
29
|
+
export const REFERENCE_PRICE = `(
|
|
30
|
+
SELECT pe.unit_price_minor FROM public.price_entries pe
|
|
31
|
+
WHERE pe.variant_id = s.id AND pe.price_list_id = %LIST% AND pe.active
|
|
32
|
+
ORDER BY pe.min_qty ASC, pe.valid_from DESC LIMIT 1)`;
|
|
33
|
+
export const COMPONENT_SQL = `
|
|
34
|
+
SELECT c.bundle_id, s.sku, s.title, pr.slug AS product_slug, s.id AS variant_id,
|
|
35
|
+
c.quantity, c.is_addon, c.sort_order,
|
|
36
|
+
${REFERENCE_PRICE.replace("%LIST%", "$2::uuid")} AS reference_unit_price_minor
|
|
37
|
+
FROM public.catalog_bundle_components c
|
|
38
|
+
JOIN public.catalog_skus s ON s.id = c.catalog_sku_id
|
|
39
|
+
JOIN public.catalog_products pr ON pr.id = s.product_id
|
|
40
|
+
WHERE c.bundle_id = $1::uuid
|
|
41
|
+
ORDER BY c.sort_order, s.sku`;
|
|
42
|
+
// One statement for the whole feed: each bundle carries its own price list, so the
|
|
43
|
+
// per-bundle list is zipped in rather than looped over.
|
|
44
|
+
export const FEED_COMPONENT_SQL = `
|
|
45
|
+
SELECT c.bundle_id, s.sku, s.title, pr.slug AS product_slug, s.id AS variant_id,
|
|
46
|
+
c.quantity, c.is_addon, c.sort_order,
|
|
47
|
+
${REFERENCE_PRICE.replace("%LIST%", "selected.price_list_id")} AS reference_unit_price_minor
|
|
48
|
+
FROM unnest($1::uuid[], $2::uuid[]) AS selected(bundle_id, price_list_id)
|
|
49
|
+
JOIN public.catalog_bundle_components c ON c.bundle_id = selected.bundle_id
|
|
50
|
+
JOIN public.catalog_skus s ON s.id = c.catalog_sku_id
|
|
51
|
+
JOIN public.catalog_products pr ON pr.id = s.product_id
|
|
52
|
+
ORDER BY c.bundle_id, c.sort_order, s.sku`;
|
|
53
|
+
export const PRICE_SQL = `
|
|
54
|
+
SELECT p.mode, p.target_price_minor, list.currency, p.amount_kind, p.active,
|
|
55
|
+
p.valid_from, p.valid_to
|
|
56
|
+
FROM public.catalog_bundle_prices p
|
|
57
|
+
JOIN public.price_lists AS list ON list.id = p.price_list_id
|
|
58
|
+
WHERE p.bundle_id = $1::uuid
|
|
59
|
+
ORDER BY p.valid_from DESC`;
|
|
60
|
+
export const OWN_LIST_SQL = `
|
|
61
|
+
SELECT list.id, list.currency
|
|
62
|
+
FROM public.catalog_bundle_prices p
|
|
63
|
+
JOIN public.price_lists AS list ON list.id = p.price_list_id
|
|
64
|
+
WHERE p.bundle_id = $1::uuid AND p.active AND ($2::text IS NULL OR p.mode = $2::text)
|
|
65
|
+
ORDER BY p.valid_from DESC LIMIT 1`;
|
|
66
|
+
export const CURRENCY_LIST_SQL = `
|
|
67
|
+
SELECT id, currency FROM public.price_lists
|
|
68
|
+
WHERE currency = $1::text AND status = 'active'
|
|
69
|
+
ORDER BY created_at DESC LIMIT 1`;
|
|
70
|
+
export const FEED_SQL = `
|
|
71
|
+
SELECT b.id, b.code, b.title, b.fulfillment_mode, p.mode, p.target_price_minor,
|
|
72
|
+
p.price_list_id, list.currency
|
|
73
|
+
FROM public.catalog_bundles b
|
|
74
|
+
JOIN public.catalog_bundle_prices p ON p.bundle_id = b.id AND p.active
|
|
75
|
+
JOIN public.price_lists AS list ON list.id = p.price_list_id
|
|
76
|
+
WHERE b.status = 'active' AND ($1::text IS NULL OR list.currency = $1::text)
|
|
77
|
+
ORDER BY b.code, p.valid_from DESC`;
|
|
78
|
+
export const HISTORY_SQL = `
|
|
79
|
+
SELECT id, bundle_code, action, before_state, after_state, created_at
|
|
80
|
+
FROM public.catalog_bundle_write_events
|
|
81
|
+
WHERE bundle_code = $1::text
|
|
82
|
+
ORDER BY created_at DESC LIMIT $2 OFFSET $3`;
|
|
83
|
+
export const HISTORY_COUNT_SQL = `
|
|
84
|
+
SELECT count(*) AS total FROM public.catalog_bundle_write_events WHERE bundle_code = $1::text`;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The semantic READ port for bundles.
|
|
3
|
+
*
|
|
4
|
+
* This file names the CAPABILITY, never the storage: no table, no routine, no
|
|
5
|
+
* data-client type and no vendor appears here, and the domain layer opens no
|
|
6
|
+
* database handle of its own. Both shipped read adapters implement exactly this
|
|
7
|
+
* interface and are proved against ONE shared scenario table, so a caller cannot
|
|
8
|
+
* tell them apart. It is the same shape the write port
|
|
9
|
+
* (`adminBundleWritePort.ts`) established in the previous wave.
|
|
10
|
+
*
|
|
11
|
+
* Reads are plain SELECTs rather than security-definer routines: the write
|
|
12
|
+
* boundary is where authority lives, and a read that re-implemented it would be a
|
|
13
|
+
* second place for the same rules to be written down. The admin surface reads the
|
|
14
|
+
* whole lifecycle (draft, active, archived); the sellable feed asks a separate
|
|
15
|
+
* question and gets only what is live.
|
|
16
|
+
*
|
|
17
|
+
* COMPONENT PRICES ARE RESOLVED, NOT STORED. A bundle stores one target price for
|
|
18
|
+
* the whole set; a component's REFERENCE unit price is whatever the selected
|
|
19
|
+
* price list says today. The adapters therefore join the catalogue and the price
|
|
20
|
+
* list themselves, and hand back a resolved figure (or `null` when the list
|
|
21
|
+
* prices nothing for that unit) so the allocator upstream never re-reads storage.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* A read that FAILED, as opposed to a read that found nothing.
|
|
25
|
+
*
|
|
26
|
+
* Both adapters raise this rather than returning an empty page, because the two
|
|
27
|
+
* outcomes are opposite: an empty catalogue is a fact a storefront may cache and
|
|
28
|
+
* show, and a failed query is not. The class lives on the port so neither chain
|
|
29
|
+
* owns the distinction.
|
|
30
|
+
*/
|
|
31
|
+
export declare class BundleCatalogReadError extends Error {
|
|
32
|
+
constructor(message: string);
|
|
33
|
+
}
|
|
34
|
+
/** Which lifecycle rows an admin list asks for. `all` is the admin default. */
|
|
35
|
+
export type BundleListStatusFilter = "draft" | "active" | "archived" | "all";
|
|
36
|
+
export interface ListBundlesInput {
|
|
37
|
+
status: BundleListStatusFilter;
|
|
38
|
+
/** Free-text match over code and title; absent means no narrowing. */
|
|
39
|
+
query?: string;
|
|
40
|
+
limit: number;
|
|
41
|
+
offset: number;
|
|
42
|
+
}
|
|
43
|
+
export interface BundleSummary {
|
|
44
|
+
code: string;
|
|
45
|
+
title: string;
|
|
46
|
+
status: string;
|
|
47
|
+
fulfillmentMode: string;
|
|
48
|
+
componentCount: number;
|
|
49
|
+
hasActiveTargetPrice: boolean;
|
|
50
|
+
updatedAt: string;
|
|
51
|
+
}
|
|
52
|
+
export interface ListBundlesResult {
|
|
53
|
+
bundles: BundleSummary[];
|
|
54
|
+
total: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One line of the bill of materials, already joined to the catalogue.
|
|
58
|
+
*
|
|
59
|
+
* `productSlug` and `variantId` are carried because the availability port
|
|
60
|
+
* addresses stock by all three coordinates; a caller that had only the sku would
|
|
61
|
+
* have to re-open the catalogue to ask about stock, which is exactly the
|
|
62
|
+
* round-trip this DTO exists to remove.
|
|
63
|
+
*/
|
|
64
|
+
export interface BundleComponentRow {
|
|
65
|
+
sku: string;
|
|
66
|
+
title: string | null;
|
|
67
|
+
productSlug: string;
|
|
68
|
+
variantId: string;
|
|
69
|
+
quantity: number;
|
|
70
|
+
isAddon: boolean;
|
|
71
|
+
sortOrder: number;
|
|
72
|
+
/** Resolved from the selected price list; `null` when it prices no such unit. */
|
|
73
|
+
referenceUnitPriceMinor: number | null;
|
|
74
|
+
}
|
|
75
|
+
export interface BundleTargetPriceRow {
|
|
76
|
+
mode: string;
|
|
77
|
+
targetPriceMinor: number;
|
|
78
|
+
currency: string;
|
|
79
|
+
amountKind: string;
|
|
80
|
+
active: boolean;
|
|
81
|
+
validFrom: string;
|
|
82
|
+
validTo: string | null;
|
|
83
|
+
}
|
|
84
|
+
export interface BundleDetail extends BundleSummary {
|
|
85
|
+
/** The opaque `{kind, version, data}` envelope; `null` for an unconstrained bundle. */
|
|
86
|
+
compositionConstraint: {
|
|
87
|
+
kind: string;
|
|
88
|
+
version: number;
|
|
89
|
+
data: Record<string, unknown>;
|
|
90
|
+
} | null;
|
|
91
|
+
metadata: Record<string, unknown>;
|
|
92
|
+
components: BundleComponentRow[];
|
|
93
|
+
prices: BundleTargetPriceRow[];
|
|
94
|
+
/** The currency whose list resolved `referenceUnitPriceMinor`; `null` if none did. */
|
|
95
|
+
resolvedCurrency: string | null;
|
|
96
|
+
/**
|
|
97
|
+
* The price list those reference figures came from. Carried because a price
|
|
98
|
+
* preview has to name the list it priced against — an amount without the list
|
|
99
|
+
* that gave it meaning is not reproducible.
|
|
100
|
+
*/
|
|
101
|
+
resolvedPriceListId: string | null;
|
|
102
|
+
}
|
|
103
|
+
export interface GetBundleInput {
|
|
104
|
+
code: string;
|
|
105
|
+
/**
|
|
106
|
+
* Price the components against THIS currency's active list. Omitted means "the
|
|
107
|
+
* list this bundle's own active target price is written into", which is the
|
|
108
|
+
* only currency an operator has actually chosen for it.
|
|
109
|
+
*/
|
|
110
|
+
currency?: string;
|
|
111
|
+
/** Narrow the target price whose list is selected; omitted means any mode. */
|
|
112
|
+
mode?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* One live, sellable bundle: active status, an active target price, and its
|
|
116
|
+
* components priced in that price's own currency. This is the feed's row, and it
|
|
117
|
+
* is deliberately a different question from `getBundle` — the storefront must
|
|
118
|
+
* never be able to see a draft by asking the read port nicely.
|
|
119
|
+
*/
|
|
120
|
+
export interface ActiveBundleComposition {
|
|
121
|
+
code: string;
|
|
122
|
+
title: string;
|
|
123
|
+
fulfillmentMode: string;
|
|
124
|
+
currency: string;
|
|
125
|
+
targetPriceMinor: number;
|
|
126
|
+
mode: string;
|
|
127
|
+
components: BundleComponentRow[];
|
|
128
|
+
}
|
|
129
|
+
export interface BundleHistoryEvent {
|
|
130
|
+
id: string;
|
|
131
|
+
action: string;
|
|
132
|
+
actorKind: string | null;
|
|
133
|
+
actorEmail: string | null;
|
|
134
|
+
entityId: string | null;
|
|
135
|
+
oldValue: unknown;
|
|
136
|
+
newValue: unknown;
|
|
137
|
+
occurredAt: string;
|
|
138
|
+
}
|
|
139
|
+
export interface BundleHistoryInput {
|
|
140
|
+
code: string;
|
|
141
|
+
limit: number;
|
|
142
|
+
offset: number;
|
|
143
|
+
}
|
|
144
|
+
export interface BundleHistoryResult {
|
|
145
|
+
events: BundleHistoryEvent[];
|
|
146
|
+
total: number;
|
|
147
|
+
}
|
|
148
|
+
export interface BundleCatalogReadPort {
|
|
149
|
+
/** Admin list across the whole lifecycle, newest-agnostic and code-ordered. */
|
|
150
|
+
listBundles(input: ListBundlesInput): Promise<ListBundlesResult>;
|
|
151
|
+
/** Full admin detail, or `null` when no bundle carries that code. */
|
|
152
|
+
getBundle(input: GetBundleInput): Promise<BundleDetail | null>;
|
|
153
|
+
/**
|
|
154
|
+
* Every bundle a storefront may sell right now. Never returns a draft or an
|
|
155
|
+
* archived bundle, and never a bundle without an active target price.
|
|
156
|
+
*/
|
|
157
|
+
listActiveBundleCompositions(input?: {
|
|
158
|
+
currency?: string;
|
|
159
|
+
}): Promise<ActiveBundleComposition[]>;
|
|
160
|
+
/**
|
|
161
|
+
* The operator trail for one bundle. The two chains answer from different
|
|
162
|
+
* ledgers — a managed audit table and the platform's neutral write-event
|
|
163
|
+
* relation — which is why this is a port method rather than a shared query.
|
|
164
|
+
*/
|
|
165
|
+
listBundleHistory(input: BundleHistoryInput): Promise<BundleHistoryResult>;
|
|
166
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The semantic READ port for bundles.
|
|
3
|
+
*
|
|
4
|
+
* This file names the CAPABILITY, never the storage: no table, no routine, no
|
|
5
|
+
* data-client type and no vendor appears here, and the domain layer opens no
|
|
6
|
+
* database handle of its own. Both shipped read adapters implement exactly this
|
|
7
|
+
* interface and are proved against ONE shared scenario table, so a caller cannot
|
|
8
|
+
* tell them apart. It is the same shape the write port
|
|
9
|
+
* (`adminBundleWritePort.ts`) established in the previous wave.
|
|
10
|
+
*
|
|
11
|
+
* Reads are plain SELECTs rather than security-definer routines: the write
|
|
12
|
+
* boundary is where authority lives, and a read that re-implemented it would be a
|
|
13
|
+
* second place for the same rules to be written down. The admin surface reads the
|
|
14
|
+
* whole lifecycle (draft, active, archived); the sellable feed asks a separate
|
|
15
|
+
* question and gets only what is live.
|
|
16
|
+
*
|
|
17
|
+
* COMPONENT PRICES ARE RESOLVED, NOT STORED. A bundle stores one target price for
|
|
18
|
+
* the whole set; a component's REFERENCE unit price is whatever the selected
|
|
19
|
+
* price list says today. The adapters therefore join the catalogue and the price
|
|
20
|
+
* list themselves, and hand back a resolved figure (or `null` when the list
|
|
21
|
+
* prices nothing for that unit) so the allocator upstream never re-reads storage.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* A read that FAILED, as opposed to a read that found nothing.
|
|
25
|
+
*
|
|
26
|
+
* Both adapters raise this rather than returning an empty page, because the two
|
|
27
|
+
* outcomes are opposite: an empty catalogue is a fact a storefront may cache and
|
|
28
|
+
* show, and a failed query is not. The class lives on the port so neither chain
|
|
29
|
+
* owns the distinction.
|
|
30
|
+
*/
|
|
31
|
+
export class BundleCatalogReadError extends Error {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "BundleCatalogReadError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { BundleCatalogReadError, } from "./bundleCatalogReadPort.js";
|
|
2
|
+
import { LIST_SQL, COUNT_SQL, DETAIL_SQL, COMPONENT_SQL, FEED_COMPONENT_SQL, PRICE_SQL, OWN_LIST_SQL, CURRENCY_LIST_SQL, FEED_SQL, HISTORY_SQL, HISTORY_COUNT_SQL, } from "./bundleCatalogQueries.js";
|
|
3
|
+
export function createPostgresBundleCatalogStore(executor) {
|
|
4
|
+
async function rows(sql, values) {
|
|
5
|
+
// A driver failure becomes the port's own read error, so a caller sees the
|
|
6
|
+
// same distinction between "found nothing" and "could not ask" on both chains.
|
|
7
|
+
const result = await executor.query(sql, values).catch((error) => {
|
|
8
|
+
throw new BundleCatalogReadError(error instanceof Error ? error.message : String(error));
|
|
9
|
+
});
|
|
10
|
+
return (result.rows ?? []);
|
|
11
|
+
}
|
|
12
|
+
async function components(bundleId, priceListId) {
|
|
13
|
+
return (await rows(COMPONENT_SQL, [bundleId, priceListId])).map(toComponent);
|
|
14
|
+
}
|
|
15
|
+
async function selectPriceList(bundleId, input) {
|
|
16
|
+
const list = input.currency
|
|
17
|
+
? await rows(CURRENCY_LIST_SQL, [input.currency])
|
|
18
|
+
: await rows(OWN_LIST_SQL, [bundleId, input.mode ?? null]);
|
|
19
|
+
return list[0] ?? null;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
async listBundles(input) {
|
|
23
|
+
const filter = [input.status, input.query ?? null];
|
|
24
|
+
const [page, counted] = await Promise.all([
|
|
25
|
+
rows(LIST_SQL, [...filter, input.limit, input.offset]),
|
|
26
|
+
rows(COUNT_SQL, filter),
|
|
27
|
+
]);
|
|
28
|
+
return { bundles: page.map(toSummary), total: Number(counted[0]?.total ?? page.length) };
|
|
29
|
+
},
|
|
30
|
+
async getBundle(input) {
|
|
31
|
+
const bundle = (await rows(DETAIL_SQL, [input.code]))[0];
|
|
32
|
+
if (!bundle)
|
|
33
|
+
return null;
|
|
34
|
+
const list = await selectPriceList(bundle.id, input);
|
|
35
|
+
const [componentRows, priceRows] = await Promise.all([
|
|
36
|
+
components(bundle.id, list?.id ?? null),
|
|
37
|
+
rows(PRICE_SQL, [bundle.id]),
|
|
38
|
+
]);
|
|
39
|
+
return {
|
|
40
|
+
...toSummary(bundle),
|
|
41
|
+
compositionConstraint: toConstraint(bundle.composition_constraint),
|
|
42
|
+
metadata: bundle.metadata ?? {},
|
|
43
|
+
components: componentRows,
|
|
44
|
+
prices: priceRows.map(toPrice),
|
|
45
|
+
resolvedCurrency: list?.currency ?? null,
|
|
46
|
+
resolvedPriceListId: list?.id ?? null,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
async listActiveBundleCompositions(input = {}) {
|
|
50
|
+
// A bundle may carry several active prices (a scheduled successor); the feed
|
|
51
|
+
// takes the newest window per bundle, which is what the ORDER BY already put first.
|
|
52
|
+
const selected = new Map();
|
|
53
|
+
for (const row of await rows(FEED_SQL, [input.currency ?? null])) {
|
|
54
|
+
if (!selected.has(row.id))
|
|
55
|
+
selected.set(row.id, row);
|
|
56
|
+
}
|
|
57
|
+
if (selected.size === 0)
|
|
58
|
+
return [];
|
|
59
|
+
const chosen = [...selected.values()];
|
|
60
|
+
const byBundle = groupComponents(await rows(FEED_COMPONENT_SQL, [
|
|
61
|
+
chosen.map((row) => row.id),
|
|
62
|
+
chosen.map((row) => row.price_list_id),
|
|
63
|
+
]));
|
|
64
|
+
return chosen.map((row) => ({
|
|
65
|
+
code: row.code,
|
|
66
|
+
title: row.title,
|
|
67
|
+
fulfillmentMode: row.fulfillment_mode,
|
|
68
|
+
currency: row.currency,
|
|
69
|
+
targetPriceMinor: row.target_price_minor,
|
|
70
|
+
mode: row.mode,
|
|
71
|
+
components: byBundle.get(row.id) ?? [],
|
|
72
|
+
}));
|
|
73
|
+
},
|
|
74
|
+
async listBundleHistory(input) {
|
|
75
|
+
const [page, counted] = await Promise.all([
|
|
76
|
+
rows(HISTORY_SQL, [input.code, input.limit, input.offset]),
|
|
77
|
+
rows(HISTORY_COUNT_SQL, [input.code]),
|
|
78
|
+
]);
|
|
79
|
+
return {
|
|
80
|
+
// This chain has no operator registry, so it can record WHICH principal
|
|
81
|
+
// wrote but never what kind of actor it was; both fields stay null rather
|
|
82
|
+
// than being invented from the principal id.
|
|
83
|
+
events: page.map((row) => ({
|
|
84
|
+
id: row.id,
|
|
85
|
+
action: row.action,
|
|
86
|
+
actorKind: null,
|
|
87
|
+
actorEmail: null,
|
|
88
|
+
entityId: row.bundle_code,
|
|
89
|
+
oldValue: row.before_state ?? null,
|
|
90
|
+
newValue: row.after_state ?? null,
|
|
91
|
+
occurredAt: row.created_at,
|
|
92
|
+
})),
|
|
93
|
+
total: Number(counted[0]?.total ?? page.length),
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function groupComponents(rows) {
|
|
99
|
+
const grouped = new Map();
|
|
100
|
+
for (const row of rows) {
|
|
101
|
+
const bucket = grouped.get(row.bundle_id) ?? [];
|
|
102
|
+
bucket.push(toComponent(row));
|
|
103
|
+
grouped.set(row.bundle_id, bucket);
|
|
104
|
+
}
|
|
105
|
+
return grouped;
|
|
106
|
+
}
|
|
107
|
+
function toComponent(row) {
|
|
108
|
+
return {
|
|
109
|
+
sku: row.sku,
|
|
110
|
+
title: row.title ?? null,
|
|
111
|
+
productSlug: row.product_slug,
|
|
112
|
+
variantId: row.variant_id,
|
|
113
|
+
quantity: Number(row.quantity),
|
|
114
|
+
isAddon: row.is_addon === true,
|
|
115
|
+
sortOrder: Number(row.sort_order),
|
|
116
|
+
referenceUnitPriceMinor: row.reference_unit_price_minor === null || row.reference_unit_price_minor === undefined
|
|
117
|
+
? null
|
|
118
|
+
: Number(row.reference_unit_price_minor),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function toSummary(row) {
|
|
122
|
+
return {
|
|
123
|
+
code: row.code,
|
|
124
|
+
title: row.title,
|
|
125
|
+
status: row.status,
|
|
126
|
+
fulfillmentMode: row.fulfillment_mode,
|
|
127
|
+
componentCount: Number(row.component_count ?? 0),
|
|
128
|
+
hasActiveTargetPrice: row.has_active_target_price === true,
|
|
129
|
+
updatedAt: row.updated_at,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function toPrice(row) {
|
|
133
|
+
return {
|
|
134
|
+
mode: row.mode,
|
|
135
|
+
targetPriceMinor: Number(row.target_price_minor),
|
|
136
|
+
currency: row.currency,
|
|
137
|
+
amountKind: row.amount_kind,
|
|
138
|
+
active: row.active === true,
|
|
139
|
+
validFrom: row.valid_from,
|
|
140
|
+
validTo: row.valid_to ?? null,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** An empty envelope is stored as `{}`; that is "unconstrained", not a constraint. */
|
|
144
|
+
function toConstraint(value) {
|
|
145
|
+
if (!value || typeof value.kind !== "string" || value.kind.trim() === "")
|
|
146
|
+
return null;
|
|
147
|
+
return {
|
|
148
|
+
kind: value.kind,
|
|
149
|
+
version: typeof value.version === "number" ? value.version : 0,
|
|
150
|
+
data: (value.data ?? {}),
|
|
151
|
+
};
|
|
152
|
+
}
|