@openlup/platform 0.20.0 → 0.22.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 +272 -278
- package/README.md +195 -6
- package/dist/composition/composeBundle.d.ts +13 -0
- package/dist/composition/composeBundle.js +4 -0
- package/dist/composition/fulfillmentContribution.d.ts +21 -0
- package/dist/composition/fulfillmentContribution.js +19 -0
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +2 -0
- package/dist/fulfillment/adapterConformance.d.ts +3 -0
- package/dist/fulfillment/adapterConformance.js +223 -0
- package/dist/fulfillment/bindings.d.ts +3 -0
- package/dist/fulfillment/bindings.js +29 -0
- package/dist/fulfillment/commerceFulfillmentHandlers.d.ts +29 -0
- package/dist/fulfillment/commerceFulfillmentHandlers.js +184 -0
- package/dist/fulfillment/commerceFulfillmentReadModel.d.ts +86 -0
- package/dist/fulfillment/commerceFulfillmentReadModel.js +131 -0
- package/dist/fulfillment/contracts/alignment.d.ts +25 -0
- package/dist/fulfillment/contracts/alignment.js +1 -0
- package/dist/fulfillment/contracts/bindings.d.ts +51 -0
- package/dist/fulfillment/contracts/bindings.js +1 -0
- package/dist/fulfillment/contracts/capabilities.d.ts +29 -0
- package/dist/fulfillment/contracts/capabilities.js +1 -0
- package/dist/fulfillment/contracts/conformance.d.ts +93 -0
- package/dist/fulfillment/contracts/conformance.js +1 -0
- package/dist/fulfillment/contracts/customerAlignment.d.ts +6 -0
- package/dist/fulfillment/contracts/customerAlignment.js +1 -0
- package/dist/fulfillment/contracts/dispatch.d.ts +105 -0
- package/dist/fulfillment/contracts/dispatch.js +1 -0
- package/dist/fulfillment/contracts/index.d.ts +18 -0
- package/dist/fulfillment/contracts/index.js +1 -0
- package/dist/fulfillment/contracts/label.d.ts +35 -0
- package/dist/fulfillment/contracts/label.js +1 -0
- package/dist/fulfillment/contracts/nativeUnsupported.d.ts +6 -0
- package/dist/fulfillment/contracts/nativeUnsupported.js +1 -0
- package/dist/fulfillment/contracts/observation.d.ts +52 -0
- package/dist/fulfillment/contracts/observation.js +1 -0
- package/dist/fulfillment/contracts/operator.d.ts +64 -0
- package/dist/fulfillment/contracts/operator.js +1 -0
- package/dist/fulfillment/contracts/read.d.ts +110 -0
- package/dist/fulfillment/contracts/read.js +1 -0
- package/dist/fulfillment/contracts/readback.d.ts +38 -0
- package/dist/fulfillment/contracts/readback.js +1 -0
- package/dist/fulfillment/contracts/replacement.d.ts +34 -0
- package/dist/fulfillment/contracts/replacement.js +1 -0
- package/dist/fulfillment/contracts/store.d.ts +86 -0
- package/dist/fulfillment/contracts/store.js +1 -0
- package/dist/fulfillment/contracts/sync.d.ts +170 -0
- package/dist/fulfillment/contracts/sync.js +1 -0
- package/dist/fulfillment/currentFulfillmentParcel.d.ts +2 -0
- package/dist/fulfillment/currentFulfillmentParcel.js +1 -0
- package/dist/fulfillment/delayReadModel.d.ts +11 -0
- package/dist/fulfillment/delayReadModel.js +45 -0
- package/dist/fulfillment/deliveryAlignmentReadModel.d.ts +4 -0
- package/dist/fulfillment/deliveryAlignmentReadModel.js +12 -0
- package/dist/fulfillment/dispatchProjection.d.ts +7 -0
- package/dist/fulfillment/dispatchProjection.js +18 -0
- package/dist/fulfillment/fulfillmentObservationEffects.d.ts +66 -0
- package/dist/fulfillment/fulfillmentObservationEffects.js +36 -0
- package/dist/fulfillment/handlerSchemas.d.ts +647 -0
- package/dist/fulfillment/handlerSchemas.js +213 -0
- package/dist/fulfillment/handlerSupport.d.ts +33 -0
- package/dist/fulfillment/handlerSupport.js +25 -0
- package/dist/fulfillment/index.d.ts +37 -0
- package/dist/fulfillment/index.js +37 -0
- package/dist/fulfillment/labelLifecycle.d.ts +24 -0
- package/dist/fulfillment/labelLifecycle.js +9 -0
- package/dist/fulfillment/lowStockEvidenceHandler.d.ts +36 -0
- package/dist/fulfillment/lowStockEvidenceHandler.js +46 -0
- package/dist/fulfillment/migrations.d.ts +27 -0
- package/dist/fulfillment/migrations.js +8 -0
- package/dist/fulfillment/nativeUnsupported.d.ts +10 -0
- package/dist/fulfillment/nativeUnsupported.js +18 -0
- package/dist/fulfillment/normalizedFulfillmentFacts.d.ts +2 -0
- package/dist/fulfillment/normalizedFulfillmentFacts.js +1 -0
- package/dist/fulfillment/observationProjection.d.ts +11 -0
- package/dist/fulfillment/observationProjection.js +37 -0
- package/dist/fulfillment/omnipack/capabilities.d.ts +3 -0
- package/dist/fulfillment/omnipack/capabilities.js +16 -0
- package/dist/fulfillment/omnipack/client.d.ts +37 -0
- package/dist/fulfillment/omnipack/client.js +162 -0
- package/dist/fulfillment/omnipack/index.d.ts +52 -0
- package/dist/fulfillment/omnipack/index.js +349 -0
- package/dist/fulfillment/omnipack/mappers.d.ts +73 -0
- package/dist/fulfillment/omnipack/mappers.js +177 -0
- package/dist/fulfillment/omnipack/observation.d.ts +21 -0
- package/dist/fulfillment/omnipack/observation.js +57 -0
- package/dist/fulfillment/omnipack/omnipackDispatchPayload.d.ts +36 -0
- package/dist/fulfillment/omnipack/omnipackDispatchPayload.js +63 -0
- package/dist/fulfillment/omnipack/omnipackOutboundOrderPayload.d.ts +83 -0
- package/dist/fulfillment/omnipack/omnipackOutboundOrderPayload.js +113 -0
- package/dist/fulfillment/omnipack/omnipackProductPackPayload.d.ts +11 -0
- package/dist/fulfillment/omnipack/omnipackProductPackPayload.js +38 -0
- package/dist/fulfillment/omnipack/omnipackProductPayload.d.ts +18 -0
- package/dist/fulfillment/omnipack/omnipackProductPayload.js +51 -0
- package/dist/fulfillment/omnipack/omnipackReconciliationPayload.d.ts +1 -0
- package/dist/fulfillment/omnipack/omnipackReconciliationPayload.js +3 -0
- package/dist/fulfillment/omnipack/omnipackStatusVocabulary.d.ts +4 -0
- package/dist/fulfillment/omnipack/omnipackStatusVocabulary.js +87 -0
- package/dist/fulfillment/omnipack/omnipackWebhookPayload.d.ts +9 -0
- package/dist/fulfillment/omnipack/omnipackWebhookPayload.js +76 -0
- package/dist/fulfillment/omnipack/productSyncMappers.d.ts +18 -0
- package/dist/fulfillment/omnipack/productSyncMappers.js +43 -0
- package/dist/fulfillment/omnipack/providerError.d.ts +25 -0
- package/dist/fulfillment/omnipack/providerError.js +47 -0
- package/dist/fulfillment/omnipack/trackingReferences.d.ts +16 -0
- package/dist/fulfillment/omnipack/trackingReferences.js +52 -0
- package/dist/fulfillment/paidFulfillmentRecovery.d.ts +67 -0
- package/dist/fulfillment/paidFulfillmentRecovery.js +154 -0
- package/dist/fulfillment/paidHandoff.d.ts +27 -0
- package/dist/fulfillment/paidHandoff.js +86 -0
- package/dist/fulfillment/paidHandoffPorts.d.ts +24 -0
- package/dist/fulfillment/paidHandoffPorts.js +3 -0
- package/dist/fulfillment/postgresDeliveryAlignment.d.ts +4 -0
- package/dist/fulfillment/postgresDeliveryAlignment.js +12 -0
- package/dist/fulfillment/postgresDispatchStore.d.ts +16 -0
- package/dist/fulfillment/postgresDispatchStore.js +44 -0
- package/dist/fulfillment/postgresEvidenceReadPort.d.ts +25 -0
- package/dist/fulfillment/postgresEvidenceReadPort.js +45 -0
- package/dist/fulfillment/postgresPaidFulfillmentRecovery.d.ts +25 -0
- package/dist/fulfillment/postgresPaidFulfillmentRecovery.js +26 -0
- package/dist/fulfillment/postgresPaidHandoffStore.d.ts +4 -0
- package/dist/fulfillment/postgresPaidHandoffStore.js +10 -0
- package/dist/fulfillment/postgresShipmentSpine.d.ts +63 -0
- package/dist/fulfillment/postgresShipmentSpine.js +232 -0
- package/dist/fulfillment/postgresStockSyncPort.d.ts +8 -0
- package/dist/fulfillment/postgresStockSyncPort.js +63 -0
- package/dist/fulfillment/productReconciliationEvidenceHandler.d.ts +36 -0
- package/dist/fulfillment/productReconciliationEvidenceHandler.js +50 -0
- package/dist/fulfillment/providerCapabilities.d.ts +9 -0
- package/dist/fulfillment/providerCapabilities.js +17 -0
- package/dist/fulfillment/providerCommandLedger.d.ts +143 -0
- package/dist/fulfillment/providerCommandLedger.js +14 -0
- package/dist/fulfillment/providerDispatchAcceptance.d.ts +26 -0
- package/dist/fulfillment/providerDispatchAcceptance.js +23 -0
- package/dist/fulfillment/providerDispatchError.d.ts +6 -0
- package/dist/fulfillment/providerDispatchError.js +5 -0
- package/dist/fulfillment/providerDispatchWorker.d.ts +31 -0
- package/dist/fulfillment/providerDispatchWorker.js +172 -0
- package/dist/fulfillment/providerProductSyncWorker.d.ts +28 -0
- package/dist/fulfillment/providerProductSyncWorker.js +122 -0
- package/dist/fulfillment/providerReconciliationError.d.ts +9 -0
- package/dist/fulfillment/providerReconciliationError.js +17 -0
- package/dist/fulfillment/providerReconciliationTerminalSkip.d.ts +2 -0
- package/dist/fulfillment/providerReconciliationTerminalSkip.js +6 -0
- package/dist/fulfillment/providerReconciliationTimestamp.d.ts +1 -0
- package/dist/fulfillment/providerReconciliationTimestamp.js +27 -0
- package/dist/fulfillment/providerReconciliationWorker.d.ts +82 -0
- package/dist/fulfillment/providerReconciliationWorker.js +151 -0
- package/dist/fulfillment/providerStockAvailability.d.ts +13 -0
- package/dist/fulfillment/providerStockAvailability.js +51 -0
- package/dist/fulfillment/providerStockSyncWorker.d.ts +37 -0
- package/dist/fulfillment/providerStockSyncWorker.js +186 -0
- package/dist/fulfillment/providerTrackingReferences.d.ts +15 -0
- package/dist/fulfillment/providerTrackingReferences.js +23 -0
- package/dist/fulfillment/replacementRefusals.d.ts +5 -0
- package/dist/fulfillment/replacementRefusals.js +38 -0
- package/dist/fulfillment/replacementShipmentHandler.d.ts +5 -0
- package/dist/fulfillment/replacementShipmentHandler.js +46 -0
- package/dist/fulfillment/schemaCapabilities.d.ts +13 -0
- package/dist/fulfillment/schemaCapabilities.js +7 -0
- package/dist/fulfillment/shipmentsOverviewHandler.d.ts +16 -0
- package/dist/fulfillment/shipmentsOverviewHandler.js +54 -0
- package/dist/fulfillment/statusMap.d.ts +2 -0
- package/dist/fulfillment/statusMap.js +1 -0
- package/dist/fulfillment/trackingProgress.d.ts +1 -0
- package/dist/fulfillment/trackingProgress.js +1 -0
- package/dist/fulfillment/verifiedIngress.d.ts +52 -0
- package/dist/fulfillment/verifiedIngress.js +66 -0
- package/dist/payments/adapterConformance.d.ts +8 -0
- package/dist/payments/adapterConformance.js +109 -0
- package/dist/payments/bindings.d.ts +3 -0
- package/dist/payments/bindings.js +17 -0
- package/dist/payments/checkoutActivePaymentActionResolver.d.ts +7 -0
- package/dist/payments/checkoutActivePaymentActionResolver.js +77 -0
- package/dist/payments/checkoutRecoveryPaymentResolver.d.ts +8 -0
- package/dist/payments/checkoutRecoveryPaymentResolver.js +87 -0
- package/dist/payments/contracts/adapter.d.ts +113 -0
- package/dist/payments/contracts/adapter.js +1 -0
- package/dist/payments/contracts/conformance.d.ts +155 -0
- package/dist/payments/contracts/conformance.js +1 -0
- package/dist/payments/contracts/evidence.d.ts +157 -0
- package/dist/payments/contracts/evidence.js +1 -0
- package/dist/payments/contracts/index.d.ts +10 -0
- package/dist/payments/contracts/index.js +1 -0
- package/dist/payments/contracts/preparedAttempt.d.ts +69 -0
- package/dist/payments/contracts/preparedAttempt.js +1 -0
- package/dist/payments/contracts/reconciliation.d.ts +303 -0
- package/dist/payments/contracts/reconciliation.js +1 -0
- package/dist/payments/contracts/repair.d.ts +92 -0
- package/dist/payments/contracts/repair.js +1 -0
- package/dist/payments/contracts/truth.d.ts +92 -0
- package/dist/payments/contracts/truth.js +1 -0
- package/dist/payments/eventConformanceRunner.d.ts +12 -0
- package/dist/payments/eventConformanceRunner.js +125 -0
- package/dist/payments/index.d.ts +16 -0
- package/dist/payments/index.js +16 -0
- package/dist/payments/paymentAttemptSilenceWindow.d.ts +10 -0
- package/dist/payments/paymentAttemptSilenceWindow.js +19 -0
- package/dist/payments/paymentMethodLifecycle.d.ts +11 -0
- package/dist/payments/paymentMethodLifecycle.js +37 -0
- package/dist/payments/paymentProviderReconciliationAbsenceReopen.d.ts +7 -0
- package/dist/payments/paymentProviderReconciliationAbsenceReopen.js +100 -0
- package/dist/payments/paymentProviderReconciliationEvidence.d.ts +36 -0
- package/dist/payments/paymentProviderReconciliationEvidence.js +91 -0
- package/dist/payments/paymentProviderReconciliationWorker.d.ts +4 -0
- package/dist/payments/paymentProviderReconciliationWorker.js +245 -0
- package/dist/payments/paymentTruth.d.ts +8 -0
- package/dist/payments/paymentTruth.js +125 -0
- package/dist/payments/paymentVerifyNowHandler.d.ts +27 -0
- package/dist/payments/paymentVerifyNowHandler.js +70 -0
- package/dist/payments/paymentVerifyNowService.d.ts +23 -0
- package/dist/payments/paymentVerifyNowService.js +93 -0
- package/dist/payments/paymentWebhookPostProcessing.d.ts +22 -0
- package/dist/payments/paymentWebhookPostProcessing.js +15 -0
- package/dist/payments/postgresPaymentTruth.d.ts +10 -0
- package/dist/payments/postgresPaymentTruth.js +126 -0
- package/dist/payments/preparedAttempt.d.ts +6 -0
- package/dist/payments/preparedAttempt.js +70 -0
- package/dist/payments/preparedAttemptFinalization.d.ts +5 -0
- package/dist/payments/preparedAttemptFinalization.js +12 -0
- package/dist/payments/schemaCapabilities.d.ts +10 -0
- package/dist/payments/schemaCapabilities.js +10 -0
- package/dist/payments/sql.d.ts +20 -0
- package/dist/payments/sql.js +6 -0
- package/dist/payments/stripe/classifyDecline.d.ts +46 -0
- package/dist/payments/stripe/classifyDecline.js +58 -0
- package/dist/payments/stripe/declineFailureHints.d.ts +46 -0
- package/dist/payments/stripe/declineFailureHints.js +87 -0
- package/dist/payments/stripe/donorContracts.d.ts +120 -0
- package/dist/payments/stripe/donorContracts.js +1 -0
- package/dist/payments/stripe/executionDecline.d.ts +53 -0
- package/dist/payments/stripe/executionDecline.js +107 -0
- package/dist/payments/stripe/index.d.ts +41 -0
- package/dist/payments/stripe/index.js +264 -0
- package/dist/payments/stripe/intentMapper.d.ts +26 -0
- package/dist/payments/stripe/intentMapper.js +51 -0
- package/dist/payments/stripe/methodFacts.d.ts +10 -0
- package/dist/payments/stripe/methodFacts.js +12 -0
- package/dist/payments/stripe/paymentFailureEvidence.d.ts +26 -0
- package/dist/payments/stripe/paymentFailureEvidence.js +33 -0
- package/dist/payments/stripe/stripeFailureEvidence.d.ts +41 -0
- package/dist/payments/stripe/stripeFailureEvidence.js +82 -0
- package/dist/payments/stripe/stripeIntentConfirmationEvidence.d.ts +28 -0
- package/dist/payments/stripe/stripeIntentConfirmationEvidence.js +32 -0
- package/dist/payments/stripe/stripePaymentReconciliationProvider.d.ts +35 -0
- package/dist/payments/stripe/stripePaymentReconciliationProvider.js +222 -0
- package/dist/payments/stripe/stripeRefundEvidence.d.ts +8 -0
- package/dist/payments/stripe/stripeRefundEvidence.js +17 -0
- package/dist/payments/stripe/stripeSandboxPaymentExecutionAdapter.d.ts +45 -0
- package/dist/payments/stripe/stripeSandboxPaymentExecutionAdapter.js +220 -0
- package/dist/payments/stripe/stripeWebhookNormalizer.d.ts +14 -0
- package/dist/payments/stripe/stripeWebhookNormalizer.js +243 -0
- package/dist/payments/stripe/webhookSignature.d.ts +14 -0
- package/dist/payments/stripe/webhookSignature.js +43 -0
- package/dist/payments/tpay/blikRecurringMapper.d.ts +37 -0
- package/dist/payments/tpay/blikRecurringMapper.js +24 -0
- package/dist/payments/tpay/capabilities.d.ts +3 -0
- package/dist/payments/tpay/capabilities.js +18 -0
- package/dist/payments/tpay/classifyDecline.d.ts +46 -0
- package/dist/payments/tpay/classifyDecline.js +58 -0
- package/dist/payments/tpay/declineFailureHints.d.ts +72 -0
- package/dist/payments/tpay/declineFailureHints.js +37 -0
- package/dist/payments/tpay/donorContracts.d.ts +140 -0
- package/dist/payments/tpay/donorContracts.js +1 -0
- package/dist/payments/tpay/index.d.ts +73 -0
- package/dist/payments/tpay/index.js +294 -0
- package/dist/payments/tpay/paymentFailureEvidence.d.ts +26 -0
- package/dist/payments/tpay/paymentFailureEvidence.js +33 -0
- package/dist/payments/tpay/preparedProviderAttempt.d.ts +22 -0
- package/dist/payments/tpay/preparedProviderAttempt.js +24 -0
- package/dist/payments/tpay/providerAttemptFailureDiagnostic.d.ts +3 -0
- package/dist/payments/tpay/providerAttemptFailureDiagnostic.js +95 -0
- package/dist/payments/tpay/tpayCreateTransactionInput.d.ts +25 -0
- package/dist/payments/tpay/tpayCreateTransactionInput.js +128 -0
- package/dist/payments/tpay/tpayDeclineEvidence.d.ts +126 -0
- package/dist/payments/tpay/tpayDeclineEvidence.js +177 -0
- package/dist/payments/tpay/tpayDispatchFailure.d.ts +60 -0
- package/dist/payments/tpay/tpayDispatchFailure.js +121 -0
- package/dist/payments/tpay/tpayFailureEvidence.d.ts +20 -0
- package/dist/payments/tpay/tpayFailureEvidence.js +61 -0
- package/dist/payments/tpay/tpayHttpClient.d.ts +52 -0
- package/dist/payments/tpay/tpayHttpClient.js +185 -0
- package/dist/payments/tpay/tpayHttpFailure.d.ts +57 -0
- package/dist/payments/tpay/tpayHttpFailure.js +143 -0
- package/dist/payments/tpay/tpayPaymentExecutionAdapter.d.ts +20 -0
- package/dist/payments/tpay/tpayPaymentExecutionAdapter.js +249 -0
- package/dist/payments/tpay/tpayPaymentReconciliationProvider.d.ts +5 -0
- package/dist/payments/tpay/tpayPaymentReconciliationProvider.js +244 -0
- package/dist/payments/tpay/tpayTransactionPayload.d.ts +120 -0
- package/dist/payments/tpay/tpayTransactionPayload.js +96 -0
- package/dist/payments/tpay/wallClockTime.d.ts +31 -0
- package/dist/payments/tpay/wallClockTime.js +57 -0
- package/dist/payments/tpay/webhookJwsVerifier.d.ts +17 -0
- package/dist/payments/tpay/webhookJwsVerifier.js +51 -0
- package/dist/payments/tpay/webhookNormalizer.d.ts +54 -0
- package/dist/payments/tpay/webhookNormalizer.js +200 -0
- package/dist/payments/verifiedEvidenceProjection.d.ts +12 -0
- package/dist/payments/verifiedEvidenceProjection.js +166 -0
- package/dist/payments/verifiedIngress.d.ts +119 -0
- package/dist/payments/verifiedIngress.js +220 -0
- package/package.json +37 -2
- package/release-gates.json +105 -3
- package/sql/20260808210000_fulfillment_shipment_rail.sql +810 -0
- package/sql/20260810180000_payment_settlement_rail.sql +574 -0
- package/sql/20260815150000_payment_truth_reconciliation.sql +479 -0
- package/sql/20260819150000_fulfillment_shipment_sequence.sql +98 -0
- package/sql/20260826100000_late_payment_shifts_the_subscription_cycle.sql +215 -0
- package/sql/20261022080000_fulfillment_command_ledger.sql +786 -0
- package/sql/20261022090000_fulfillment_delivery_alignment.sql +1106 -0
- package/src/composition/composeBundle.ts +13 -0
- package/src/composition/fulfillmentContribution.ts +28 -0
- package/src/composition/index.ts +2 -0
- package/src/fulfillment/adapterConformance.ts +195 -0
- package/src/fulfillment/bindings.ts +26 -0
- package/src/fulfillment/commerceFulfillmentHandlers.ts +263 -0
- package/src/fulfillment/commerceFulfillmentReadModel.ts +257 -0
- package/src/fulfillment/contracts/alignment.ts +13 -0
- package/src/fulfillment/contracts/bindings.ts +30 -0
- package/src/fulfillment/contracts/capabilities.ts +15 -0
- package/src/fulfillment/contracts/conformance.ts +61 -0
- package/src/fulfillment/contracts/customerAlignment.ts +4 -0
- package/src/fulfillment/contracts/dispatch.ts +58 -0
- package/src/fulfillment/contracts/index.ts +18 -0
- package/src/fulfillment/contracts/label.ts +9 -0
- package/src/fulfillment/contracts/nativeUnsupported.ts +6 -0
- package/src/fulfillment/contracts/observation.ts +18 -0
- package/src/fulfillment/contracts/operator.ts +31 -0
- package/src/fulfillment/contracts/read.ts +42 -0
- package/src/fulfillment/contracts/readback.ts +11 -0
- package/src/fulfillment/contracts/replacement.ts +15 -0
- package/src/fulfillment/contracts/store.ts +26 -0
- package/src/fulfillment/contracts/sync.ts +61 -0
- package/src/fulfillment/currentFulfillmentParcel.ts +2 -0
- package/src/fulfillment/delayReadModel.ts +60 -0
- package/src/fulfillment/deliveryAlignmentReadModel.ts +15 -0
- package/src/fulfillment/dispatchProjection.ts +20 -0
- package/src/fulfillment/fulfillmentObservationEffects.ts +86 -0
- package/src/fulfillment/handlerSchemas.ts +255 -0
- package/src/fulfillment/handlerSupport.ts +25 -0
- package/src/fulfillment/index.ts +38 -0
- package/src/fulfillment/labelLifecycle.ts +11 -0
- package/src/fulfillment/lowStockEvidenceHandler.ts +60 -0
- package/src/fulfillment/migrations.ts +8 -0
- package/src/fulfillment/nativeUnsupported.ts +23 -0
- package/src/fulfillment/normalizedFulfillmentFacts.ts +2 -0
- package/src/fulfillment/observationProjection.ts +41 -0
- package/src/fulfillment/omnipack/capabilities.ts +18 -0
- package/src/fulfillment/omnipack/client.ts +258 -0
- package/src/fulfillment/omnipack/index.ts +312 -0
- package/src/fulfillment/omnipack/mappers.ts +261 -0
- package/src/fulfillment/omnipack/observation.ts +61 -0
- package/src/fulfillment/omnipack/omnipackDispatchPayload.ts +93 -0
- package/src/fulfillment/omnipack/omnipackOutboundOrderPayload.ts +194 -0
- package/src/fulfillment/omnipack/omnipackProductPackPayload.ts +47 -0
- package/src/fulfillment/omnipack/omnipackProductPayload.ts +67 -0
- package/src/fulfillment/omnipack/omnipackReconciliationPayload.ts +7 -0
- package/src/fulfillment/omnipack/omnipackStatusVocabulary.ts +103 -0
- package/src/fulfillment/omnipack/omnipackWebhookPayload.ts +73 -0
- package/src/fulfillment/omnipack/productSyncMappers.ts +74 -0
- package/src/fulfillment/omnipack/providerError.ts +64 -0
- package/src/fulfillment/omnipack/trackingReferences.ts +77 -0
- package/src/fulfillment/paidFulfillmentRecovery.ts +252 -0
- package/src/fulfillment/paidHandoff.ts +122 -0
- package/src/fulfillment/paidHandoffPorts.ts +21 -0
- package/src/fulfillment/postgresDeliveryAlignment.ts +14 -0
- package/src/fulfillment/postgresDispatchStore.ts +55 -0
- package/src/fulfillment/postgresEvidenceReadPort.ts +59 -0
- package/src/fulfillment/postgresPaidFulfillmentRecovery.ts +29 -0
- package/src/fulfillment/postgresPaidHandoffStore.ts +11 -0
- package/src/fulfillment/postgresShipmentSpine.ts +321 -0
- package/src/fulfillment/postgresStockSyncPort.ts +65 -0
- package/src/fulfillment/productReconciliationEvidenceHandler.ts +64 -0
- package/src/fulfillment/providerCapabilities.ts +18 -0
- package/src/fulfillment/providerCommandLedger.ts +53 -0
- package/src/fulfillment/providerDispatchAcceptance.ts +31 -0
- package/src/fulfillment/providerDispatchError.ts +7 -0
- package/src/fulfillment/providerDispatchWorker.ts +131 -0
- package/src/fulfillment/providerProductSyncWorker.ts +154 -0
- package/src/fulfillment/providerReconciliationError.ts +20 -0
- package/src/fulfillment/providerReconciliationTerminalSkip.ts +8 -0
- package/src/fulfillment/providerReconciliationTimestamp.ts +34 -0
- package/src/fulfillment/providerReconciliationWorker.ts +150 -0
- package/src/fulfillment/providerStockAvailability.ts +60 -0
- package/src/fulfillment/providerStockSyncWorker.ts +222 -0
- package/src/fulfillment/providerTrackingReferences.ts +31 -0
- package/src/fulfillment/replacementRefusals.ts +43 -0
- package/src/fulfillment/replacementShipmentHandler.ts +47 -0
- package/src/fulfillment/schemaCapabilities.ts +7 -0
- package/src/fulfillment/shipmentsOverviewHandler.ts +73 -0
- package/src/fulfillment/statusMap.ts +2 -0
- package/src/fulfillment/trackingProgress.ts +1 -0
- package/src/fulfillment/verifiedIngress.ts +80 -0
- package/src/payments/adapterConformance.ts +118 -0
- package/src/payments/bindings.ts +17 -0
- package/src/payments/checkoutActivePaymentActionResolver.ts +97 -0
- package/src/payments/checkoutRecoveryPaymentResolver.ts +108 -0
- package/src/payments/contracts/adapter.ts +96 -0
- package/src/payments/contracts/conformance.ts +171 -0
- package/src/payments/contracts/evidence.ts +142 -0
- package/src/payments/contracts/index.ts +54 -0
- package/src/payments/contracts/preparedAttempt.ts +86 -0
- package/src/payments/contracts/reconciliation.ts +296 -0
- package/src/payments/contracts/repair.ts +95 -0
- package/src/payments/contracts/truth.ts +108 -0
- package/src/payments/eventConformanceRunner.ts +149 -0
- package/src/payments/index.ts +21 -0
- package/src/payments/paymentAttemptSilenceWindow.ts +26 -0
- package/src/payments/paymentMethodLifecycle.ts +50 -0
- package/src/payments/paymentProviderReconciliationAbsenceReopen.ts +130 -0
- package/src/payments/paymentProviderReconciliationEvidence.ts +117 -0
- package/src/payments/paymentProviderReconciliationWorker.ts +291 -0
- package/src/payments/paymentTruth.ts +131 -0
- package/src/payments/paymentVerifyNowHandler.ts +94 -0
- package/src/payments/paymentVerifyNowService.ts +125 -0
- package/src/payments/paymentWebhookPostProcessing.ts +36 -0
- package/src/payments/postgresPaymentTruth.ts +149 -0
- package/src/payments/preparedAttempt.ts +90 -0
- package/src/payments/preparedAttemptFinalization.ts +13 -0
- package/src/payments/schemaCapabilities.ts +10 -0
- package/src/payments/sql.ts +6 -0
- package/src/payments/stripe/classifyDecline.ts +62 -0
- package/src/payments/stripe/declineFailureHints.ts +89 -0
- package/src/payments/stripe/donorContracts.ts +87 -0
- package/src/payments/stripe/executionDecline.ts +126 -0
- package/src/payments/stripe/index.ts +265 -0
- package/src/payments/stripe/intentMapper.ts +58 -0
- package/src/payments/stripe/methodFacts.ts +21 -0
- package/src/payments/stripe/paymentFailureEvidence.ts +58 -0
- package/src/payments/stripe/stripeFailureEvidence.ts +115 -0
- package/src/payments/stripe/stripeIntentConfirmationEvidence.ts +34 -0
- package/src/payments/stripe/stripePaymentReconciliationProvider.ts +263 -0
- package/src/payments/stripe/stripeRefundEvidence.ts +19 -0
- package/src/payments/stripe/stripeSandboxPaymentExecutionAdapter.ts +283 -0
- package/src/payments/stripe/stripeWebhookNormalizer.ts +277 -0
- package/src/payments/stripe/webhookSignature.ts +55 -0
- package/src/payments/tpay/blikRecurringMapper.ts +42 -0
- package/src/payments/tpay/capabilities.ts +21 -0
- package/src/payments/tpay/classifyDecline.ts +62 -0
- package/src/payments/tpay/declineFailureHints.ts +90 -0
- package/src/payments/tpay/donorContracts.ts +104 -0
- package/src/payments/tpay/index.ts +293 -0
- package/src/payments/tpay/paymentFailureEvidence.ts +58 -0
- package/src/payments/tpay/preparedProviderAttempt.ts +38 -0
- package/src/payments/tpay/providerAttemptFailureDiagnostic.ts +99 -0
- package/src/payments/tpay/tpayCreateTransactionInput.ts +158 -0
- package/src/payments/tpay/tpayDeclineEvidence.ts +233 -0
- package/src/payments/tpay/tpayDispatchFailure.ts +186 -0
- package/src/payments/tpay/tpayFailureEvidence.ts +75 -0
- package/src/payments/tpay/tpayHttpClient.ts +290 -0
- package/src/payments/tpay/tpayHttpFailure.ts +186 -0
- package/src/payments/tpay/tpayPaymentExecutionAdapter.ts +297 -0
- package/src/payments/tpay/tpayPaymentReconciliationProvider.ts +285 -0
- package/src/payments/tpay/tpayTransactionPayload.ts +207 -0
- package/src/payments/tpay/wallClockTime.ts +57 -0
- package/src/payments/tpay/webhookJwsVerifier.ts +82 -0
- package/src/payments/tpay/webhookNormalizer.ts +279 -0
- package/src/payments/verifiedEvidenceProjection.ts +179 -0
- package/src/payments/verifiedIngress.ts +317 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Pure builder for the OmniPack product-registration request (catalog load). Mirrors the
|
|
2
|
+
// outbound-order payload convention (pure module in server/_lib, wired through the client).
|
|
3
|
+
// The exact OmniPack request key names live behind the constants below so finalizing them
|
|
4
|
+
// against the (auth-gated) OmniPack product API docs is a one-line edit.
|
|
5
|
+
|
|
6
|
+
// Product-registration request key names (confirm against the OmniPack product API docs).
|
|
7
|
+
const KEY_SKU = "sku";
|
|
8
|
+
const KEY_EAN = "ean";
|
|
9
|
+
const KEY_GROUP = "group";
|
|
10
|
+
const KEY_NAME = "name";
|
|
11
|
+
const KEY_DIMENSIONS = "dimensions";
|
|
12
|
+
|
|
13
|
+
export interface OmnipackProductPack {
|
|
14
|
+
weightGrams: number;
|
|
15
|
+
lengthMm: number;
|
|
16
|
+
widthMm: number;
|
|
17
|
+
heightMm: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface OmnipackProductInput {
|
|
21
|
+
sku: string;
|
|
22
|
+
ean: string | null;
|
|
23
|
+
productGroup: string;
|
|
24
|
+
title: string;
|
|
25
|
+
pack: OmnipackProductPack | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class OmnipackProductPayloadError extends Error {
|
|
29
|
+
constructor(readonly code: string) {
|
|
30
|
+
super(`omnipack_product_payload_invalid: ${code}`);
|
|
31
|
+
this.name = "OmnipackProductPayloadError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function requireNonEmpty(value: string | null | undefined, code: string): string {
|
|
36
|
+
const trimmed = value?.trim();
|
|
37
|
+
if (!trimmed) throw new OmnipackProductPayloadError(code);
|
|
38
|
+
return trimmed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function requirePositive(value: number, code: string): number {
|
|
42
|
+
if (!Number.isFinite(value) || value <= 0) throw new OmnipackProductPayloadError(code);
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Builds the product-registration payload. EAN, group, title and a full pack are required —
|
|
47
|
+
// OmniPack matches physical goods by EAN and a batch-tracked group needs known dimensions.
|
|
48
|
+
export function buildOmnipackProductPayload(input: OmnipackProductInput): Record<string, unknown> {
|
|
49
|
+
const sku = requireNonEmpty(input.sku, "missing_sku");
|
|
50
|
+
const ean = requireNonEmpty(input.ean, "missing_ean");
|
|
51
|
+
const group = requireNonEmpty(input.productGroup, "missing_product_group");
|
|
52
|
+
const name = requireNonEmpty(input.title, "missing_title");
|
|
53
|
+
if (!input.pack) throw new OmnipackProductPayloadError("missing_pack");
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
[KEY_SKU]: sku,
|
|
57
|
+
[KEY_EAN]: ean,
|
|
58
|
+
[KEY_GROUP]: group,
|
|
59
|
+
[KEY_NAME]: name,
|
|
60
|
+
[KEY_DIMENSIONS]: {
|
|
61
|
+
weight: requirePositive(input.pack.weightGrams, "invalid_pack_weight"),
|
|
62
|
+
length: requirePositive(input.pack.lengthMm, "invalid_pack_length"),
|
|
63
|
+
width: requirePositive(input.pack.widthMm, "invalid_pack_width"),
|
|
64
|
+
height: requirePositive(input.pack.heightMm, "invalid_pack_height"),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Provider status translation only; lifecycle effects remain host-owned.
|
|
2
|
+
export type NormalizedProviderStatus =
|
|
3
|
+
| "new"
|
|
4
|
+
| "in_fulfillment"
|
|
5
|
+
| "ready_for_packing"
|
|
6
|
+
| "awaiting_courier"
|
|
7
|
+
| "shipping"
|
|
8
|
+
| "delivered"
|
|
9
|
+
| "shipping_failed"
|
|
10
|
+
| "returned_to_sender"
|
|
11
|
+
| "cancelled"
|
|
12
|
+
| "suspended";
|
|
13
|
+
|
|
14
|
+
// Provider strings arrive in varied spelling ("IN_FULFILLMENT", "in_fulfillment",
|
|
15
|
+
// "Shipping") — compare on a canonical token so casing/separator drift can never
|
|
16
|
+
// silently zero the pull.
|
|
17
|
+
export function canonicalStatusToken(value: string | null | undefined): string | null {
|
|
18
|
+
const token = value?.trim().toLowerCase().replace(/[\s_-]+/g, "_");
|
|
19
|
+
return token || null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Map the provider primary `status` to our normalized enum. subStatus is NOT
|
|
23
|
+
// consulted: it is recorded verbatim as evidence but never changes the local
|
|
24
|
+
// state (the provider-status mapping lives entirely in the primary status).
|
|
25
|
+
// Returns null for an unknown/UNKNOWN primary status → the worker quarantines it
|
|
26
|
+
// as omnipack_unknown_provider_status (loud, self-diagnosing) rather than skipping.
|
|
27
|
+
export function normalizeStatus(status: string | null): NormalizedProviderStatus | null {
|
|
28
|
+
switch (canonicalStatusToken(status)) {
|
|
29
|
+
case "new":
|
|
30
|
+
return "new";
|
|
31
|
+
case "in_fulfillment":
|
|
32
|
+
return "in_fulfillment";
|
|
33
|
+
case "ready_for_packing":
|
|
34
|
+
return "ready_for_packing";
|
|
35
|
+
case "awaiting_courier":
|
|
36
|
+
return "awaiting_courier";
|
|
37
|
+
case "shipping":
|
|
38
|
+
return "shipping";
|
|
39
|
+
case "delivered":
|
|
40
|
+
return "delivered";
|
|
41
|
+
case "shipping_failed":
|
|
42
|
+
return "shipping_failed";
|
|
43
|
+
case "returned_to_sender":
|
|
44
|
+
return "returned_to_sender";
|
|
45
|
+
case "cancelled":
|
|
46
|
+
return "cancelled";
|
|
47
|
+
case "suspended":
|
|
48
|
+
return "suspended";
|
|
49
|
+
// "unknown" is OmniPack's documented exceptional value ("in general it
|
|
50
|
+
// shouldn't happen") — quarantine it like any unmapped status.
|
|
51
|
+
default:
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Local fulfillment status vocabulary (the canonical set used across the
|
|
57
|
+
// commerce domain): provider_received | picking | packed | in_transit |
|
|
58
|
+
// delivered | cancelled | exception. Both ingestion paths — the poller and the
|
|
59
|
+
// webhook — map into it here and nowhere else.
|
|
60
|
+
//
|
|
61
|
+
// A total Record rather than a `switch`: a new member of the union is then a
|
|
62
|
+
// compile error instead of a silent fall-through to whatever the last branch
|
|
63
|
+
// returned. The webhook path used to carry exactly that hole (its private
|
|
64
|
+
// mapper defaulted every unnamed token to `delivered`, the most consequential
|
|
65
|
+
// terminal state); routing it through this table removed it.
|
|
66
|
+
const LOCAL_STATUS_BY_PROVIDER_STATUS: Record<NormalizedProviderStatus, string> = {
|
|
67
|
+
// Created / on hold at the provider. READY_FOR_EXPORT means validation passed
|
|
68
|
+
// and waits for export to warehouse execution; EXPORTED means handed to
|
|
69
|
+
// warehouse execution. Neither proves a label, stock coverage, WMS
|
|
70
|
+
// acceptance, cut-off passage, or literal picking. Neither is shipped.
|
|
71
|
+
new: "provider_received",
|
|
72
|
+
// Canonical `picking` is the coarse provider-neutral warehouse-preparation
|
|
73
|
+
// bucket; IN_FULFILLMENT evidence does not prove a literal picker action, and
|
|
74
|
+
// it does NOT consume provider stock — see stockConsumedFor below.
|
|
75
|
+
in_fulfillment: "picking",
|
|
76
|
+
// Picking completed, awaiting packing. This is the domain's finished-picking
|
|
77
|
+
// consumption boundary: the webhook path maps the same physical moment
|
|
78
|
+
// (order.picked) to local `packed` and consumes provider stock, so the poller
|
|
79
|
+
// must not lag a state behind (push/pull parity). `packed` is not in the
|
|
80
|
+
// handover set, so no dispatch email fires here.
|
|
81
|
+
ready_for_packing: "packed",
|
|
82
|
+
// Packed, waiting for the courier to collect. Stock is consumed; the parcel
|
|
83
|
+
// is NOT yet handed over, so no dispatch email fires here.
|
|
84
|
+
awaiting_courier: "packed",
|
|
85
|
+
// Courier has the parcel — this is the ship boundary: handover + tracking +
|
|
86
|
+
// the shipment.dispatched customer email.
|
|
87
|
+
shipping: "in_transit",
|
|
88
|
+
delivered: "delivered",
|
|
89
|
+
// Shipping failed / order suspended pending merchant clarification / returned
|
|
90
|
+
// to sender / provider-side cancellation: all route to an operational
|
|
91
|
+
// fulfillment_exception hold for OMS review. The verified vendor source emits
|
|
92
|
+
// the existing reassurance-only event before delivery; after durable delivery
|
|
93
|
+
// the hold remains but the future-tense event is suppressed. The distinct
|
|
94
|
+
// provider status is preserved as the hold reason.
|
|
95
|
+
shipping_failed: "exception",
|
|
96
|
+
suspended: "exception",
|
|
97
|
+
returned_to_sender: "exception",
|
|
98
|
+
cancelled: "exception",
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export function localStatusFor(status: NormalizedProviderStatus): string {
|
|
102
|
+
return LOCAL_STATUS_BY_PROVIDER_STATUS[status];
|
|
103
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
import type { OmnipackWebhookEvidence } from "./mappers.js";
|
|
3
|
+
import type { NormalizedProviderStatus } from "./omnipackStatusVocabulary.js";
|
|
4
|
+
|
|
5
|
+
export interface OmnipackWebhookRequest { headers: Record<string, string | string[] | undefined> }
|
|
6
|
+
export type OmnipackWebhookRouteEvent = "shipment.accepted" | "order.processing_started" | "order.picked" | "order.shipped" | "order.delivered";
|
|
7
|
+
|
|
8
|
+
export const EVENT_TO_STATUS: Record<OmnipackWebhookRouteEvent, NormalizedProviderStatus> = {
|
|
9
|
+
"shipment.accepted": "new",
|
|
10
|
+
"order.processing_started": "in_fulfillment",
|
|
11
|
+
"order.picked": "ready_for_packing",
|
|
12
|
+
"order.shipped": "shipping",
|
|
13
|
+
"order.delivered": "delivered",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function verifyOmnipackWebhookToken(req: OmnipackWebhookRequest, expectedToken: string | undefined): boolean {
|
|
17
|
+
if (!expectedToken) return false;
|
|
18
|
+
const authorization = readHeader(req, "authorization");
|
|
19
|
+
if (safeEqual(authorization, `Bearer ${expectedToken}`)) return true;
|
|
20
|
+
if (verifyBasicAuth(authorization, expectedToken)) return true;
|
|
21
|
+
return safeEqual(readHeader(req, "x-omnipack-webhook-token"), expectedToken);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function buildProviderEventId(evidence: OmnipackWebhookEvidence): string {
|
|
25
|
+
return [
|
|
26
|
+
evidence.event,
|
|
27
|
+
evidence.providerOrderId ?? evidence.orderNumber ?? "unknown-order",
|
|
28
|
+
evidence.fulfilmentNumber ?? "unknown-fulfilment",
|
|
29
|
+
evidence.occurredAt ?? "unknown-time",
|
|
30
|
+
].join(":");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function readHeader(req: OmnipackWebhookRequest, name: string): string | undefined {
|
|
34
|
+
const direct = req.headers[name];
|
|
35
|
+
if (typeof direct === "string") return direct;
|
|
36
|
+
if (Array.isArray(direct)) return direct[0];
|
|
37
|
+
const lowerName = name.toLowerCase();
|
|
38
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
39
|
+
if (key.toLowerCase() !== lowerName) continue;
|
|
40
|
+
if (typeof value === "string") return value;
|
|
41
|
+
if (Array.isArray(value)) return value[0];
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function verifyBasicAuth(authorization: string | undefined, expectedToken: string): boolean {
|
|
47
|
+
const match = authorization?.match(/^Basic\s+(.+)$/i);
|
|
48
|
+
if (!match) return false;
|
|
49
|
+
const credentials = decodeBase64(match[1]);
|
|
50
|
+
if (!credentials) return false;
|
|
51
|
+
const separator = credentials.indexOf(":");
|
|
52
|
+
if (separator <= 0) return false;
|
|
53
|
+
const username = credentials.slice(0, separator);
|
|
54
|
+
if (!username.trim()) return false;
|
|
55
|
+
const password = credentials.slice(separator + 1);
|
|
56
|
+
if (!password) return false;
|
|
57
|
+
return safeEqual(password, expectedToken);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function decodeBase64(value: string): string | null {
|
|
61
|
+
try {
|
|
62
|
+
return Buffer.from(value, "base64").toString("utf8");
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function safeEqual(actual: string | undefined, expected: string): boolean {
|
|
69
|
+
if (!actual) return false;
|
|
70
|
+
const actualBytes = Buffer.from(actual);
|
|
71
|
+
const expectedBytes = Buffer.from(expected);
|
|
72
|
+
return actualBytes.length === expectedBytes.length && timingSafeEqual(actualBytes, expectedBytes);
|
|
73
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Response mappers for the two-way OmniPack product sync (one SKU ↔ many EANs / "packs").
|
|
2
|
+
// Kept separate from the order/stock/fulfilment mappers so the product-sync surface stays a
|
|
3
|
+
// cohesive, independently-testable module. Self-contained tiny readers (no cross-file coupling)
|
|
4
|
+
// mirror the defensive parsing convention used in mappers.ts.
|
|
5
|
+
import { sanitizeOmnipackPayload } from "./mappers.js";
|
|
6
|
+
|
|
7
|
+
export interface OmnipackProductPackEvidence {
|
|
8
|
+
ean: string;
|
|
9
|
+
quantity: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// GET /products/{sku} — the product with its packs[]. The pack list is authoritative for what
|
|
13
|
+
// OmniPack currently holds; the push diff and the pull reconciliation both read it.
|
|
14
|
+
export interface OmnipackProductEvidence {
|
|
15
|
+
provider: "omnipack";
|
|
16
|
+
sku: string;
|
|
17
|
+
packs: OmnipackProductPackEvidence[];
|
|
18
|
+
raw: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface OmnipackProductPackCreatedEvidence {
|
|
22
|
+
provider: "omnipack";
|
|
23
|
+
sku: string;
|
|
24
|
+
ean: string;
|
|
25
|
+
raw: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// We tolerate a sparse body and fall back to the request-side sku; packs without an EAN are
|
|
29
|
+
// dropped (an EAN-less pack is not addressable for the host↔OmniPack diff).
|
|
30
|
+
export function mapOmnipackProductResponse(body: unknown, requestSku: string): OmnipackProductEvidence {
|
|
31
|
+
const response = asRecord(body);
|
|
32
|
+
const packs = readArray(response.packs)
|
|
33
|
+
.map((entry) => {
|
|
34
|
+
const pack = asRecord(entry);
|
|
35
|
+
return { ean: readString(pack.ean), quantity: readNumber(pack.quantity) };
|
|
36
|
+
})
|
|
37
|
+
.filter((pack) => pack.ean.length > 0);
|
|
38
|
+
return {
|
|
39
|
+
provider: "omnipack",
|
|
40
|
+
sku: readString(response.sku) || requestSku,
|
|
41
|
+
packs,
|
|
42
|
+
raw: sanitizeOmnipackPayload(response),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function mapOmnipackProductPackCreatedResponse(
|
|
47
|
+
body: unknown,
|
|
48
|
+
requestSku: string,
|
|
49
|
+
requestEan: string,
|
|
50
|
+
): OmnipackProductPackCreatedEvidence {
|
|
51
|
+
const response = asRecord(body);
|
|
52
|
+
return {
|
|
53
|
+
provider: "omnipack",
|
|
54
|
+
sku: readString(response.sku) || requestSku,
|
|
55
|
+
ean: readString(response.ean) || requestEan,
|
|
56
|
+
raw: sanitizeOmnipackPayload(response),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function asRecord(input: unknown): Record<string, unknown> {
|
|
61
|
+
return input && typeof input === "object" && !Array.isArray(input) ? (input as Record<string, unknown>) : {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readArray(input: unknown): unknown[] {
|
|
65
|
+
return Array.isArray(input) ? input : [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function readString(input: unknown): string {
|
|
69
|
+
return typeof input === "string" ? input : "";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function readNumber(input: unknown): number {
|
|
73
|
+
return typeof input === "number" && Number.isFinite(input) ? input : 0;
|
|
74
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export class OmnipackProviderError extends Error {
|
|
2
|
+
readonly provider = "omnipack";
|
|
3
|
+
readonly operation: string;
|
|
4
|
+
readonly status: number | null;
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly retryable: boolean;
|
|
7
|
+
readonly mayHaveSucceeded: boolean;
|
|
8
|
+
|
|
9
|
+
constructor(input: {
|
|
10
|
+
operation: string;
|
|
11
|
+
status: number | null;
|
|
12
|
+
code: string;
|
|
13
|
+
retryable: boolean;
|
|
14
|
+
mayHaveSucceeded: boolean;
|
|
15
|
+
}) {
|
|
16
|
+
super(`OmniPack request failed: ${input.operation}`);
|
|
17
|
+
this.name = "OmnipackProviderError";
|
|
18
|
+
this.operation = input.operation;
|
|
19
|
+
this.status = input.status;
|
|
20
|
+
this.code = input.code;
|
|
21
|
+
this.retryable = input.retryable;
|
|
22
|
+
this.mayHaveSucceeded = input.mayHaveSucceeded;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SanitizedOmnipackProviderError {
|
|
27
|
+
code: string;
|
|
28
|
+
mayHaveSucceeded: boolean;
|
|
29
|
+
message: string;
|
|
30
|
+
operation: string | null;
|
|
31
|
+
retryable: boolean;
|
|
32
|
+
status: number | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function sanitizeOmnipackProviderError(error: unknown): SanitizedOmnipackProviderError {
|
|
36
|
+
if (error instanceof OmnipackProviderError) {
|
|
37
|
+
return {
|
|
38
|
+
code: error.code,
|
|
39
|
+
mayHaveSucceeded: error.mayHaveSucceeded,
|
|
40
|
+
message: error.message,
|
|
41
|
+
operation: error.operation,
|
|
42
|
+
retryable: error.retryable,
|
|
43
|
+
status: error.status,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
code: "omnipack_provider_error",
|
|
48
|
+
mayHaveSucceeded: true,
|
|
49
|
+
message: "OmniPack request failed",
|
|
50
|
+
operation: null,
|
|
51
|
+
retryable: true,
|
|
52
|
+
status: null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function mayPostHaveSucceeded(method: string, status: number | null): boolean {
|
|
57
|
+
if (method !== "POST") return false;
|
|
58
|
+
return status === null
|
|
59
|
+
|| status === 408
|
|
60
|
+
|| status === 409
|
|
61
|
+
|| status === 425
|
|
62
|
+
|| status === 429
|
|
63
|
+
|| status >= 500;
|
|
64
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Provider-payload extraction only. This infra layer stays free of domain
|
|
2
|
+
// imports (provider-infra boundary): it surfaces the feed's raw carrier
|
|
3
|
+
// evidence (carrier code, service, feed-supplied URL) and leaves carrier
|
|
4
|
+
// normalization + tracking-URL building to the fulfillment domain
|
|
5
|
+
// (enrichOmnipackTrackingReference + the shipping carrier registry).
|
|
6
|
+
export interface OmnipackTrackingReferenceEvidence {
|
|
7
|
+
provider: "omnipack";
|
|
8
|
+
trackingNumber: string;
|
|
9
|
+
trackingUrl: string | null;
|
|
10
|
+
/** Raw provider carrier/platform code. */
|
|
11
|
+
carrier: string | null;
|
|
12
|
+
carrierKind: string | null;
|
|
13
|
+
service: string | null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function mapOmnipackTrackingReferences(input: {
|
|
17
|
+
shipments?: unknown[];
|
|
18
|
+
trackingNumbers?: unknown[];
|
|
19
|
+
readString: (value: unknown) => string;
|
|
20
|
+
readNullableString: (value: unknown) => string | null;
|
|
21
|
+
asRecord: (value: unknown) => Record<string, unknown>;
|
|
22
|
+
}): OmnipackTrackingReferenceEvidence[] {
|
|
23
|
+
const fromShipments = (input.shipments ?? [])
|
|
24
|
+
.map(input.asRecord)
|
|
25
|
+
.map((shipment) => {
|
|
26
|
+
const trackingNumber = input.readString(shipment.trackingNo) || input.readString(shipment.trackingNumber);
|
|
27
|
+
if (!trackingNumber) return null;
|
|
28
|
+
const service = input.readNullableString(shipment.shippingMethod) ?? input.readNullableString(shipment.service);
|
|
29
|
+
return {
|
|
30
|
+
provider: "omnipack" as const,
|
|
31
|
+
trackingNumber,
|
|
32
|
+
trackingUrl:
|
|
33
|
+
input.readNullableString(shipment.trackingUrl) ??
|
|
34
|
+
input.readNullableString(shipment.trackingURL) ??
|
|
35
|
+
input.readNullableString(shipment.trackingLink) ??
|
|
36
|
+
input.readNullableString(shipment.publicTrackingUrl),
|
|
37
|
+
carrier: input.readNullableString(shipment.carrier) ?? input.readNullableString(shipment.carrierCode),
|
|
38
|
+
carrierKind: carrierKindFromService(service),
|
|
39
|
+
service,
|
|
40
|
+
};
|
|
41
|
+
})
|
|
42
|
+
.filter((ref): ref is OmnipackTrackingReferenceEvidence => ref !== null);
|
|
43
|
+
|
|
44
|
+
const fallbackNumbers = (input.trackingNumbers ?? [])
|
|
45
|
+
.map(input.readString)
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
.map((trackingNumber) => ({
|
|
48
|
+
provider: "omnipack" as const,
|
|
49
|
+
trackingNumber,
|
|
50
|
+
trackingUrl: null,
|
|
51
|
+
carrier: null,
|
|
52
|
+
carrierKind: null,
|
|
53
|
+
service: null,
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
return uniqueTrackingReferences([...fromShipments, ...fallbackNumbers]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function uniqueTrackingReferences(
|
|
60
|
+
refs: OmnipackTrackingReferenceEvidence[],
|
|
61
|
+
): OmnipackTrackingReferenceEvidence[] {
|
|
62
|
+
const seen = new Set<string>();
|
|
63
|
+
const result: OmnipackTrackingReferenceEvidence[] = [];
|
|
64
|
+
for (const ref of refs) {
|
|
65
|
+
const key = ref.trackingNumber.trim();
|
|
66
|
+
if (!key || seen.has(key)) continue;
|
|
67
|
+
seen.add(key);
|
|
68
|
+
result.push({ ...ref, trackingNumber: key });
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function carrierKindFromService(service: string | null): string | null {
|
|
74
|
+
if (!service) return null;
|
|
75
|
+
const [carrier] = service.split("_");
|
|
76
|
+
return carrier ? carrier.toLowerCase() : null;
|
|
77
|
+
}
|