@quatrain/messaging 1.0.2 → 1.0.4
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/LICENSE.md +15 -0
- package/lib/AbstractMessagingAdapter.d.ts +0 -3
- package/lib/AbstractMessagingAdapter.js +0 -7
- package/lib/MessageFormatter.d.ts +1 -3
- package/lib/MessageFormatter.js +2 -2
- package/lib/Messaging.d.ts +8 -8
- package/lib/Messaging.js +9 -9
- package/lib/Messaging.test.d.ts +1 -0
- package/lib/Messaging.test.js +258 -0
- package/lib/MockMessagingAdapter.d.ts +32 -0
- package/lib/MockMessagingAdapter.js +131 -0
- package/lib/index.d.ts +3 -2
- package/lib/index.js +3 -1
- package/lib/types/{AbstractMessage.d.ts → MessageType.d.ts} +1 -1
- package/lib/types/NotificationCapableAdapter.d.ts +1 -2
- package/lib/types/NotificationMessage.d.ts +2 -2
- package/lib/types/TextCapableAdapter.d.ts +6 -0
- package/package.json +38 -40
- package/src/AbstractMessagingAdapter.ts +9 -0
- package/src/MessageFormatter.ts +11 -0
- package/src/Messaging.test.ts +318 -0
- package/src/Messaging.ts +44 -0
- package/src/MockMessagingAdapter.ts +163 -0
- package/src/index.ts +20 -0
- package/src/types/EmailCapableAdapter.ts +14 -0
- package/src/types/MessageType.ts +6 -0
- package/src/types/MessagingRecipient.ts +6 -0
- package/src/types/MessagingTemplate.ts +3 -0
- package/src/types/NotificationCapableAdapter.ts +14 -0
- package/src/types/NotificationMessage.ts +3 -0
- package/src/types/TextCapableAdapter.ts +14 -0
- package/lib/types/MessagingInterface.d.ts +0 -6
- /package/lib/types/{AbstractMessage.js → MessageType.js} +0 -0
- /package/lib/types/{MessagingInterface.js → TextCapableAdapter.js} +0 -0
package/package.json
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
}
|
|
2
|
+
"name": "@quatrain/messaging",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"license": "AGPL-3.0-only",
|
|
5
|
+
"description": "Messaging adapters commons",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"bun": "src/index.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"LICENSE.md",
|
|
11
|
+
"src/",
|
|
12
|
+
"lib/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"author": "Quatrain Développement SAS <developers@quatrain.com>",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@quatrain/core": "^1.1.43",
|
|
18
|
+
"mustache": "^4.2.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@tsconfig/recommended": "^1.0.1",
|
|
22
|
+
"@types/jest": "^27.0.3",
|
|
23
|
+
"@types/mustache": "^4",
|
|
24
|
+
"@types/node": "^22.10.1",
|
|
25
|
+
"jest": "^30.2.0",
|
|
26
|
+
"jest-node-exports-resolver": "^1.1.6",
|
|
27
|
+
"jest-serial-runner": "^1.2.1",
|
|
28
|
+
"trace-unhandled": "^2.0.1",
|
|
29
|
+
"ts-jest": "^27.1.2",
|
|
30
|
+
"ts-node": "^10.9.1",
|
|
31
|
+
"typescript": "^5.1.5"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"test-ci": "jest --runInBand",
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"wbuild": "tsc --watch",
|
|
37
|
+
"bump-to": "yarn version"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { Messaging, MessagingParameters } from './Messaging'
|
|
2
|
+
import { MockMessagingAdapter } from './MockMessagingAdapter'
|
|
3
|
+
import { MessagingRecipient } from './types/MessagingRecipient'
|
|
4
|
+
import { NotificationMessage } from './types/NotificationMessage'
|
|
5
|
+
|
|
6
|
+
describe('Messaging', () => {
|
|
7
|
+
let mockAdapter1: MockMessagingAdapter
|
|
8
|
+
let mockAdapter2: MockMessagingAdapter
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// Reset messagers before each test
|
|
12
|
+
;(Messaging as any)._messagers = {}
|
|
13
|
+
Messaging.defaultMessager = 'default'
|
|
14
|
+
|
|
15
|
+
// Create fresh mock adapters
|
|
16
|
+
mockAdapter1 = new MockMessagingAdapter({ debug: false })
|
|
17
|
+
mockAdapter2 = new MockMessagingAdapter({ debug: false })
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
// Clean up
|
|
22
|
+
mockAdapter1?.clearMessages()
|
|
23
|
+
mockAdapter2?.clearMessages()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe('addMessager', () => {
|
|
27
|
+
it('should add a messager with an alias', () => {
|
|
28
|
+
Messaging.addMessager(mockAdapter1, 'test-messager')
|
|
29
|
+
|
|
30
|
+
const messager = Messaging.getMessager('test-messager')
|
|
31
|
+
expect(messager).toBe(mockAdapter1)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should add multiple messagers with different aliases', () => {
|
|
35
|
+
Messaging.addMessager(mockAdapter1, 'messager1')
|
|
36
|
+
Messaging.addMessager(mockAdapter2, 'messager2')
|
|
37
|
+
|
|
38
|
+
const messager1 = Messaging.getMessager('messager1')
|
|
39
|
+
const messager2 = Messaging.getMessager('messager2')
|
|
40
|
+
|
|
41
|
+
expect(messager1).toBe(mockAdapter1)
|
|
42
|
+
expect(messager2).toBe(mockAdapter2)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should set default messager when setDefault is true', () => {
|
|
46
|
+
Messaging.addMessager(mockAdapter1, 'custom-messager', true)
|
|
47
|
+
|
|
48
|
+
expect(Messaging.defaultMessager).toBe('custom-messager')
|
|
49
|
+
const messager = Messaging.getMessager() // Should use default
|
|
50
|
+
expect(messager).toBe(mockAdapter1)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('should not change default messager when setDefault is false', () => {
|
|
54
|
+
const originalDefault = Messaging.defaultMessager
|
|
55
|
+
Messaging.addMessager(mockAdapter1, 'custom-messager', false)
|
|
56
|
+
|
|
57
|
+
expect(Messaging.defaultMessager).toBe(originalDefault)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should allow overriding an existing messager', () => {
|
|
61
|
+
Messaging.addMessager(mockAdapter1, 'messager')
|
|
62
|
+
Messaging.addMessager(mockAdapter2, 'messager')
|
|
63
|
+
|
|
64
|
+
const messager = Messaging.getMessager('messager')
|
|
65
|
+
expect(messager).toBe(mockAdapter2)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe('getMessager', () => {
|
|
70
|
+
it('should return the correct messager by alias', () => {
|
|
71
|
+
Messaging.addMessager(mockAdapter1, 'test-messager')
|
|
72
|
+
|
|
73
|
+
const messager = Messaging.getMessager('test-messager')
|
|
74
|
+
expect(messager).toBe(mockAdapter1)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('should return the default messager when no alias is specified', () => {
|
|
78
|
+
Messaging.addMessager(mockAdapter1, 'default', true)
|
|
79
|
+
|
|
80
|
+
const messager = Messaging.getMessager()
|
|
81
|
+
expect(messager).toBe(mockAdapter1)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('should throw error when messager alias does not exist', () => {
|
|
85
|
+
expect(() => {
|
|
86
|
+
Messaging.getMessager('non-existent')
|
|
87
|
+
}).toThrow("Unknown messager alias: 'non-existent'")
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should throw error when getting default messager that does not exist', () => {
|
|
91
|
+
expect(() => {
|
|
92
|
+
Messaging.getMessager()
|
|
93
|
+
}).toThrow("Unknown messager alias: 'default'")
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
describe('defaultMessager property', () => {
|
|
98
|
+
it('should have a default value of "default"', () => {
|
|
99
|
+
expect(Messaging.defaultMessager).toBe('default')
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('should allow changing the default messager', () => {
|
|
103
|
+
Messaging.addMessager(mockAdapter1, 'new-default', true)
|
|
104
|
+
expect(Messaging.defaultMessager).toBe('new-default')
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
describe('Integration with MockMessagingAdapter - Notifications', () => {
|
|
109
|
+
const recipient: MessagingRecipient = {
|
|
110
|
+
firstname: 'John',
|
|
111
|
+
lastname: 'Doe',
|
|
112
|
+
email: 'john@example.com',
|
|
113
|
+
messageToken: 'test-token-123',
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const message: NotificationMessage = {
|
|
117
|
+
title: 'Test Notification',
|
|
118
|
+
body: 'This is a test',
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
it('should send single notification', async () => {
|
|
122
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
123
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
124
|
+
|
|
125
|
+
const result = await messager.sendNotification(recipient, message)
|
|
126
|
+
|
|
127
|
+
expect(result.success).toBe(true)
|
|
128
|
+
expect(result.messageId).toMatch(/^notif-/)
|
|
129
|
+
expect(messager.getMessageCount('notification')).toBe(1)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('should send batch notifications', async () => {
|
|
133
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
134
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
135
|
+
|
|
136
|
+
const recipients = [
|
|
137
|
+
recipient,
|
|
138
|
+
{ ...recipient, email: 'jane@example.com' },
|
|
139
|
+
]
|
|
140
|
+
const result = await messager.sendNotifications(recipients, message)
|
|
141
|
+
|
|
142
|
+
expect(result.success).toBe(true)
|
|
143
|
+
expect(result.count).toBe(2)
|
|
144
|
+
expect(messager.getMessageCount('notification')).toBe(1) // One batch
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
describe('Integration with MockMessagingAdapter - Emails', () => {
|
|
149
|
+
const recipient: MessagingRecipient = {
|
|
150
|
+
firstname: 'John',
|
|
151
|
+
lastname: 'Doe',
|
|
152
|
+
email: 'john@example.com',
|
|
153
|
+
messageToken: 'test-token-123',
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const message: NotificationMessage = {
|
|
157
|
+
title: 'Test Email',
|
|
158
|
+
body: 'This is a test email',
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
it('should send single email', async () => {
|
|
162
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
163
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
164
|
+
|
|
165
|
+
const result = await messager.sendEmail(recipient, message)
|
|
166
|
+
|
|
167
|
+
expect(result.success).toBe(true)
|
|
168
|
+
expect(result.messageId).toMatch(/^email-/)
|
|
169
|
+
expect(messager.getMessageCount('email')).toBe(1)
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('should send batch emails', async () => {
|
|
173
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
174
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
175
|
+
|
|
176
|
+
const recipients = [
|
|
177
|
+
recipient,
|
|
178
|
+
{ ...recipient, email: 'jane@example.com' },
|
|
179
|
+
]
|
|
180
|
+
const result = await messager.sendEmails(recipients, message)
|
|
181
|
+
|
|
182
|
+
expect(result.success).toBe(true)
|
|
183
|
+
expect(result.count).toBe(2)
|
|
184
|
+
expect(messager.getMessageCount('email')).toBe(1) // One batch
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
describe('Integration with MockMessagingAdapter - Text Messages', () => {
|
|
189
|
+
const recipient: MessagingRecipient = {
|
|
190
|
+
firstname: 'John',
|
|
191
|
+
lastname: 'Doe',
|
|
192
|
+
email: 'john@example.com',
|
|
193
|
+
messageToken: 'test-token-123',
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const message: NotificationMessage = {
|
|
197
|
+
title: 'Test SMS',
|
|
198
|
+
body: 'This is a test SMS',
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
it('should send single text message', async () => {
|
|
202
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
203
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
204
|
+
|
|
205
|
+
const result = await messager.sendTextMessage(recipient, message)
|
|
206
|
+
|
|
207
|
+
expect(result.success).toBe(true)
|
|
208
|
+
expect(result.messageId).toMatch(/^text-/)
|
|
209
|
+
expect(messager.getMessageCount('text')).toBe(1)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('should send batch text messages', async () => {
|
|
213
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
214
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
215
|
+
|
|
216
|
+
const recipients = [
|
|
217
|
+
recipient,
|
|
218
|
+
{ ...recipient, email: 'jane@example.com' },
|
|
219
|
+
]
|
|
220
|
+
const result = await messager.sendTextMessages(recipients, message)
|
|
221
|
+
|
|
222
|
+
expect(result.success).toBe(true)
|
|
223
|
+
expect(result.count).toBe(2)
|
|
224
|
+
expect(messager.getMessageCount('text')).toBe(1) // One batch
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
describe('Integration - Multiple message types', () => {
|
|
229
|
+
it('should maintain separate state between messagers', async () => {
|
|
230
|
+
Messaging.addMessager(mockAdapter1, 'messager1')
|
|
231
|
+
Messaging.addMessager(mockAdapter2, 'messager2')
|
|
232
|
+
|
|
233
|
+
const adapter1 = Messaging.getMessager(
|
|
234
|
+
'messager1'
|
|
235
|
+
) as MockMessagingAdapter
|
|
236
|
+
const adapter2 = Messaging.getMessager(
|
|
237
|
+
'messager2'
|
|
238
|
+
) as MockMessagingAdapter
|
|
239
|
+
|
|
240
|
+
const recipient: MessagingRecipient = {
|
|
241
|
+
firstname: 'Test',
|
|
242
|
+
lastname: 'User',
|
|
243
|
+
email: 'test@example.com',
|
|
244
|
+
messageToken: 'test-token-123',
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const message: NotificationMessage = {
|
|
248
|
+
title: 'Test',
|
|
249
|
+
body: 'Test message',
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
await adapter1.sendNotification(recipient, message)
|
|
253
|
+
await adapter2.sendEmail(recipient, message)
|
|
254
|
+
|
|
255
|
+
expect(adapter1.getMessageCount('notification')).toBe(1)
|
|
256
|
+
expect(adapter1.getMessageCount('email')).toBe(0)
|
|
257
|
+
|
|
258
|
+
expect(adapter2.getMessageCount('email')).toBe(1)
|
|
259
|
+
expect(adapter2.getMessageCount('notification')).toBe(0)
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it('should track different message types', async () => {
|
|
263
|
+
Messaging.addMessager(mockAdapter1, 'test')
|
|
264
|
+
const messager = Messaging.getMessager('test') as MockMessagingAdapter
|
|
265
|
+
|
|
266
|
+
const recipient: MessagingRecipient = {
|
|
267
|
+
firstname: 'Test',
|
|
268
|
+
lastname: 'User',
|
|
269
|
+
email: 'test@example.com',
|
|
270
|
+
messageToken: 'test-token-123',
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const message: NotificationMessage = {
|
|
274
|
+
title: 'Test',
|
|
275
|
+
body: 'Test message',
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
await messager.sendNotification(recipient, message)
|
|
279
|
+
await messager.sendEmail(recipient, message)
|
|
280
|
+
await messager.sendTextMessage(recipient, message)
|
|
281
|
+
|
|
282
|
+
expect(messager.getMessageCount()).toBe(3)
|
|
283
|
+
expect(messager.getMessageCount('notification')).toBe(1)
|
|
284
|
+
expect(messager.getMessageCount('email')).toBe(1)
|
|
285
|
+
expect(messager.getMessageCount('text')).toBe(1)
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
describe('Messaging registry behavior', () => {
|
|
290
|
+
it('should maintain messagers across multiple operations', () => {
|
|
291
|
+
Messaging.addMessager(mockAdapter1, 'persistent')
|
|
292
|
+
|
|
293
|
+
// Multiple get operations
|
|
294
|
+
const messager1 = Messaging.getMessager('persistent')
|
|
295
|
+
const messager2 = Messaging.getMessager('persistent')
|
|
296
|
+
|
|
297
|
+
expect(messager1).toBe(messager2)
|
|
298
|
+
expect(messager1).toBe(mockAdapter1)
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
it('should handle switching default messager multiple times', () => {
|
|
302
|
+
Messaging.addMessager(mockAdapter1, 'messager1', true)
|
|
303
|
+
expect(Messaging.defaultMessager).toBe('messager1')
|
|
304
|
+
|
|
305
|
+
Messaging.addMessager(mockAdapter2, 'messager2', true)
|
|
306
|
+
expect(Messaging.defaultMessager).toBe('messager2')
|
|
307
|
+
|
|
308
|
+
const defaultMessager = Messaging.getMessager()
|
|
309
|
+
expect(defaultMessager).toBe(mockAdapter2)
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
describe('logger', () => {
|
|
314
|
+
it('should have a logger instance', () => {
|
|
315
|
+
expect(Messaging.logger).toBeDefined()
|
|
316
|
+
})
|
|
317
|
+
})
|
|
318
|
+
})
|
package/src/Messaging.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Core } from '@quatrain/core'
|
|
2
|
+
import { NotificationCapableAdapter } from './types/NotificationCapableAdapter'
|
|
3
|
+
import { EmailCapableAdapter } from './types/EmailCapableAdapter'
|
|
4
|
+
import { TextCapableAdapter } from './types/TextCapableAdapter'
|
|
5
|
+
|
|
6
|
+
export type MessagingRegistry<T extends NotificationCapableAdapter
|
|
7
|
+
| EmailCapableAdapter
|
|
8
|
+
| TextCapableAdapter> = {
|
|
9
|
+
[x: string]: T
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface MessagingParameters {
|
|
13
|
+
config?: any
|
|
14
|
+
debug?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Messaging extends Core {
|
|
18
|
+
static defaultMessager = 'default'
|
|
19
|
+
static logger = this.addLogger('Messaging')
|
|
20
|
+
|
|
21
|
+
protected static _messagers: MessagingRegistry<any> = {}
|
|
22
|
+
|
|
23
|
+
static addMessager(
|
|
24
|
+
messager:
|
|
25
|
+
| NotificationCapableAdapter
|
|
26
|
+
| EmailCapableAdapter
|
|
27
|
+
| TextCapableAdapter,
|
|
28
|
+
alias: string,
|
|
29
|
+
setDefault: boolean = false
|
|
30
|
+
) {
|
|
31
|
+
this._messagers[alias] = messager
|
|
32
|
+
if (setDefault) {
|
|
33
|
+
this.defaultMessager = alias
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static getMessager(alias: string = this.defaultMessager) {
|
|
38
|
+
if (this._messagers[alias]) {
|
|
39
|
+
return this._messagers[alias]
|
|
40
|
+
} else {
|
|
41
|
+
throw new Error(`Unknown messager alias: '${alias}'`)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { AbstractMessagingAdapter } from './AbstractMessagingAdapter'
|
|
2
|
+
import { NotificationCapableAdapter } from './types/NotificationCapableAdapter'
|
|
3
|
+
import { EmailCapableAdapter } from './types/EmailCapableAdapter'
|
|
4
|
+
import { TextCapableAdapter } from './types/TextCapableAdapter'
|
|
5
|
+
import { MessagingRecipient } from './types/MessagingRecipient'
|
|
6
|
+
import { NotificationMessage } from './types/NotificationMessage'
|
|
7
|
+
import { MessagingParameters } from './Messaging'
|
|
8
|
+
|
|
9
|
+
interface SentMessage {
|
|
10
|
+
type: 'notification' | 'email' | 'text'
|
|
11
|
+
recipient: MessagingRecipient | MessagingRecipient[]
|
|
12
|
+
message: NotificationMessage
|
|
13
|
+
timestamp: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Mock Messaging Adapter for testing purposes
|
|
18
|
+
* Implements all three capability interfaces
|
|
19
|
+
*/
|
|
20
|
+
export class MockMessagingAdapter
|
|
21
|
+
extends AbstractMessagingAdapter
|
|
22
|
+
implements
|
|
23
|
+
NotificationCapableAdapter,
|
|
24
|
+
EmailCapableAdapter,
|
|
25
|
+
TextCapableAdapter
|
|
26
|
+
{
|
|
27
|
+
private sentMessages: SentMessage[] = []
|
|
28
|
+
|
|
29
|
+
constructor(params: MessagingParameters = {}) {
|
|
30
|
+
super(params)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async sendNotification(
|
|
34
|
+
recipient: MessagingRecipient,
|
|
35
|
+
message: NotificationMessage
|
|
36
|
+
): Promise<any> {
|
|
37
|
+
this.sentMessages.push({
|
|
38
|
+
type: 'notification',
|
|
39
|
+
recipient,
|
|
40
|
+
message,
|
|
41
|
+
timestamp: Date.now(),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
messageId: `notif-${Date.now()}`,
|
|
47
|
+
recipient: recipient.email,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async sendNotifications(
|
|
52
|
+
recipients: MessagingRecipient[],
|
|
53
|
+
message: NotificationMessage
|
|
54
|
+
): Promise<any> {
|
|
55
|
+
this.sentMessages.push({
|
|
56
|
+
type: 'notification',
|
|
57
|
+
recipient: recipients,
|
|
58
|
+
message,
|
|
59
|
+
timestamp: Date.now(),
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
count: recipients.length,
|
|
65
|
+
messageIds: recipients.map((r, i) => `notif-batch-${Date.now()}-${i}`),
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async sendEmail(
|
|
70
|
+
recipient: MessagingRecipient,
|
|
71
|
+
message: NotificationMessage
|
|
72
|
+
): Promise<any> {
|
|
73
|
+
this.sentMessages.push({
|
|
74
|
+
type: 'email',
|
|
75
|
+
recipient,
|
|
76
|
+
message,
|
|
77
|
+
timestamp: Date.now(),
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
messageId: `email-${Date.now()}`,
|
|
83
|
+
recipient: recipient.email,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async sendEmails(
|
|
88
|
+
recipients: MessagingRecipient[],
|
|
89
|
+
message: NotificationMessage
|
|
90
|
+
): Promise<any> {
|
|
91
|
+
this.sentMessages.push({
|
|
92
|
+
type: 'email',
|
|
93
|
+
recipient: recipients,
|
|
94
|
+
message,
|
|
95
|
+
timestamp: Date.now(),
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
count: recipients.length,
|
|
101
|
+
messageIds: recipients.map((r, i) => `email-batch-${Date.now()}-${i}`),
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async sendTextMessage(
|
|
106
|
+
recipient: MessagingRecipient,
|
|
107
|
+
message: NotificationMessage
|
|
108
|
+
): Promise<any> {
|
|
109
|
+
this.sentMessages.push({
|
|
110
|
+
type: 'text',
|
|
111
|
+
recipient,
|
|
112
|
+
message,
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
messageId: `text-${Date.now()}`,
|
|
119
|
+
recipient: recipient.email,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async sendTextMessages(
|
|
124
|
+
recipients: MessagingRecipient[],
|
|
125
|
+
message: NotificationMessage
|
|
126
|
+
): Promise<any> {
|
|
127
|
+
this.sentMessages.push({
|
|
128
|
+
type: 'text',
|
|
129
|
+
recipient: recipients,
|
|
130
|
+
message,
|
|
131
|
+
timestamp: Date.now(),
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
success: true,
|
|
136
|
+
count: recipients.length,
|
|
137
|
+
messageIds: recipients.map((r, i) => `text-batch-${Date.now()}-${i}`),
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Helper methods for testing
|
|
142
|
+
getSentMessages(type?: 'notification' | 'email' | 'text'): SentMessage[] {
|
|
143
|
+
if (type) {
|
|
144
|
+
return this.sentMessages.filter((msg) => msg.type === type)
|
|
145
|
+
}
|
|
146
|
+
return this.sentMessages
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
clearMessages(): void {
|
|
150
|
+
this.sentMessages = []
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
getMessageCount(type?: 'notification' | 'email' | 'text'): number {
|
|
154
|
+
return this.getSentMessages(type).length
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
getLastMessage(
|
|
158
|
+
type?: 'notification' | 'email' | 'text'
|
|
159
|
+
): SentMessage | undefined {
|
|
160
|
+
const messages = this.getSentMessages(type)
|
|
161
|
+
return messages[messages.length - 1]
|
|
162
|
+
}
|
|
163
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Messaging, MessagingParameters } from './Messaging'
|
|
2
|
+
import { AbstractMessagingAdapter } from './AbstractMessagingAdapter'
|
|
3
|
+
import { MessagingRecipient } from './types/MessagingRecipient'
|
|
4
|
+
import { NotificationMessage } from './types/NotificationMessage'
|
|
5
|
+
import { MessageType } from './types/MessageType'
|
|
6
|
+
import { EmailCapableAdapter } from './types/EmailCapableAdapter'
|
|
7
|
+
import { NotificationCapableAdapter } from './types/NotificationCapableAdapter'
|
|
8
|
+
import { MessageFormatter } from './MessageFormatter'
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
Messaging,
|
|
12
|
+
MessagingParameters,
|
|
13
|
+
AbstractMessagingAdapter,
|
|
14
|
+
MessagingRecipient,
|
|
15
|
+
NotificationMessage,
|
|
16
|
+
MessageType,
|
|
17
|
+
EmailCapableAdapter,
|
|
18
|
+
NotificationCapableAdapter,
|
|
19
|
+
MessageFormatter,
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MessagingRecipient } from './MessagingRecipient'
|
|
2
|
+
import { NotificationMessage } from './NotificationMessage'
|
|
3
|
+
|
|
4
|
+
export interface EmailCapableAdapter {
|
|
5
|
+
sendEmail(
|
|
6
|
+
recipient: MessagingRecipient,
|
|
7
|
+
message: NotificationMessage
|
|
8
|
+
): Promise<any>
|
|
9
|
+
|
|
10
|
+
sendEmails(
|
|
11
|
+
recipients: MessagingRecipient[],
|
|
12
|
+
message: NotificationMessage
|
|
13
|
+
): Promise<any>
|
|
14
|
+
}
|