@bernierllc/email-webhook-events 1.0.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/.eslintrc.cjs +29 -0
- package/README.md +349 -0
- package/__tests__/EmailWebhookEventsService.test.ts +247 -0
- package/__tests__/analytics/AnalyticsEngine.test.ts +244 -0
- package/__tests__/normalizers/MailgunNormalizer.test.ts +149 -0
- package/__tests__/normalizers/PostmarkNormalizer.test.ts +112 -0
- package/__tests__/normalizers/SESNormalizer.test.ts +168 -0
- package/__tests__/normalizers/SMTP2GONormalizer.test.ts +83 -0
- package/__tests__/normalizers/SendGridNormalizer.test.ts +181 -0
- package/__tests__/persistence/PersistenceAdapter.test.ts +103 -0
- package/coverage/clover.xml +328 -0
- package/coverage/coverage-final.json +10 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +161 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/src/EmailWebhookEventsService.ts.html +826 -0
- package/coverage/lcov-report/src/analytics/AnalyticsEngine.ts.html +775 -0
- package/coverage/lcov-report/src/analytics/index.html +116 -0
- package/coverage/lcov-report/src/index.html +131 -0
- package/coverage/lcov-report/src/normalizers/MailgunNormalizer.ts.html +301 -0
- package/coverage/lcov-report/src/normalizers/PostmarkNormalizer.ts.html +301 -0
- package/coverage/lcov-report/src/normalizers/SESNormalizer.ts.html +436 -0
- package/coverage/lcov-report/src/normalizers/SMTP2GONormalizer.ts.html +247 -0
- package/coverage/lcov-report/src/normalizers/SendGridNormalizer.ts.html +274 -0
- package/coverage/lcov-report/src/normalizers/index.html +176 -0
- package/coverage/lcov-report/src/persistence/InMemoryPersistenceAdapter.ts.html +289 -0
- package/coverage/lcov-report/src/persistence/index.html +116 -0
- package/coverage/lcov-report/src/types.ts.html +823 -0
- package/coverage/lcov.info +710 -0
- package/dist/EmailWebhookEventsService.d.ts +53 -0
- package/dist/EmailWebhookEventsService.d.ts.map +1 -0
- package/dist/EmailWebhookEventsService.js +198 -0
- package/dist/EmailWebhookEventsService.js.map +1 -0
- package/dist/analytics/AnalyticsEngine.d.ts +20 -0
- package/dist/analytics/AnalyticsEngine.d.ts.map +1 -0
- package/dist/analytics/AnalyticsEngine.js +160 -0
- package/dist/analytics/AnalyticsEngine.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/normalizers/EventNormalizer.d.ts +5 -0
- package/dist/normalizers/EventNormalizer.d.ts.map +1 -0
- package/dist/normalizers/EventNormalizer.js +10 -0
- package/dist/normalizers/EventNormalizer.js.map +1 -0
- package/dist/normalizers/MailgunNormalizer.d.ts +9 -0
- package/dist/normalizers/MailgunNormalizer.d.ts.map +1 -0
- package/dist/normalizers/MailgunNormalizer.js +73 -0
- package/dist/normalizers/MailgunNormalizer.js.map +1 -0
- package/dist/normalizers/PostmarkNormalizer.d.ts +10 -0
- package/dist/normalizers/PostmarkNormalizer.d.ts.map +1 -0
- package/dist/normalizers/PostmarkNormalizer.js +75 -0
- package/dist/normalizers/PostmarkNormalizer.js.map +1 -0
- package/dist/normalizers/SESNormalizer.d.ts +16 -0
- package/dist/normalizers/SESNormalizer.d.ts.map +1 -0
- package/dist/normalizers/SESNormalizer.js +107 -0
- package/dist/normalizers/SESNormalizer.js.map +1 -0
- package/dist/normalizers/SMTP2GONormalizer.d.ts +9 -0
- package/dist/normalizers/SMTP2GONormalizer.d.ts.map +1 -0
- package/dist/normalizers/SMTP2GONormalizer.js +55 -0
- package/dist/normalizers/SMTP2GONormalizer.js.map +1 -0
- package/dist/normalizers/SendGridNormalizer.d.ts +9 -0
- package/dist/normalizers/SendGridNormalizer.d.ts.map +1 -0
- package/dist/normalizers/SendGridNormalizer.js +64 -0
- package/dist/normalizers/SendGridNormalizer.js.map +1 -0
- package/dist/persistence/InMemoryPersistenceAdapter.d.ts +12 -0
- package/dist/persistence/InMemoryPersistenceAdapter.d.ts.map +1 -0
- package/dist/persistence/InMemoryPersistenceAdapter.js +58 -0
- package/dist/persistence/InMemoryPersistenceAdapter.js.map +1 -0
- package/dist/persistence/PersistenceAdapter.d.ts +7 -0
- package/dist/persistence/PersistenceAdapter.d.ts.map +1 -0
- package/dist/persistence/PersistenceAdapter.js +10 -0
- package/dist/persistence/PersistenceAdapter.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +41 -0
- package/dist/types.js.map +1 -0
- package/jest.config.cjs +29 -0
- package/package.json +51 -0
- package/src/EmailWebhookEventsService.ts +247 -0
- package/src/analytics/AnalyticsEngine.ts +230 -0
- package/src/index.ts +39 -0
- package/src/normalizers/EventNormalizer.ts +13 -0
- package/src/normalizers/MailgunNormalizer.ts +72 -0
- package/src/normalizers/PostmarkNormalizer.ts +72 -0
- package/src/normalizers/SESNormalizer.ts +117 -0
- package/src/normalizers/SMTP2GONormalizer.ts +54 -0
- package/src/normalizers/SendGridNormalizer.ts +63 -0
- package/src/persistence/InMemoryPersistenceAdapter.ts +68 -0
- package/src/persistence/PersistenceAdapter.ts +15 -0
- package/src/types.ts +246 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EventNormalizer } from './EventNormalizer';
|
|
2
|
+
import { EmailEvent, WebhookPayload } from '../types';
|
|
3
|
+
export declare class PostmarkNormalizer implements EventNormalizer {
|
|
4
|
+
normalize(webhook: WebhookPayload): EmailEvent;
|
|
5
|
+
private mapEventType;
|
|
6
|
+
private mapBounceType;
|
|
7
|
+
private generateEventId;
|
|
8
|
+
private detectDeviceType;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=PostmarkNormalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostmarkNormalizer.d.ts","sourceRoot":"","sources":["../../src/normalizers/PostmarkNormalizer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAiC,cAAc,EAAE,MAAM,UAAU,CAAC;AAErF,qBAAa,kBAAmB,YAAW,eAAe;IACxD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU;IA6B9C,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;CAOzB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.PostmarkNormalizer = void 0;
|
|
11
|
+
const types_1 = require("../types");
|
|
12
|
+
class PostmarkNormalizer {
|
|
13
|
+
normalize(webhook) {
|
|
14
|
+
const event = webhook.payload;
|
|
15
|
+
return {
|
|
16
|
+
id: this.generateEventId(event),
|
|
17
|
+
emailId: event.MessageID || '',
|
|
18
|
+
messageId: event.MessageID || '',
|
|
19
|
+
type: this.mapEventType(event.RecordType),
|
|
20
|
+
recipient: event.Recipient || '',
|
|
21
|
+
timestamp: new Date(event.ReceivedAt),
|
|
22
|
+
provider: types_1.EmailProvider.POSTMARK,
|
|
23
|
+
metadata: {
|
|
24
|
+
url: event.OriginalLink,
|
|
25
|
+
bounceType: this.mapBounceType(event.Type),
|
|
26
|
+
bounceReason: event.Description,
|
|
27
|
+
bounceCode: event.TypeCode?.toString(),
|
|
28
|
+
complaintFeedbackType: event.Type,
|
|
29
|
+
userAgent: event.UserAgent,
|
|
30
|
+
deviceType: this.detectDeviceType(event.UserAgent),
|
|
31
|
+
location: {
|
|
32
|
+
country: event.Geo?.Country,
|
|
33
|
+
region: event.Geo?.Region,
|
|
34
|
+
city: event.Geo?.City
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
rawEvent: event
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
mapEventType(postmarkEvent) {
|
|
41
|
+
const mapping = {
|
|
42
|
+
'Delivery': types_1.EmailEventType.DELIVERED,
|
|
43
|
+
'Open': types_1.EmailEventType.OPENED,
|
|
44
|
+
'Click': types_1.EmailEventType.CLICKED,
|
|
45
|
+
'Bounce': types_1.EmailEventType.BOUNCED,
|
|
46
|
+
'SpamComplaint': types_1.EmailEventType.COMPLAINED,
|
|
47
|
+
'SubscriptionChange': types_1.EmailEventType.UNSUBSCRIBED
|
|
48
|
+
};
|
|
49
|
+
return mapping[postmarkEvent] || types_1.EmailEventType.FAILED;
|
|
50
|
+
}
|
|
51
|
+
mapBounceType(bounceType) {
|
|
52
|
+
if (!bounceType)
|
|
53
|
+
return undefined;
|
|
54
|
+
if (bounceType.includes('Hard'))
|
|
55
|
+
return 'hard';
|
|
56
|
+
if (bounceType.includes('Soft'))
|
|
57
|
+
return 'soft';
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
generateEventId(event) {
|
|
61
|
+
return `postmark-${event.MessageID || ''}-${Date.now()}`;
|
|
62
|
+
}
|
|
63
|
+
detectDeviceType(userAgent) {
|
|
64
|
+
if (!userAgent)
|
|
65
|
+
return 'unknown';
|
|
66
|
+
const ua = userAgent.toLowerCase();
|
|
67
|
+
if (ua.includes('mobile'))
|
|
68
|
+
return 'mobile';
|
|
69
|
+
if (ua.includes('tablet') || ua.includes('ipad'))
|
|
70
|
+
return 'tablet';
|
|
71
|
+
return 'desktop';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.PostmarkNormalizer = PostmarkNormalizer;
|
|
75
|
+
//# sourceMappingURL=PostmarkNormalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostmarkNormalizer.js","sourceRoot":"","sources":["../../src/normalizers/PostmarkNormalizer.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAGF,oCAAqF;AAErF,MAAa,kBAAkB;IAC7B,SAAS,CAAC,OAAuB;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAkC,CAAC;QAEzD,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;YAC/B,OAAO,EAAG,KAAK,CAAC,SAAoB,IAAI,EAAE;YAC1C,SAAS,EAAG,KAAK,CAAC,SAAoB,IAAI,EAAE;YAC5C,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAoB,CAAC;YACnD,SAAS,EAAG,KAAK,CAAC,SAAoB,IAAI,EAAE;YAC5C,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,UAAoB,CAAC;YAC/C,QAAQ,EAAE,qBAAa,CAAC,QAAQ;YAChC,QAAQ,EAAE;gBACR,GAAG,EAAE,KAAK,CAAC,YAAkC;gBAC7C,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAA0B,CAAC;gBAChE,YAAY,EAAE,KAAK,CAAC,WAAiC;gBACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACtC,qBAAqB,EAAE,KAAK,CAAC,IAA0B;gBACvD,SAAS,EAAE,KAAK,CAAC,SAA+B;gBAChD,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,SAA+B,CAAC;gBACxE,QAAQ,EAAE;oBACR,OAAO,EAAG,KAAK,CAAC,GAA0C,EAAE,OAAO;oBACnE,MAAM,EAAG,KAAK,CAAC,GAA0C,EAAE,MAAM;oBACjE,IAAI,EAAG,KAAK,CAAC,GAA0C,EAAE,IAAI;iBAC9D;aACF;YACD,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,aAAqB;QACxC,MAAM,OAAO,GAAmC;YAC9C,UAAU,EAAE,sBAAc,CAAC,SAAS;YACpC,MAAM,EAAE,sBAAc,CAAC,MAAM;YAC7B,OAAO,EAAE,sBAAc,CAAC,OAAO;YAC/B,QAAQ,EAAE,sBAAc,CAAC,OAAO;YAChC,eAAe,EAAE,sBAAc,CAAC,UAAU;YAC1C,oBAAoB,EAAE,sBAAc,CAAC,YAAY;SAClD,CAAC;QACF,OAAO,OAAO,CAAC,aAAa,CAAC,IAAI,sBAAc,CAAC,MAAM,CAAC;IACzD,CAAC;IAEO,aAAa,CAAC,UAAmB;QACvC,IAAI,CAAC,UAAU;YAAE,OAAO,SAAS,CAAC;QAClC,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QAC/C,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QAC/C,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,eAAe,CAAC,KAA8B;QACpD,OAAO,YAAa,KAAK,CAAC,SAAoB,IAAI,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACvE,CAAC;IAEO,gBAAgB,CAAC,SAAkB;QACzC,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QACjC,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,QAAQ,CAAC;QAC3C,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,QAAQ,CAAC;QAClE,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AA5DD,gDA4DC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EventNormalizer } from './EventNormalizer';
|
|
2
|
+
import { EmailEvent, WebhookPayload } from '../types';
|
|
3
|
+
export declare class SESNormalizer implements EventNormalizer {
|
|
4
|
+
normalize(webhook: WebhookPayload): EmailEvent;
|
|
5
|
+
private mapEventType;
|
|
6
|
+
private extractMessageId;
|
|
7
|
+
private extractRecipient;
|
|
8
|
+
private extractBounceType;
|
|
9
|
+
private extractBounceReason;
|
|
10
|
+
private extractComplaintType;
|
|
11
|
+
private extractClickUrl;
|
|
12
|
+
private extractIpAddress;
|
|
13
|
+
private extractUserAgent;
|
|
14
|
+
private generateEventId;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=SESNormalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SESNormalizer.d.ts","sourceRoot":"","sources":["../../src/normalizers/SESNormalizer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAiC,cAAc,EAAE,MAAM,UAAU,CAAC;AAErF,qBAAa,aAAc,YAAW,eAAe;IACnD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU;IAyB9C,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,eAAe;CAIxB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SESNormalizer = void 0;
|
|
11
|
+
const types_1 = require("../types");
|
|
12
|
+
class SESNormalizer {
|
|
13
|
+
normalize(webhook) {
|
|
14
|
+
const payload = webhook.payload;
|
|
15
|
+
const message = JSON.parse(payload.Message);
|
|
16
|
+
const eventType = message.eventType;
|
|
17
|
+
return {
|
|
18
|
+
id: this.generateEventId(message),
|
|
19
|
+
emailId: this.extractMessageId(message),
|
|
20
|
+
messageId: this.extractMessageId(message),
|
|
21
|
+
type: this.mapEventType(eventType),
|
|
22
|
+
recipient: this.extractRecipient(message),
|
|
23
|
+
timestamp: new Date(message.mail.timestamp),
|
|
24
|
+
provider: types_1.EmailProvider.AWS_SES,
|
|
25
|
+
metadata: {
|
|
26
|
+
bounceType: this.extractBounceType(message),
|
|
27
|
+
bounceReason: this.extractBounceReason(message),
|
|
28
|
+
complaintFeedbackType: this.extractComplaintType(message),
|
|
29
|
+
url: this.extractClickUrl(message),
|
|
30
|
+
ipAddress: this.extractIpAddress(message),
|
|
31
|
+
userAgent: this.extractUserAgent(message)
|
|
32
|
+
},
|
|
33
|
+
rawEvent: message
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
mapEventType(sesEvent) {
|
|
37
|
+
const mapping = {
|
|
38
|
+
'Delivery': types_1.EmailEventType.DELIVERED,
|
|
39
|
+
'Open': types_1.EmailEventType.OPENED,
|
|
40
|
+
'Click': types_1.EmailEventType.CLICKED,
|
|
41
|
+
'Bounce': types_1.EmailEventType.BOUNCED,
|
|
42
|
+
'Complaint': types_1.EmailEventType.COMPLAINED,
|
|
43
|
+
'Reject': types_1.EmailEventType.FAILED
|
|
44
|
+
};
|
|
45
|
+
return mapping[sesEvent] || types_1.EmailEventType.FAILED;
|
|
46
|
+
}
|
|
47
|
+
extractMessageId(message) {
|
|
48
|
+
const mail = message.mail;
|
|
49
|
+
return mail?.messageId || '';
|
|
50
|
+
}
|
|
51
|
+
extractRecipient(message) {
|
|
52
|
+
const bounce = message.bounce;
|
|
53
|
+
const complaint = message.complaint;
|
|
54
|
+
const mail = message.mail;
|
|
55
|
+
if (bounce) {
|
|
56
|
+
const bouncedRecipients = bounce.bouncedRecipients;
|
|
57
|
+
if (bouncedRecipients?.[0]?.emailAddress) {
|
|
58
|
+
return bouncedRecipients[0].emailAddress;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (complaint) {
|
|
62
|
+
const complainedRecipients = complaint.complainedRecipients;
|
|
63
|
+
if (complainedRecipients?.[0]?.emailAddress) {
|
|
64
|
+
return complainedRecipients[0].emailAddress;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const destination = mail.destination;
|
|
68
|
+
return destination?.[0] || '';
|
|
69
|
+
}
|
|
70
|
+
extractBounceType(message) {
|
|
71
|
+
const bounce = message.bounce;
|
|
72
|
+
if (!bounce)
|
|
73
|
+
return undefined;
|
|
74
|
+
return bounce.bounceType?.toLowerCase();
|
|
75
|
+
}
|
|
76
|
+
extractBounceReason(message) {
|
|
77
|
+
const bounce = message.bounce;
|
|
78
|
+
if (!bounce)
|
|
79
|
+
return undefined;
|
|
80
|
+
const bouncedRecipients = bounce.bouncedRecipients;
|
|
81
|
+
return bouncedRecipients?.[0]?.diagnosticCode;
|
|
82
|
+
}
|
|
83
|
+
extractComplaintType(message) {
|
|
84
|
+
const complaint = message.complaint;
|
|
85
|
+
return complaint?.complaintFeedbackType;
|
|
86
|
+
}
|
|
87
|
+
extractClickUrl(message) {
|
|
88
|
+
const click = message.click;
|
|
89
|
+
return click?.link;
|
|
90
|
+
}
|
|
91
|
+
extractIpAddress(message) {
|
|
92
|
+
const open = message.open;
|
|
93
|
+
const click = message.click;
|
|
94
|
+
return open?.ipAddress || click?.ipAddress || undefined;
|
|
95
|
+
}
|
|
96
|
+
extractUserAgent(message) {
|
|
97
|
+
const open = message.open;
|
|
98
|
+
const click = message.click;
|
|
99
|
+
return open?.userAgent || click?.userAgent || undefined;
|
|
100
|
+
}
|
|
101
|
+
generateEventId(message) {
|
|
102
|
+
const mail = message.mail;
|
|
103
|
+
return `ses-${mail?.messageId || ''}-${Date.now()}`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.SESNormalizer = SESNormalizer;
|
|
107
|
+
//# sourceMappingURL=SESNormalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SESNormalizer.js","sourceRoot":"","sources":["../../src/normalizers/SESNormalizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EventNormalizer } from './EventNormalizer';
|
|
2
|
+
import { EmailEvent, WebhookPayload } from '../types';
|
|
3
|
+
export declare class SMTP2GONormalizer implements EventNormalizer {
|
|
4
|
+
normalize(webhook: WebhookPayload): EmailEvent;
|
|
5
|
+
private mapEventType;
|
|
6
|
+
private mapBounceType;
|
|
7
|
+
private generateEventId;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=SMTP2GONormalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SMTP2GONormalizer.d.ts","sourceRoot":"","sources":["../../src/normalizers/SMTP2GONormalizer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAiC,cAAc,EAAE,MAAM,UAAU,CAAC;AAErF,qBAAa,iBAAkB,YAAW,eAAe;IACvD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU;IAoB9C,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,eAAe;CAGxB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SMTP2GONormalizer = void 0;
|
|
11
|
+
const types_1 = require("../types");
|
|
12
|
+
class SMTP2GONormalizer {
|
|
13
|
+
normalize(webhook) {
|
|
14
|
+
const event = webhook.payload;
|
|
15
|
+
return {
|
|
16
|
+
id: this.generateEventId(event),
|
|
17
|
+
emailId: event.email_id || event.message_id || '',
|
|
18
|
+
messageId: event.message_id || '',
|
|
19
|
+
type: this.mapEventType(event.event),
|
|
20
|
+
recipient: event.rcpt_to || '',
|
|
21
|
+
timestamp: new Date(event.timestamp),
|
|
22
|
+
provider: types_1.EmailProvider.SMTP2GO,
|
|
23
|
+
metadata: {
|
|
24
|
+
bounceType: this.mapBounceType(event.bounce_type),
|
|
25
|
+
bounceReason: event.reason,
|
|
26
|
+
failureReason: event.reason
|
|
27
|
+
},
|
|
28
|
+
rawEvent: event
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
mapEventType(smtp2goEvent) {
|
|
32
|
+
const mapping = {
|
|
33
|
+
'delivered': types_1.EmailEventType.DELIVERED,
|
|
34
|
+
'open': types_1.EmailEventType.OPENED,
|
|
35
|
+
'click': types_1.EmailEventType.CLICKED,
|
|
36
|
+
'bounce': types_1.EmailEventType.BOUNCED,
|
|
37
|
+
'failed': types_1.EmailEventType.FAILED
|
|
38
|
+
};
|
|
39
|
+
return mapping[smtp2goEvent] || types_1.EmailEventType.FAILED;
|
|
40
|
+
}
|
|
41
|
+
mapBounceType(bounceType) {
|
|
42
|
+
if (!bounceType)
|
|
43
|
+
return undefined;
|
|
44
|
+
if (bounceType.toLowerCase().includes('hard'))
|
|
45
|
+
return 'hard';
|
|
46
|
+
if (bounceType.toLowerCase().includes('soft'))
|
|
47
|
+
return 'soft';
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
generateEventId(event) {
|
|
51
|
+
return `smtp2go-${event.message_id || ''}-${Date.now()}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.SMTP2GONormalizer = SMTP2GONormalizer;
|
|
55
|
+
//# sourceMappingURL=SMTP2GONormalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SMTP2GONormalizer.js","sourceRoot":"","sources":["../../src/normalizers/SMTP2GONormalizer.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAGF,oCAAqF;AAErF,MAAa,iBAAiB;IAC5B,SAAS,CAAC,OAAuB;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAkC,CAAC;QAEzD,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;YAC/B,OAAO,EAAG,KAAK,CAAC,QAAmB,IAAK,KAAK,CAAC,UAAqB,IAAI,EAAE;YACzE,SAAS,EAAG,KAAK,CAAC,UAAqB,IAAI,EAAE;YAC7C,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAe,CAAC;YAC9C,SAAS,EAAG,KAAK,CAAC,OAAkB,IAAI,EAAE;YAC1C,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,SAAmB,CAAC;YAC9C,QAAQ,EAAE,qBAAa,CAAC,OAAO;YAC/B,QAAQ,EAAE;gBACR,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,WAAiC,CAAC;gBACvE,YAAY,EAAE,KAAK,CAAC,MAA4B;gBAChD,aAAa,EAAE,KAAK,CAAC,MAA4B;aAClD;YACD,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,YAAoB;QACvC,MAAM,OAAO,GAAmC;YAC9C,WAAW,EAAE,sBAAc,CAAC,SAAS;YACrC,MAAM,EAAE,sBAAc,CAAC,MAAM;YAC7B,OAAO,EAAE,sBAAc,CAAC,OAAO;YAC/B,QAAQ,EAAE,sBAAc,CAAC,OAAO;YAChC,QAAQ,EAAE,sBAAc,CAAC,MAAM;SAChC,CAAC;QACF,OAAO,OAAO,CAAC,YAAY,CAAC,IAAI,sBAAc,CAAC,MAAM,CAAC;IACxD,CAAC;IAEO,aAAa,CAAC,UAAmB;QACvC,IAAI,CAAC,UAAU;YAAE,OAAO,SAAS,CAAC;QAClC,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QAC7D,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,eAAe,CAAC,KAA8B;QACpD,OAAO,WAAY,KAAK,CAAC,UAAqB,IAAI,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACvE,CAAC;CACF;AA1CD,8CA0CC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EventNormalizer } from './EventNormalizer';
|
|
2
|
+
import { EmailEvent, WebhookPayload } from '../types';
|
|
3
|
+
export declare class SendGridNormalizer implements EventNormalizer {
|
|
4
|
+
normalize(webhook: WebhookPayload): EmailEvent;
|
|
5
|
+
private mapEventType;
|
|
6
|
+
private generateEventId;
|
|
7
|
+
private detectDeviceType;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=SendGridNormalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SendGridNormalizer.d.ts","sourceRoot":"","sources":["../../src/normalizers/SendGridNormalizer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAiC,cAAc,EAAE,MAAM,UAAU,CAAC;AAErF,qBAAa,kBAAmB,YAAW,eAAe;IACxD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU;IAyB9C,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;CAOzB"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SendGridNormalizer = void 0;
|
|
11
|
+
const types_1 = require("../types");
|
|
12
|
+
class SendGridNormalizer {
|
|
13
|
+
normalize(webhook) {
|
|
14
|
+
const event = webhook.payload;
|
|
15
|
+
return {
|
|
16
|
+
id: this.generateEventId(event),
|
|
17
|
+
emailId: event.email_id || event.sg_message_id || '',
|
|
18
|
+
messageId: event.sg_message_id || '',
|
|
19
|
+
type: this.mapEventType(event.event),
|
|
20
|
+
recipient: event.email || '',
|
|
21
|
+
timestamp: new Date(event.timestamp * 1000),
|
|
22
|
+
provider: types_1.EmailProvider.SENDGRID,
|
|
23
|
+
metadata: {
|
|
24
|
+
url: event.url,
|
|
25
|
+
bounceType: event.event === 'bounce'
|
|
26
|
+
? (event.status?.startsWith('5') ? 'hard' : 'soft')
|
|
27
|
+
: undefined,
|
|
28
|
+
bounceReason: event.reason,
|
|
29
|
+
userAgent: event.useragent,
|
|
30
|
+
ipAddress: event.ip,
|
|
31
|
+
deviceType: this.detectDeviceType(event.useragent)
|
|
32
|
+
},
|
|
33
|
+
rawEvent: event
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
mapEventType(sendgridEvent) {
|
|
37
|
+
const mapping = {
|
|
38
|
+
'delivered': types_1.EmailEventType.DELIVERED,
|
|
39
|
+
'open': types_1.EmailEventType.OPENED,
|
|
40
|
+
'click': types_1.EmailEventType.CLICKED,
|
|
41
|
+
'bounce': types_1.EmailEventType.BOUNCED,
|
|
42
|
+
'dropped': types_1.EmailEventType.DROPPED,
|
|
43
|
+
'spamreport': types_1.EmailEventType.COMPLAINED,
|
|
44
|
+
'unsubscribe': types_1.EmailEventType.UNSUBSCRIBED,
|
|
45
|
+
'deferred': types_1.EmailEventType.DEFERRED
|
|
46
|
+
};
|
|
47
|
+
return mapping[sendgridEvent] || types_1.EmailEventType.FAILED;
|
|
48
|
+
}
|
|
49
|
+
generateEventId(event) {
|
|
50
|
+
return `sendgrid-${event.sg_event_id || Date.now()}`;
|
|
51
|
+
}
|
|
52
|
+
detectDeviceType(userAgent) {
|
|
53
|
+
if (!userAgent)
|
|
54
|
+
return 'unknown';
|
|
55
|
+
const ua = userAgent.toLowerCase();
|
|
56
|
+
if (ua.includes('mobile'))
|
|
57
|
+
return 'mobile';
|
|
58
|
+
if (ua.includes('tablet') || ua.includes('ipad'))
|
|
59
|
+
return 'tablet';
|
|
60
|
+
return 'desktop';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.SendGridNormalizer = SendGridNormalizer;
|
|
64
|
+
//# sourceMappingURL=SendGridNormalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SendGridNormalizer.js","sourceRoot":"","sources":["../../src/normalizers/SendGridNormalizer.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAGF,oCAAqF;AAErF,MAAa,kBAAkB;IAC7B,SAAS,CAAC,OAAuB;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAkC,CAAC;QAEzD,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;YAC/B,OAAO,EAAG,KAAK,CAAC,QAAmB,IAAK,KAAK,CAAC,aAAwB,IAAI,EAAE;YAC5E,SAAS,EAAG,KAAK,CAAC,aAAwB,IAAI,EAAE;YAChD,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,KAAe,CAAC;YAC9C,SAAS,EAAG,KAAK,CAAC,KAAgB,IAAI,EAAE;YACxC,SAAS,EAAE,IAAI,IAAI,CAAE,KAAK,CAAC,SAAoB,GAAG,IAAI,CAAC;YACvD,QAAQ,EAAE,qBAAa,CAAC,QAAQ;YAChC,QAAQ,EAAE;gBACR,GAAG,EAAE,KAAK,CAAC,GAAyB;gBACpC,UAAU,EAAE,KAAK,CAAC,KAAK,KAAK,QAAQ;oBAClC,CAAC,CAAC,CAAE,KAAK,CAAC,MAAiB,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;oBAC/D,CAAC,CAAC,SAAS;gBACb,YAAY,EAAE,KAAK,CAAC,MAA4B;gBAChD,SAAS,EAAE,KAAK,CAAC,SAA+B;gBAChD,SAAS,EAAE,KAAK,CAAC,EAAwB;gBACzC,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,SAA+B,CAAC;aACzE;YACD,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,aAAqB;QACxC,MAAM,OAAO,GAAmC;YAC9C,WAAW,EAAE,sBAAc,CAAC,SAAS;YACrC,MAAM,EAAE,sBAAc,CAAC,MAAM;YAC7B,OAAO,EAAE,sBAAc,CAAC,OAAO;YAC/B,QAAQ,EAAE,sBAAc,CAAC,OAAO;YAChC,SAAS,EAAE,sBAAc,CAAC,OAAO;YACjC,YAAY,EAAE,sBAAc,CAAC,UAAU;YACvC,aAAa,EAAE,sBAAc,CAAC,YAAY;YAC1C,UAAU,EAAE,sBAAc,CAAC,QAAQ;SACpC,CAAC;QACF,OAAO,OAAO,CAAC,aAAa,CAAC,IAAI,sBAAc,CAAC,MAAM,CAAC;IACzD,CAAC;IAEO,eAAe,CAAC,KAA8B;QACpD,OAAO,YAAa,KAAK,CAAC,WAAsB,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACnE,CAAC;IAEO,gBAAgB,CAAC,SAAkB;QACzC,IAAI,CAAC,SAAS;YAAE,OAAO,SAAS,CAAC;QACjC,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,QAAQ,CAAC;QAC3C,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,QAAQ,CAAC;QAClE,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAnDD,gDAmDC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PersistenceAdapter } from './PersistenceAdapter';
|
|
2
|
+
import { EmailEvent, EventQuery } from '../types';
|
|
3
|
+
export declare class InMemoryPersistenceAdapter implements PersistenceAdapter {
|
|
4
|
+
private events;
|
|
5
|
+
private sentEmails;
|
|
6
|
+
saveEvent(event: EmailEvent): Promise<void>;
|
|
7
|
+
queryEvents(query: EventQuery): Promise<EmailEvent[]>;
|
|
8
|
+
saveSentEmail(emailData: unknown): Promise<void>;
|
|
9
|
+
getEventCount(): number;
|
|
10
|
+
clearEvents(): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=InMemoryPersistenceAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InMemoryPersistenceAdapter.d.ts","sourceRoot":"","sources":["../../src/persistence/InMemoryPersistenceAdapter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAElD,qBAAa,0BAA2B,YAAW,kBAAkB;IACnE,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,UAAU,CAAiB;IAE7B,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAmCrD,aAAa,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD,aAAa,IAAI,MAAM;IAIvB,WAAW,IAAI,IAAI;CAIpB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.InMemoryPersistenceAdapter = void 0;
|
|
11
|
+
class InMemoryPersistenceAdapter {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.events = [];
|
|
14
|
+
this.sentEmails = [];
|
|
15
|
+
}
|
|
16
|
+
async saveEvent(event) {
|
|
17
|
+
this.events.push(event);
|
|
18
|
+
}
|
|
19
|
+
async queryEvents(query) {
|
|
20
|
+
let results = [...this.events];
|
|
21
|
+
if (query.emailId) {
|
|
22
|
+
results = results.filter(e => e.emailId === query.emailId);
|
|
23
|
+
}
|
|
24
|
+
if (query.recipient) {
|
|
25
|
+
results = results.filter(e => e.recipient === query.recipient);
|
|
26
|
+
}
|
|
27
|
+
if (query.eventTypes && query.eventTypes.length > 0) {
|
|
28
|
+
results = results.filter(e => query.eventTypes.includes(e.type));
|
|
29
|
+
}
|
|
30
|
+
if (query.startDate) {
|
|
31
|
+
results = results.filter(e => e.timestamp >= query.startDate);
|
|
32
|
+
}
|
|
33
|
+
if (query.endDate) {
|
|
34
|
+
results = results.filter(e => e.timestamp <= query.endDate);
|
|
35
|
+
}
|
|
36
|
+
// Apply offset and limit
|
|
37
|
+
if (query.offset) {
|
|
38
|
+
results = results.slice(query.offset);
|
|
39
|
+
}
|
|
40
|
+
if (query.limit) {
|
|
41
|
+
results = results.slice(0, query.limit);
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
async saveSentEmail(emailData) {
|
|
46
|
+
this.sentEmails.push(emailData);
|
|
47
|
+
}
|
|
48
|
+
// Test helper methods
|
|
49
|
+
getEventCount() {
|
|
50
|
+
return this.events.length;
|
|
51
|
+
}
|
|
52
|
+
clearEvents() {
|
|
53
|
+
this.events = [];
|
|
54
|
+
this.sentEmails = [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.InMemoryPersistenceAdapter = InMemoryPersistenceAdapter;
|
|
58
|
+
//# sourceMappingURL=InMemoryPersistenceAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InMemoryPersistenceAdapter.js","sourceRoot":"","sources":["../../src/persistence/InMemoryPersistenceAdapter.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAKF,MAAa,0BAA0B;IAAvC;QACU,WAAM,GAAiB,EAAE,CAAC;QAC1B,eAAU,GAAc,EAAE,CAAC;IAsDrC,CAAC;IApDC,KAAK,CAAC,SAAS,CAAC,KAAiB;QAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAiB;QACjC,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAE/B,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,SAAU,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,OAAQ,CAAC,CAAC;QAC/D,CAAC;QAED,yBAAyB;QACzB,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAkB;QACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,sBAAsB;IACtB,aAAa;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACvB,CAAC;CACF;AAxDD,gEAwDC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EmailEvent, EventQuery } from '../types';
|
|
2
|
+
export interface PersistenceAdapter {
|
|
3
|
+
saveEvent(event: EmailEvent): Promise<void>;
|
|
4
|
+
queryEvents(query: EventQuery): Promise<EmailEvent[]>;
|
|
5
|
+
saveSentEmail?(emailData: unknown): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=PersistenceAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistenceAdapter.d.ts","sourceRoot":"","sources":["../../src/persistence/PersistenceAdapter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACtD,aAAa,CAAC,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
//# sourceMappingURL=PersistenceAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistenceAdapter.js","sourceRoot":"","sources":["../../src/persistence/PersistenceAdapter.ts"],"names":[],"mappings":";AAAA;;;;;;EAME"}
|