@openlup/platform 0.16.0 → 0.17.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 +84 -0
- package/README.md +285 -5
- 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 +51 -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/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 +46 -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/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/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/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/package.json +12 -2
- package/release-gates.json +41 -8
- package/sql/20260807190000_comms_outbox_rail.sql +329 -0
- package/sql/20260810120001_transactional_delivery_receipts.sql +209 -0
- package/sql/20260813120000_communications_control_plane.sql +568 -0
- package/sql/20261019200000_communications_native_operations.sql +68 -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 +51 -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/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 +46 -0
- package/src/communications/integrationEventSignature.ts +49 -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/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/http/index.ts +1 -0
- package/src/http/webhookSignature.ts +96 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { admitPolicyEnforcedEmailTransport } from "./emailEgress.js";
|
|
2
|
+
/** Converts the transport's legacy identifier field at the transport boundary. */
|
|
3
|
+
export function emailTransportMessageId(outcome) {
|
|
4
|
+
return outcome.resendId;
|
|
5
|
+
}
|
|
6
|
+
/** Maps the neutral message identifier onto the deployed ledger's legacy field. */
|
|
7
|
+
export function emailTransportLedgerIdentifier(messageId) {
|
|
8
|
+
return { resend_id: messageId };
|
|
9
|
+
}
|
|
10
|
+
/** Synthesizes the canonical terminal transport shape when `send` throws. */
|
|
11
|
+
export function failedEmailTransportResult() {
|
|
12
|
+
return {
|
|
13
|
+
outcome: { ok: false, resendId: null, httpStatus: 0, providerError: "provider_transport_threw", aborted: false },
|
|
14
|
+
providerResponse: { exception: true },
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** One truth projection for every Node email ledger, timeline and caller. */
|
|
18
|
+
export function classifyEmailSendOutcome(outcome) {
|
|
19
|
+
const skipReason = outcome.skipReason
|
|
20
|
+
?? (outcome.adminDisabled ? "admin_disabled" : null)
|
|
21
|
+
?? (outcome.suppressed === "drop" ? "egress_suppressed" : null);
|
|
22
|
+
if (skipReason) {
|
|
23
|
+
return {
|
|
24
|
+
skipReason,
|
|
25
|
+
timelineStatus: "skipped",
|
|
26
|
+
ledgerStatus: "skipped",
|
|
27
|
+
sentAtEligible: false,
|
|
28
|
+
lastErrorCode: skipReason,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// `ok` deliberately remains the transport-acceptance contract. In particular,
|
|
32
|
+
// this wave does not turn a historical 2xx-without-id answer into a retry.
|
|
33
|
+
if (outcome.ok) {
|
|
34
|
+
return {
|
|
35
|
+
skipReason: null,
|
|
36
|
+
timelineStatus: "sent",
|
|
37
|
+
ledgerStatus: "sent",
|
|
38
|
+
sentAtEligible: true,
|
|
39
|
+
lastErrorCode: null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (outcome.aborted) {
|
|
43
|
+
return {
|
|
44
|
+
skipReason: null,
|
|
45
|
+
timelineStatus: "delivery_delayed",
|
|
46
|
+
ledgerStatus: "failed",
|
|
47
|
+
sentAtEligible: false,
|
|
48
|
+
lastErrorCode: "provider_request_aborted",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
skipReason: null,
|
|
53
|
+
timelineStatus: "failed",
|
|
54
|
+
ledgerStatus: "failed",
|
|
55
|
+
sentAtEligible: false,
|
|
56
|
+
lastErrorCode: normalizeEmailFailureCode(outcome.providerError),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Adds a provider-neutral skip reason without changing ordinary wire shapes. */
|
|
60
|
+
export function withEmailSendSkipReason(outcome) {
|
|
61
|
+
const skipReason = classifyEmailSendOutcome(outcome).skipReason;
|
|
62
|
+
return skipReason ? { ...outcome, skipReason } : outcome;
|
|
63
|
+
}
|
|
64
|
+
function normalizeEmailFailureCode(value) {
|
|
65
|
+
if (!value)
|
|
66
|
+
return "provider_send_failed";
|
|
67
|
+
const normalized = value
|
|
68
|
+
.toLowerCase()
|
|
69
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
70
|
+
.replace(/^_+|_+$/g, "")
|
|
71
|
+
.slice(0, 80);
|
|
72
|
+
return normalized || "provider_send_failed";
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Reference capture transport: captures sends in memory and never makes a
|
|
76
|
+
* network call. Proves the seam is real — a port wired to this sends email with
|
|
77
|
+
* no HTTP client — and doubles as the substitute an OSS fork starts from
|
|
78
|
+
* before writing its own SES/SMTP adapter.
|
|
79
|
+
*/
|
|
80
|
+
export function createInMemoryEmailTransport(opts) {
|
|
81
|
+
const sent = [];
|
|
82
|
+
const prefix = opts?.idPrefix ?? "in-memory";
|
|
83
|
+
return admitPolicyEnforcedEmailTransport({
|
|
84
|
+
providerKind: "in-memory",
|
|
85
|
+
sent,
|
|
86
|
+
async send(message) {
|
|
87
|
+
sent.push(message);
|
|
88
|
+
const id = `${prefix}-${sent.length}`;
|
|
89
|
+
return {
|
|
90
|
+
outcome: { ok: true, resendId: id, httpStatus: 200, providerError: null, aborted: false },
|
|
91
|
+
providerResponse: { id },
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class CommunicationRecipientNotFoundError extends Error {
|
|
2
|
+
constructor(message?: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class CommunicationTemplateNotFoundError extends Error {
|
|
5
|
+
constructor(message?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class CommunicationConflictError extends Error {
|
|
8
|
+
constructor(message?: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class CommunicationValidationError extends Error {
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class CommunicationUnavailableError extends Error {
|
|
14
|
+
constructor(message?: string);
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class CommunicationRecipientNotFoundError extends Error {
|
|
2
|
+
constructor(message = "Communication recipient not found") {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "CommunicationRecipientNotFoundError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export class CommunicationTemplateNotFoundError extends Error {
|
|
8
|
+
constructor(message = "Communication template not found") {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "CommunicationTemplateNotFoundError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class CommunicationConflictError extends Error {
|
|
14
|
+
constructor(message = "Communication request conflicts with current state") {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "CommunicationConflictError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class CommunicationValidationError extends Error {
|
|
20
|
+
constructor(message = "Communication request is invalid") {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "CommunicationValidationError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class CommunicationUnavailableError extends Error {
|
|
26
|
+
constructor(message = "Communication capability is unavailable") {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "CommunicationUnavailableError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export * from "./accountingDocumentDelivery.js";
|
|
2
|
+
export * from "./authEmailError.js";
|
|
3
|
+
export * from "./authSendEmailHook.js";
|
|
4
|
+
export * from "./capturedTransactionalDelivery.js";
|
|
5
|
+
export * from "./communicationSync.js";
|
|
6
|
+
export * from "./communicationSyncWorker.js";
|
|
7
|
+
export * from "./consentPolicy.js";
|
|
8
|
+
export * from "./deliveryReconciliation.js";
|
|
9
|
+
export * from "./contribution.js";
|
|
10
|
+
export * from "./emailHealthAssessment.js";
|
|
11
|
+
export * from "./emailHealthMetricsPort.js";
|
|
12
|
+
export * from "./emailNotificationControl.js";
|
|
13
|
+
export * from "./emailObservation.js";
|
|
14
|
+
export * from "./emailTransport.js";
|
|
15
|
+
export * from "./emailEgress.js";
|
|
16
|
+
export * from "./errors.js";
|
|
17
|
+
export * from "./integrationEventSignature.js";
|
|
18
|
+
export * from "./managedTransactionalDeliveryStore.js";
|
|
19
|
+
export * from "./newsletterIntegrationContracts.js";
|
|
20
|
+
export * from "./newsletterWebhookPort.js";
|
|
21
|
+
export * from "./originPolicy.js";
|
|
22
|
+
export * from "./postgresTransactionalDeliveryStore.js";
|
|
23
|
+
export * from "./preferencesToken.js";
|
|
24
|
+
export * from "./publicPreferenceToken.js";
|
|
25
|
+
export * from "./shipmentNotifications.js";
|
|
26
|
+
export * from "./sql.js";
|
|
27
|
+
export * from "./standardWebhooks.js";
|
|
28
|
+
export * from "./status.js";
|
|
29
|
+
export * from "./transactionalDelivery.js";
|
|
30
|
+
export * from "./transactionalDeliveryIdentifier.js";
|
|
31
|
+
export * from "./unsubscribeToken.js";
|
|
32
|
+
export type * from "./contracts/authEmail.js";
|
|
33
|
+
export type * from "./contracts/email.js";
|
|
34
|
+
export type * from "./contracts/publicIntake.js";
|
|
35
|
+
export type * from "./contracts/transactionalDelivery.js";
|
|
36
|
+
export type * from "./contracts/newsletterWebhook.js";
|
|
37
|
+
export type { NewsletterSyncProviderPort, NewsletterSyncOutcome, NewsletterSyncReconcileOutcome } from "./contracts/newsletter.js";
|
|
38
|
+
export * from "./consentPurposeRegistry.js";
|
|
39
|
+
export type * from "./contracts/consent.js";
|
|
40
|
+
export type * from "./contracts/marketingAutomation.js";
|
|
41
|
+
export * from "./newsletterWebhookProcessing.js";
|
|
42
|
+
export * from "./nativeOperations.js";
|
|
43
|
+
export * from "./postgresDeliveryReconciliation.js";
|
|
44
|
+
export * from "./postgresCommunicationSync.js";
|
|
45
|
+
export * from "./postgresNotificationRecipients.js";
|
|
46
|
+
export * from "./postgresConsentEvaluator.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export * from "./accountingDocumentDelivery.js";
|
|
2
|
+
export * from "./authEmailError.js";
|
|
3
|
+
export * from "./authSendEmailHook.js";
|
|
4
|
+
export * from "./capturedTransactionalDelivery.js";
|
|
5
|
+
export * from "./communicationSync.js";
|
|
6
|
+
export * from "./communicationSyncWorker.js";
|
|
7
|
+
export * from "./consentPolicy.js";
|
|
8
|
+
export * from "./deliveryReconciliation.js";
|
|
9
|
+
export * from "./contribution.js";
|
|
10
|
+
export * from "./emailHealthAssessment.js";
|
|
11
|
+
export * from "./emailHealthMetricsPort.js";
|
|
12
|
+
export * from "./emailNotificationControl.js";
|
|
13
|
+
export * from "./emailObservation.js";
|
|
14
|
+
export * from "./emailTransport.js";
|
|
15
|
+
export * from "./emailEgress.js";
|
|
16
|
+
export * from "./errors.js";
|
|
17
|
+
export * from "./integrationEventSignature.js";
|
|
18
|
+
export * from "./managedTransactionalDeliveryStore.js";
|
|
19
|
+
export * from "./newsletterIntegrationContracts.js";
|
|
20
|
+
export * from "./newsletterWebhookPort.js";
|
|
21
|
+
export * from "./originPolicy.js";
|
|
22
|
+
export * from "./postgresTransactionalDeliveryStore.js";
|
|
23
|
+
export * from "./preferencesToken.js";
|
|
24
|
+
export * from "./publicPreferenceToken.js";
|
|
25
|
+
export * from "./shipmentNotifications.js";
|
|
26
|
+
export * from "./sql.js";
|
|
27
|
+
export * from "./standardWebhooks.js";
|
|
28
|
+
export * from "./status.js";
|
|
29
|
+
export * from "./transactionalDelivery.js";
|
|
30
|
+
export * from "./transactionalDeliveryIdentifier.js";
|
|
31
|
+
export * from "./unsubscribeToken.js";
|
|
32
|
+
export * from "./consentPurposeRegistry.js";
|
|
33
|
+
export * from "./newsletterWebhookProcessing.js";
|
|
34
|
+
export * from "./nativeOperations.js";
|
|
35
|
+
export * from "./postgresDeliveryReconciliation.js";
|
|
36
|
+
export * from "./postgresCommunicationSync.js";
|
|
37
|
+
export * from "./postgresNotificationRecipients.js";
|
|
38
|
+
export * from "./postgresConsentEvaluator.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const COMMUNICATION_INTEGRATION_SIGNATURE_TOLERANCE_SECONDS = 300;
|
|
2
|
+
export declare const COMMUNICATION_INTEGRATION_SIGNATURE_HEADER = "x-openlup-communications-signature";
|
|
3
|
+
export declare const COMMUNICATION_INTEGRATION_TIMESTAMP_HEADER = "x-openlup-communications-timestamp";
|
|
4
|
+
export declare function verifyCommunicationIntegrationEventSignature(input: {
|
|
5
|
+
rawBody: string;
|
|
6
|
+
signatureHeader: string | undefined;
|
|
7
|
+
timestampHeader: string | undefined;
|
|
8
|
+
secret: string;
|
|
9
|
+
now?: () => number;
|
|
10
|
+
}): boolean;
|
|
11
|
+
export declare function signCommunicationIntegrationEvent(input: {
|
|
12
|
+
rawBody: string;
|
|
13
|
+
timestamp: number;
|
|
14
|
+
secret: string;
|
|
15
|
+
}): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
export const COMMUNICATION_INTEGRATION_SIGNATURE_TOLERANCE_SECONDS = 300;
|
|
3
|
+
export const COMMUNICATION_INTEGRATION_SIGNATURE_HEADER = "x-openlup-communications-signature";
|
|
4
|
+
export const COMMUNICATION_INTEGRATION_TIMESTAMP_HEADER = "x-openlup-communications-timestamp";
|
|
5
|
+
export function verifyCommunicationIntegrationEventSignature(input) {
|
|
6
|
+
if (!input.secret || !input.signatureHeader || !input.timestampHeader)
|
|
7
|
+
return false;
|
|
8
|
+
const timestamp = Number(input.timestampHeader);
|
|
9
|
+
if (!Number.isFinite(timestamp))
|
|
10
|
+
return false;
|
|
11
|
+
const now = input.now ?? (() => Math.floor(Date.now() / 1000));
|
|
12
|
+
const age = now() - timestamp;
|
|
13
|
+
if (age > COMMUNICATION_INTEGRATION_SIGNATURE_TOLERANCE_SECONDS)
|
|
14
|
+
return false;
|
|
15
|
+
if (age < -COMMUNICATION_INTEGRATION_SIGNATURE_TOLERANCE_SECONDS)
|
|
16
|
+
return false;
|
|
17
|
+
const signature = normalizeSignature(input.signatureHeader);
|
|
18
|
+
const expected = signCommunicationIntegrationEvent({
|
|
19
|
+
rawBody: input.rawBody,
|
|
20
|
+
timestamp,
|
|
21
|
+
secret: input.secret,
|
|
22
|
+
});
|
|
23
|
+
return safeEqual(signature, expected);
|
|
24
|
+
}
|
|
25
|
+
export function signCommunicationIntegrationEvent(input) {
|
|
26
|
+
return createHmac("sha256", input.secret)
|
|
27
|
+
.update(`${input.timestamp}.${input.rawBody}`)
|
|
28
|
+
.digest("hex");
|
|
29
|
+
}
|
|
30
|
+
function normalizeSignature(value) {
|
|
31
|
+
return value.trim().replace(/^sha256=/i, "");
|
|
32
|
+
}
|
|
33
|
+
function safeEqual(left, right) {
|
|
34
|
+
const leftBuffer = Buffer.from(left);
|
|
35
|
+
const rightBuffer = Buffer.from(right);
|
|
36
|
+
return leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TransactionalDeliveryReceiptStore } from "./contracts/transactionalDelivery.js";
|
|
2
|
+
export interface ManagedTransactionalDeliveryStoreClient {
|
|
3
|
+
rpc(functionName: string, args: Record<string, unknown>): PromiseLike<{
|
|
4
|
+
data: unknown;
|
|
5
|
+
error: {
|
|
6
|
+
code?: string;
|
|
7
|
+
message?: string;
|
|
8
|
+
} | null;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
/** Managed adapter over the three receipt RPCs; access scope belongs to its binding. */
|
|
12
|
+
export declare function createManagedTransactionalDeliveryStore(client: ManagedTransactionalDeliveryStoreClient): TransactionalDeliveryReceiptStore;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
function failure(name, error) {
|
|
2
|
+
const result = new Error(`${name}_failed: ${error.message ?? error.code ?? "unknown"}`);
|
|
3
|
+
result.code = error.code;
|
|
4
|
+
return result;
|
|
5
|
+
}
|
|
6
|
+
function receipt(data) {
|
|
7
|
+
const value = (Array.isArray(data) ? data[0] : data);
|
|
8
|
+
if (!value || typeof value !== "object")
|
|
9
|
+
throw new Error("transactional_delivery_receipt_invalid");
|
|
10
|
+
const common = {
|
|
11
|
+
idempotencyKey: String(value.idempotency_key ?? ""),
|
|
12
|
+
commandFingerprint: String(value.command_fingerprint ?? ""),
|
|
13
|
+
attemptCount: Number(value.attempt_count ?? 0),
|
|
14
|
+
};
|
|
15
|
+
if (value.state === "accepted" && typeof value.delivery_reference === "string" && value.error_code == null) {
|
|
16
|
+
return { ...common, state: "accepted", deliveryReference: value.delivery_reference, errorCode: null };
|
|
17
|
+
}
|
|
18
|
+
if (value.state === "failed" && value.delivery_reference == null && typeof value.error_code === "string") {
|
|
19
|
+
return { ...common, state: "failed", deliveryReference: null, errorCode: value.error_code };
|
|
20
|
+
}
|
|
21
|
+
throw new Error("transactional_delivery_receipt_invalid");
|
|
22
|
+
}
|
|
23
|
+
/** Managed adapter over the three receipt RPCs; access scope belongs to its binding. */
|
|
24
|
+
export function createManagedTransactionalDeliveryStore(client) {
|
|
25
|
+
const call = async (name, args) => {
|
|
26
|
+
const { data, error } = await client.rpc(name, args);
|
|
27
|
+
if (error)
|
|
28
|
+
throw failure(name, error);
|
|
29
|
+
return receipt(data);
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
async readReceipt(idempotencyKey) {
|
|
33
|
+
const { data, error } = await client.rpc("transactional_delivery_read_receipt", { p_idempotency_key: idempotencyKey });
|
|
34
|
+
if (error)
|
|
35
|
+
throw failure("transactional_delivery_read_receipt", error);
|
|
36
|
+
return Array.isArray(data) && data.length === 0 ? null : receipt(data);
|
|
37
|
+
},
|
|
38
|
+
recordAccepted: (input) => call("transactional_delivery_record_accepted", {
|
|
39
|
+
p_idempotency_key: input.idempotencyKey,
|
|
40
|
+
p_command_fingerprint: input.commandFingerprint,
|
|
41
|
+
p_delivery_reference: input.deliveryReference,
|
|
42
|
+
}),
|
|
43
|
+
recordFailed: (input) => call("transactional_delivery_record_failed", {
|
|
44
|
+
p_idempotency_key: input.idempotencyKey,
|
|
45
|
+
p_command_fingerprint: input.commandFingerprint,
|
|
46
|
+
p_error_code: input.errorCode,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { PostgresDataGatewayOptions } from "../data/index.js";
|
|
2
|
+
import type { DeliveryReconciliationPort } from "./deliveryReconciliation.js";
|
|
3
|
+
import type { CommunicationRecipientKind } from "./consentPolicy.js";
|
|
4
|
+
export interface NativeCommunicationsOptions extends PostgresDataGatewayOptions {
|
|
5
|
+
binding: string;
|
|
6
|
+
}
|
|
7
|
+
export type NativeObservationKind = "sent" | "delayed" | "delivered" | "bounced" | "complained" | "failed";
|
|
8
|
+
export interface NativeNetworkTarget {
|
|
9
|
+
sourceKey: string;
|
|
10
|
+
messageId: string;
|
|
11
|
+
recipientEmail: string;
|
|
12
|
+
templateReference: string;
|
|
13
|
+
acceptedAt: string;
|
|
14
|
+
/** Only a host that observed a real network acceptance may register this fact. */
|
|
15
|
+
evidence: "network_accepted";
|
|
16
|
+
}
|
|
17
|
+
export interface NativeDeliveryEvidence {
|
|
18
|
+
id: string;
|
|
19
|
+
sourceKey: string;
|
|
20
|
+
messageId: string;
|
|
21
|
+
acceptedAt: string;
|
|
22
|
+
observedState: NativeObservationKind | null;
|
|
23
|
+
observedAt: string | null;
|
|
24
|
+
lastPollAt: string | null;
|
|
25
|
+
notFoundCount: number;
|
|
26
|
+
abandonedAt: string | null;
|
|
27
|
+
observations: {
|
|
28
|
+
key: string;
|
|
29
|
+
kind: NativeObservationKind;
|
|
30
|
+
occurredAt: string;
|
|
31
|
+
source: "poll" | "callback";
|
|
32
|
+
}[];
|
|
33
|
+
}
|
|
34
|
+
export interface NativeDeliveryStore extends DeliveryReconciliationPort {
|
|
35
|
+
registerNetworkTarget(input: NativeNetworkTarget): Promise<{
|
|
36
|
+
id: string;
|
|
37
|
+
}>;
|
|
38
|
+
applyObservation(input: {
|
|
39
|
+
sendId: string;
|
|
40
|
+
messageId: string;
|
|
41
|
+
observationKey: string;
|
|
42
|
+
kind: NativeObservationKind;
|
|
43
|
+
occurredAt: string;
|
|
44
|
+
recipientEmail: string | null;
|
|
45
|
+
source: "poll" | "callback";
|
|
46
|
+
}): Promise<void>;
|
|
47
|
+
findByMessageId(messageId: string): Promise<{
|
|
48
|
+
id: string;
|
|
49
|
+
} | null>;
|
|
50
|
+
listEvidence(input: {
|
|
51
|
+
limit: number;
|
|
52
|
+
}): Promise<NativeDeliveryEvidence[]>;
|
|
53
|
+
readEvidence(sendId: string): Promise<NativeDeliveryEvidence | null>;
|
|
54
|
+
close(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
export type NativeNotificationType = "packaging_digest" | "new_signup" | "commerce_payment_critical";
|
|
57
|
+
export interface NativeNotificationRecipient {
|
|
58
|
+
id: string;
|
|
59
|
+
email: string;
|
|
60
|
+
name: string | null;
|
|
61
|
+
active: boolean;
|
|
62
|
+
notification_type: NativeNotificationType;
|
|
63
|
+
created_at: string;
|
|
64
|
+
}
|
|
65
|
+
export interface NativeConsentInput {
|
|
66
|
+
email: string;
|
|
67
|
+
purpose: string;
|
|
68
|
+
recipientKind?: CommunicationRecipientKind;
|
|
69
|
+
sourceTable?: "testers" | "waitlist" | "clients" | "b2b_inquiries" | "notification_recipients";
|
|
70
|
+
sourceId?: string | null;
|
|
71
|
+
}
|
|
72
|
+
export interface NativeConsentDecision {
|
|
73
|
+
allowed: boolean;
|
|
74
|
+
reason: string;
|
|
75
|
+
decisionId: string;
|
|
76
|
+
}
|
|
77
|
+
export declare class NativeConsentEvaluationUnavailableError extends Error {
|
|
78
|
+
constructor(cause: unknown);
|
|
79
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { CommunicationPurposeRegistry } from "./contracts/consent.js";
|
|
2
|
+
import { z } from "./validation.js";
|
|
3
|
+
export declare const NEWSLETTER_MARKETING_PURPOSES: readonly ["marketing_launch_offer", "marketing_newsletter"];
|
|
4
|
+
export declare const NEWSLETTER_SYNC_EVENT_TYPES: readonly ["subscribe", "update", "unsubscribe", "suppress"];
|
|
5
|
+
export declare const NEWSLETTER_WEBHOOK_EVENT_TYPES: readonly ["subscribe", "update", "unsubscribe", "suppress", "complaint", "bounce", "email_change", "profile_update", "ignored"];
|
|
6
|
+
export declare const NEWSLETTER_PROVIDER_CAPABILITY_KEYS: readonly ["subscribe", "unsubscribe", "suppress", "unsuppress", "doubleOptIn", "emailChange", "listMembership", "webhookIdempotency", "retryAfter"];
|
|
7
|
+
import type { NewsletterMarketingPurpose } from "./contracts/newsletter.js";
|
|
8
|
+
import type { NewsletterSyncEventType, NewsletterProviderCapabilityKey, NewsletterProviderCapabilities, NewsletterWebhookEvent } from "./contracts/newsletter.js";
|
|
9
|
+
export type { NewsletterProviderKind, NewsletterMarketingPurpose, NewsletterSyncEventType, NewsletterWebhookEventType, NewsletterProviderCapabilityKey, NewsletterProviderCapabilities, NewsletterWebhookEvent, NewsletterSyncEvent } from "./contracts/newsletter.js";
|
|
10
|
+
export declare const defaultNewsletterProviderCapabilities: NewsletterProviderCapabilities;
|
|
11
|
+
export declare const fullNewsletterProviderCapabilities: NewsletterProviderCapabilities;
|
|
12
|
+
export declare const newsletterProviderKindSchema: z.ZodString;
|
|
13
|
+
export declare const newsletterMarketingPurposeSchema: z.ZodEnum<{
|
|
14
|
+
marketing_launch_offer: "marketing_launch_offer";
|
|
15
|
+
marketing_newsletter: "marketing_newsletter";
|
|
16
|
+
}>;
|
|
17
|
+
export declare const newsletterSyncEventTypeSchema: z.ZodEnum<{
|
|
18
|
+
update: "update";
|
|
19
|
+
subscribe: "subscribe";
|
|
20
|
+
unsubscribe: "unsubscribe";
|
|
21
|
+
suppress: "suppress";
|
|
22
|
+
}>;
|
|
23
|
+
export declare const newsletterWebhookEventTypeSchema: z.ZodEnum<{
|
|
24
|
+
email_change: "email_change";
|
|
25
|
+
update: "update";
|
|
26
|
+
subscribe: "subscribe";
|
|
27
|
+
unsubscribe: "unsubscribe";
|
|
28
|
+
suppress: "suppress";
|
|
29
|
+
complaint: "complaint";
|
|
30
|
+
bounce: "bounce";
|
|
31
|
+
profile_update: "profile_update";
|
|
32
|
+
ignored: "ignored";
|
|
33
|
+
}>;
|
|
34
|
+
export declare const newsletterProviderCapabilitiesSchema: z.ZodObject<{
|
|
35
|
+
subscribe: z.ZodBoolean;
|
|
36
|
+
unsubscribe: z.ZodBoolean;
|
|
37
|
+
suppress: z.ZodBoolean;
|
|
38
|
+
unsuppress: z.ZodBoolean;
|
|
39
|
+
doubleOptIn: z.ZodBoolean;
|
|
40
|
+
emailChange: z.ZodBoolean;
|
|
41
|
+
listMembership: z.ZodBoolean;
|
|
42
|
+
webhookIdempotency: z.ZodBoolean;
|
|
43
|
+
retryAfter: z.ZodBoolean;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
export declare const canonicalNewsletterWebhookEventSchema: z.ZodObject<{
|
|
46
|
+
providerKind: z.ZodString;
|
|
47
|
+
providerEventId: z.ZodString;
|
|
48
|
+
eventType: z.ZodEnum<{
|
|
49
|
+
email_change: "email_change";
|
|
50
|
+
update: "update";
|
|
51
|
+
subscribe: "subscribe";
|
|
52
|
+
unsubscribe: "unsubscribe";
|
|
53
|
+
suppress: "suppress";
|
|
54
|
+
complaint: "complaint";
|
|
55
|
+
bounce: "bounce";
|
|
56
|
+
profile_update: "profile_update";
|
|
57
|
+
ignored: "ignored";
|
|
58
|
+
}>;
|
|
59
|
+
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
remoteProfileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
61
|
+
remoteListId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
62
|
+
purpose: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
63
|
+
marketing_launch_offer: "marketing_launch_offer";
|
|
64
|
+
marketing_newsletter: "marketing_newsletter";
|
|
65
|
+
}>>>;
|
|
66
|
+
explicitOptInEvidence: z.ZodOptional<z.ZodBoolean>;
|
|
67
|
+
doubleOptInStatus: z.ZodOptional<z.ZodEnum<{
|
|
68
|
+
unknown: "unknown";
|
|
69
|
+
confirmed: "confirmed";
|
|
70
|
+
pending: "pending";
|
|
71
|
+
}>>;
|
|
72
|
+
occurredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
73
|
+
payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
export type CanonicalNewsletterWebhookEvent = z.infer<typeof canonicalNewsletterWebhookEventSchema>;
|
|
76
|
+
export declare function normalizeCanonicalNewsletterWebhookEvent<Purpose extends string = NewsletterMarketingPurpose>(event: Omit<CanonicalNewsletterWebhookEvent, "purpose"> & {
|
|
77
|
+
purpose?: Purpose | null;
|
|
78
|
+
}): NewsletterWebhookEvent<Purpose>;
|
|
79
|
+
export declare function requiredNewsletterCapabilityForEvent(eventType: NewsletterSyncEventType): NewsletterProviderCapabilityKey;
|
|
80
|
+
export declare function supportsNewsletterSyncEvent(capabilities: NewsletterProviderCapabilities, eventType: NewsletterSyncEventType): boolean;
|
|
81
|
+
/** Explicit registry binding; legacy schemas above retain their two-purpose default. */
|
|
82
|
+
export declare function createNewsletterIntegrationSchemas<Purpose extends string>(registry: CommunicationPurposeRegistry<Purpose>): {
|
|
83
|
+
purpose: z.ZodCustom<Purpose, Purpose>;
|
|
84
|
+
webhookEvent: z.ZodObject<{
|
|
85
|
+
providerKind: z.ZodString;
|
|
86
|
+
providerEventId: z.ZodString;
|
|
87
|
+
eventType: z.ZodEnum<{
|
|
88
|
+
email_change: "email_change";
|
|
89
|
+
update: "update";
|
|
90
|
+
subscribe: "subscribe";
|
|
91
|
+
unsubscribe: "unsubscribe";
|
|
92
|
+
suppress: "suppress";
|
|
93
|
+
complaint: "complaint";
|
|
94
|
+
bounce: "bounce";
|
|
95
|
+
profile_update: "profile_update";
|
|
96
|
+
ignored: "ignored";
|
|
97
|
+
}>;
|
|
98
|
+
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
99
|
+
remoteProfileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
100
|
+
remoteListId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
101
|
+
explicitOptInEvidence: z.ZodOptional<z.ZodBoolean>;
|
|
102
|
+
doubleOptInStatus: z.ZodOptional<z.ZodEnum<{
|
|
103
|
+
unknown: "unknown";
|
|
104
|
+
confirmed: "confirmed";
|
|
105
|
+
pending: "pending";
|
|
106
|
+
}>>;
|
|
107
|
+
occurredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
108
|
+
payload: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
109
|
+
purpose: z.ZodOptional<z.ZodNullable<z.ZodCustom<Purpose, Purpose>>>;
|
|
110
|
+
}, z.core.$strip>;
|
|
111
|
+
syncEvent: z.ZodObject<{
|
|
112
|
+
id: z.ZodString;
|
|
113
|
+
claimToken: z.ZodString;
|
|
114
|
+
contactId: z.ZodString;
|
|
115
|
+
normalizedEmail: z.ZodString;
|
|
116
|
+
eventType: z.ZodEnum<{
|
|
117
|
+
update: "update";
|
|
118
|
+
subscribe: "subscribe";
|
|
119
|
+
unsubscribe: "unsubscribe";
|
|
120
|
+
suppress: "suppress";
|
|
121
|
+
}>;
|
|
122
|
+
purpose: z.ZodCustom<Purpose, Purpose>;
|
|
123
|
+
payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
124
|
+
attemptCount: z.ZodNumber;
|
|
125
|
+
originProviderKind: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
126
|
+
originProviderEventId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
127
|
+
remoteProfileId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
128
|
+
remoteListId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
129
|
+
}, z.core.$strip>;
|
|
130
|
+
};
|