townkrier-termii 1.0.0-alpha.6
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 +44 -0
- package/README.md +296 -0
- package/__tests__/termii.channel.spec.ts +64 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +18 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/termii-channel.d.ts +13 -0
- package/dist/core/termii-channel.d.ts.map +1 -0
- package/dist/core/termii-channel.js +94 -0
- package/dist/core/termii-channel.js.map +1 -0
- package/dist/core/termii-channel.spec.d.ts +2 -0
- package/dist/core/termii-channel.spec.d.ts.map +1 -0
- package/dist/core/termii-channel.spec.js +65 -0
- package/dist/core/termii-channel.spec.js.map +1 -0
- package/dist/core/termii.mapper.d.ts +9 -0
- package/dist/core/termii.mapper.d.ts.map +1 -0
- package/dist/core/termii.mapper.js +62 -0
- package/dist/core/termii.mapper.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/index.d.ts +19 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +3 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/jest.config.js +8 -0
- package/package.json +39 -0
- package/src/core/index.ts +1 -0
- package/src/core/termii-channel.spec.ts +80 -0
- package/src/core/termii-channel.ts +146 -0
- package/src/core/termii.mapper.ts +77 -0
- package/src/index.ts +4 -0
- package/src/interfaces/index.ts +29 -0
- package/src/types/index.ts +26 -0
- package/tsconfig.json +12 -0
- package/tsconfig.spec.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
# 1.0.0-alpha.5 (2026-02-02)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- Update publish workflow to enforce frozen lockfile and adjust publish commands ([ae73a10](https://github.com/jeremiah-olisa/townkrier/commit/ae73a10c7629f54b0e2de4b1f648e6e721125dbc))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- add bulk SMS support to Termii channel by enabling multiple recipients and dynamic endpoint selection, with improved error handling. ([d45121a](https://github.com/jeremiah-olisa/townkrier/commit/d45121a3857f93170c1566910eb3ab30e70f2583))
|
|
15
|
+
- Add Firebase-backed push notification handling to the Expo example and improve Termii channel error message parsing. ([6959e52](https://github.com/jeremiah-olisa/townkrier/commit/6959e5258109c6812532b3ee1f0aa979583f000e))
|
|
16
|
+
- Implement a new logger system and refactor the Resend email channel with a dedicated mapper and enhanced response handling. ([4517e6e](https://github.com/jeremiah-olisa/townkrier/commit/4517e6e76bd07cf381ad1c1b35ada4b0ab829a9e))
|
|
17
|
+
- Introduce FCM and Termii channels, refactor FCM with mappers, and update playground usage. ([cb5b556](https://github.com/jeremiah-olisa/townkrier/commit/cb5b556ee8d7e70f9c4587eaac24f6f67e3fcad4))
|
|
18
|
+
|
|
19
|
+
# 1.0.0-alpha.4 (2026-01-28)
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
|
|
23
|
+
- add bulk SMS support to Termii channel by enabling multiple recipients and dynamic endpoint selection, with improved error handling. ([d45121a](https://github.com/jeremiah-olisa/townkrier/commit/d45121a3857f93170c1566910eb3ab30e70f2583))
|
|
24
|
+
- Add Firebase-backed push notification handling to the Expo example and improve Termii channel error message parsing. ([6959e52](https://github.com/jeremiah-olisa/townkrier/commit/6959e5258109c6812532b3ee1f0aa979583f000e))
|
|
25
|
+
- Implement a new logger system and refactor the Resend email channel with a dedicated mapper and enhanced response handling. ([4517e6e](https://github.com/jeremiah-olisa/townkrier/commit/4517e6e76bd07cf381ad1c1b35ada4b0ab829a9e))
|
|
26
|
+
- Introduce FCM and Termii channels, refactor FCM with mappers, and update playground usage. ([cb5b556](https://github.com/jeremiah-olisa/townkrier/commit/cb5b556ee8d7e70f9c4587eaac24f6f67e3fcad4))
|
|
27
|
+
|
|
28
|
+
# 1.0.0-alpha.3 (2026-01-28)
|
|
29
|
+
|
|
30
|
+
### Features
|
|
31
|
+
|
|
32
|
+
- add bulk SMS support to Termii channel by enabling multiple recipients and dynamic endpoint selection, with improved error handling. ([d45121a](https://github.com/jeremiah-olisa/townkrier/commit/d45121a3857f93170c1566910eb3ab30e70f2583))
|
|
33
|
+
- Add Firebase-backed push notification handling to the Expo example and improve Termii channel error message parsing. ([6959e52](https://github.com/jeremiah-olisa/townkrier/commit/6959e5258109c6812532b3ee1f0aa979583f000e))
|
|
34
|
+
- Implement a new logger system and refactor the Resend email channel with a dedicated mapper and enhanced response handling. ([4517e6e](https://github.com/jeremiah-olisa/townkrier/commit/4517e6e76bd07cf381ad1c1b35ada4b0ab829a9e))
|
|
35
|
+
- Introduce FCM and Termii channels, refactor FCM with mappers, and update playground usage. ([cb5b556](https://github.com/jeremiah-olisa/townkrier/commit/cb5b556ee8d7e70f9c4587eaac24f6f67e3fcad4))
|
|
36
|
+
|
|
37
|
+
# 1.0.0-alpha.2 (2026-01-28)
|
|
38
|
+
|
|
39
|
+
### Features
|
|
40
|
+
|
|
41
|
+
- add bulk SMS support to Termii channel by enabling multiple recipients and dynamic endpoint selection, with improved error handling. ([d45121a](https://github.com/jeremiah-olisa/townkrier/commit/d45121a3857f93170c1566910eb3ab30e70f2583))
|
|
42
|
+
- Add Firebase-backed push notification handling to the Expo example and improve Termii channel error message parsing. ([6959e52](https://github.com/jeremiah-olisa/townkrier/commit/6959e5258109c6812532b3ee1f0aa979583f000e))
|
|
43
|
+
- Implement a new logger system and refactor the Resend email channel with a dedicated mapper and enhanced response handling. ([4517e6e](https://github.com/jeremiah-olisa/townkrier/commit/4517e6e76bd07cf381ad1c1b35ada4b0ab829a9e))
|
|
44
|
+
- Introduce FCM and Termii channels, refactor FCM with mappers, and update playground usage. ([cb5b556](https://github.com/jeremiah-olisa/townkrier/commit/cb5b556ee8d7e70f9c4587eaac24f6f67e3fcad4))
|
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# townkrier-termii
|
|
2
|
+
|
|
3
|
+
Termii SMS adapter for the TownKrier notification system.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📱 SMS notifications via Termii API
|
|
8
|
+
- 🌍 Support for multiple countries and regions
|
|
9
|
+
- 🔄 Automatic retry with exponential backoff
|
|
10
|
+
- 📝 Message templates and personalization
|
|
11
|
+
- 🔍 Delivery status tracking
|
|
12
|
+
- 🛡️ Error handling and validation
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install townkrier-termii townkrier-core
|
|
18
|
+
# or
|
|
19
|
+
pnpm add townkrier-termii townkrier-core
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { NotificationManager, NotificationChannel } from 'townkrier-core';
|
|
26
|
+
import { createTermiiChannel } from 'townkrier-termii';
|
|
27
|
+
|
|
28
|
+
// Configure the manager with Termii channel
|
|
29
|
+
const manager = new NotificationManager({
|
|
30
|
+
defaultChannel: 'sms-termii',
|
|
31
|
+
channels: [
|
|
32
|
+
{
|
|
33
|
+
name: 'sms-termii',
|
|
34
|
+
enabled: true,
|
|
35
|
+
config: {
|
|
36
|
+
apiKey: process.env.TERMII_API_KEY,
|
|
37
|
+
senderId: 'YourApp', // Your registered sender ID
|
|
38
|
+
channel: 'generic', // or 'dnd', 'whatsapp'
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Register the Termii channel factory
|
|
45
|
+
manager.registerFactory('sms-termii', createTermiiChannel);
|
|
46
|
+
|
|
47
|
+
// Create a notification
|
|
48
|
+
class WelcomeSmsNotification extends Notification {
|
|
49
|
+
constructor(private userName: string) {
|
|
50
|
+
super();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
via() {
|
|
54
|
+
return [NotificationChannel.SMS];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
toSms() {
|
|
58
|
+
return {
|
|
59
|
+
to: '+1234567890',
|
|
60
|
+
message: `Welcome ${this.userName}! Thank you for joining our service.`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Send the notification
|
|
66
|
+
const notification = new WelcomeSmsNotification('John');
|
|
67
|
+
const recipient = {
|
|
68
|
+
[NotificationChannel.SMS]: {
|
|
69
|
+
phone: '+1234567890',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
await manager.send(notification, recipient);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Configuration
|
|
77
|
+
|
|
78
|
+
### TermiiConfig
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface TermiiConfig {
|
|
82
|
+
apiKey: string; // Required: Your Termii API key
|
|
83
|
+
senderId: string; // Required: Your registered sender ID (max 11 chars)
|
|
84
|
+
channel?: string; // Optional: Message channel (default: 'generic')
|
|
85
|
+
timeout?: number; // Optional: Request timeout in ms (default: 30000)
|
|
86
|
+
debug?: boolean; // Optional: Enable debug logging (default: false)
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Channel Types
|
|
91
|
+
|
|
92
|
+
Termii supports different message channels:
|
|
93
|
+
|
|
94
|
+
- `generic` - Standard SMS (default, most reliable)
|
|
95
|
+
- `dnd` - For numbers on DND (Do Not Disturb)
|
|
96
|
+
- `whatsapp` - For WhatsApp Business messages
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
{
|
|
100
|
+
channel: 'generic', // Change based on your needs
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Advanced Usage
|
|
105
|
+
|
|
106
|
+
### With Personalization
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
class OrderConfirmationNotification extends Notification {
|
|
110
|
+
constructor(
|
|
111
|
+
private orderNumber: string,
|
|
112
|
+
private totalAmount: string,
|
|
113
|
+
private estimatedDelivery: string,
|
|
114
|
+
) {
|
|
115
|
+
super();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
via() {
|
|
119
|
+
return [NotificationChannel.SMS];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
toSms() {
|
|
123
|
+
return {
|
|
124
|
+
to: '+1234567890',
|
|
125
|
+
message: `Order #${this.orderNumber} confirmed! Total: ${this.totalAmount}. Estimated delivery: ${this.estimatedDelivery}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Multi-Channel with Fallback
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
class CriticalAlertNotification extends Notification {
|
|
135
|
+
via() {
|
|
136
|
+
// Try SMS first, fallback to email if SMS fails
|
|
137
|
+
return [NotificationChannel.SMS, NotificationChannel.EMAIL];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
toSms() {
|
|
141
|
+
return {
|
|
142
|
+
to: '+1234567890',
|
|
143
|
+
message: 'Critical Alert: Your account requires immediate attention.',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
toEmail() {
|
|
148
|
+
return {
|
|
149
|
+
subject: 'Critical Alert',
|
|
150
|
+
html: '<h1>Critical Alert</h1><p>Your account requires immediate attention.</p>',
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### International Numbers
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// Always use E.164 format for international numbers
|
|
160
|
+
{
|
|
161
|
+
to: '+44712345678', // UK
|
|
162
|
+
to: '+12125551234', // USA
|
|
163
|
+
to: '+234812345678', // Nigeria
|
|
164
|
+
message: 'Your message here',
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Getting Your API Key
|
|
169
|
+
|
|
170
|
+
1. Sign up at [termii.com](https://termii.com)
|
|
171
|
+
2. Navigate to your Dashboard
|
|
172
|
+
3. Go to API Settings
|
|
173
|
+
4. Copy your API Key
|
|
174
|
+
5. Register a Sender ID (this may require verification)
|
|
175
|
+
|
|
176
|
+
### Sender ID Requirements
|
|
177
|
+
|
|
178
|
+
- Maximum 11 characters
|
|
179
|
+
- Alphanumeric only
|
|
180
|
+
- Must be approved by Termii
|
|
181
|
+
- Some countries require pre-registration
|
|
182
|
+
|
|
183
|
+
## Error Handling
|
|
184
|
+
|
|
185
|
+
The adapter includes comprehensive error handling:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { NotificationFailed } from 'townkrier-core';
|
|
189
|
+
|
|
190
|
+
// Listen for failures
|
|
191
|
+
eventDispatcher.on(NotificationFailed, async (event) => {
|
|
192
|
+
console.error('SMS failed:', event.error.message);
|
|
193
|
+
console.error('Failed channel:', event.failedChannel);
|
|
194
|
+
|
|
195
|
+
// Implement custom retry logic or alerts
|
|
196
|
+
if (event.error.message.includes('Invalid number')) {
|
|
197
|
+
// Handle invalid phone numbers
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Message Length
|
|
203
|
+
|
|
204
|
+
- Standard SMS: 160 characters
|
|
205
|
+
- Unicode messages (emojis, etc.): 70 characters
|
|
206
|
+
- Messages longer than these limits are split into multiple parts
|
|
207
|
+
|
|
208
|
+
## Testing
|
|
209
|
+
|
|
210
|
+
### Development Mode
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
{
|
|
214
|
+
apiKey: process.env.TERMII_API_KEY,
|
|
215
|
+
senderId: 'Test',
|
|
216
|
+
debug: true, // Enable detailed logging
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Test Numbers
|
|
221
|
+
|
|
222
|
+
Termii provides test numbers for development. Check their documentation for current test numbers.
|
|
223
|
+
|
|
224
|
+
## Pricing
|
|
225
|
+
|
|
226
|
+
Termii charges per SMS sent. Pricing varies by:
|
|
227
|
+
|
|
228
|
+
- Destination country
|
|
229
|
+
- Message type (SMS vs WhatsApp)
|
|
230
|
+
- Volume discounts
|
|
231
|
+
|
|
232
|
+
Check [Termii Pricing](https://termii.com/pricing) for current rates.
|
|
233
|
+
|
|
234
|
+
## Best Practices
|
|
235
|
+
|
|
236
|
+
1. **Validate Phone Numbers**: Always validate numbers before sending
|
|
237
|
+
2. **Keep Messages Concise**: Stay under 160 characters when possible
|
|
238
|
+
3. **Use Sender ID Wisely**: Choose a recognizable sender ID
|
|
239
|
+
4. **Handle Errors**: Implement proper error handling and logging
|
|
240
|
+
5. **Respect Regulations**: Follow SMS marketing regulations (TCPA, etc.)
|
|
241
|
+
6. **Rate Limiting**: Be mindful of rate limits
|
|
242
|
+
7. **Store Preferences**: Track user SMS preferences and opt-outs
|
|
243
|
+
|
|
244
|
+
## Troubleshooting
|
|
245
|
+
|
|
246
|
+
### "Invalid API Key"
|
|
247
|
+
|
|
248
|
+
- Verify your API key is correct
|
|
249
|
+
- Check if the key has necessary permissions
|
|
250
|
+
- Ensure the key hasn't expired
|
|
251
|
+
|
|
252
|
+
### "Invalid Sender ID"
|
|
253
|
+
|
|
254
|
+
- Verify sender ID is registered with Termii
|
|
255
|
+
- Check sender ID is maximum 11 characters
|
|
256
|
+
- Ensure sender ID is approved for your account
|
|
257
|
+
|
|
258
|
+
### "Insufficient Balance"
|
|
259
|
+
|
|
260
|
+
- Check your Termii account balance
|
|
261
|
+
- Add credits to your account
|
|
262
|
+
|
|
263
|
+
### "Invalid Phone Number"
|
|
264
|
+
|
|
265
|
+
- Use E.164 format (+countrycode + number)
|
|
266
|
+
- Remove spaces, dashes, or special characters
|
|
267
|
+
- Verify the number is valid for the destination country
|
|
268
|
+
|
|
269
|
+
## Related Packages
|
|
270
|
+
|
|
271
|
+
- [townkrier-core](../../core) - Core notification system
|
|
272
|
+
- [townkrier-resend](../../resend) - Email provider
|
|
273
|
+
- [townkrier-fcm](../push/fcm) - Push notifications provider
|
|
274
|
+
- [townkrier-queue](../../queue) - Queue system for background processing
|
|
275
|
+
- [townkrier-dashboard](../../dashboard) - Monitoring dashboard
|
|
276
|
+
|
|
277
|
+
## Examples
|
|
278
|
+
|
|
279
|
+
See the [examples directory](../../../../examples) for complete working examples:
|
|
280
|
+
|
|
281
|
+
- [Complete Example](../../../../examples/complete-example.ts) - Full multi-channel setup
|
|
282
|
+
- [SMS Specific Examples](../../../../examples/notifications) - SMS notification examples
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
MIT
|
|
287
|
+
|
|
288
|
+
## Support
|
|
289
|
+
|
|
290
|
+
- [Termii Documentation](https://developers.termii.com)
|
|
291
|
+
- [TownKrier Documentation](../../../../README.md)
|
|
292
|
+
- [Report Issues](https://github.com/jeremiah-olisa/townkrier/issues)
|
|
293
|
+
|
|
294
|
+
## Author
|
|
295
|
+
|
|
296
|
+
Jeremiah Olisa
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { TermiiChannel, createTermiiChannel } from '../src/core';
|
|
2
|
+
import { TermiiConfig } from '../src/types';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
// Mock axios
|
|
6
|
+
jest.mock('axios');
|
|
7
|
+
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
|
8
|
+
|
|
9
|
+
describe('TermiiChannel', () => {
|
|
10
|
+
const config: TermiiConfig = {
|
|
11
|
+
apiKey: 'test-api-key',
|
|
12
|
+
from: 'TestSender',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let channel: TermiiChannel;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
jest.clearAllMocks();
|
|
19
|
+
// Mock axios.create to return the mocked axios instance so we can spy on post
|
|
20
|
+
(mockedAxios.create as jest.Mock).mockReturnValue(mockedAxios);
|
|
21
|
+
channel = new TermiiChannel(config);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should be defined', () => {
|
|
25
|
+
expect(channel).toBeDefined();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should send sms successfully', async () => {
|
|
29
|
+
mockedAxios.post.mockResolvedValue({
|
|
30
|
+
data: {
|
|
31
|
+
message_id: '12345',
|
|
32
|
+
message: 'Successfully Sent',
|
|
33
|
+
balance: 10,
|
|
34
|
+
user: 'test-user',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const result = await channel.sendSms({
|
|
39
|
+
to: { phone: '2348012345678' },
|
|
40
|
+
message: 'Hello World',
|
|
41
|
+
text: 'Hello World',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(mockedAxios.post).toHaveBeenCalledWith(
|
|
45
|
+
'/api/sms/send', // Method uses relative path on client
|
|
46
|
+
expect.objectContaining({
|
|
47
|
+
api_key: 'test-api-key',
|
|
48
|
+
to: '2348012345678',
|
|
49
|
+
from: 'TestSender',
|
|
50
|
+
sms: 'Hello World',
|
|
51
|
+
type: 'plain',
|
|
52
|
+
channel: 'generic',
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(result.status).toBe('sent');
|
|
57
|
+
expect(result.messageId).toBe('12345');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should create channel using factory', () => {
|
|
61
|
+
const channelFromFactory = createTermiiChannel(config);
|
|
62
|
+
expect(channelFromFactory).toBeInstanceOf(TermiiChannel);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./termii-channel"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SmsChannel, SendSmsRequest, SendSmsResponse } from 'townkrier-core';
|
|
2
|
+
import { TermiiConfig } from '../types';
|
|
3
|
+
export declare class TermiiChannel extends SmsChannel {
|
|
4
|
+
private readonly client;
|
|
5
|
+
private readonly termiiConfig;
|
|
6
|
+
private readonly baseUrl;
|
|
7
|
+
constructor(config: TermiiConfig);
|
|
8
|
+
sendSms(request: SendSmsRequest): Promise<SendSmsResponse>;
|
|
9
|
+
protected isValidNotificationRequest(request: any): request is SendSmsRequest;
|
|
10
|
+
private handleError;
|
|
11
|
+
}
|
|
12
|
+
export declare function createTermiiChannel(config: TermiiConfig): TermiiChannel;
|
|
13
|
+
//# sourceMappingURL=termii-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"termii-channel.d.ts","sourceRoot":"","sources":["../../src/core/termii-channel.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,eAAe,EAGhB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAQxC,qBAAa,aAAc,SAAQ,UAAU;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,YAAY;IAoD1B,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAoDhE,SAAS,CAAC,0BAA0B,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,cAAc;IAU7E,OAAO,CAAC,WAAW;CAGpB;AAKD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CAEvE"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TermiiChannel = void 0;
|
|
7
|
+
exports.createTermiiChannel = createTermiiChannel;
|
|
8
|
+
const townkrier_core_1 = require("townkrier-core");
|
|
9
|
+
const termii_mapper_1 = require("./termii.mapper");
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
11
|
+
class TermiiChannel extends townkrier_core_1.SmsChannel {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
if (!config.apiKey) {
|
|
14
|
+
throw new townkrier_core_1.NotificationConfigurationException('API key is required for Termii', {
|
|
15
|
+
channel: 'Termii',
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
super(config, 'Termii');
|
|
19
|
+
this.termiiConfig = config;
|
|
20
|
+
this.baseUrl = config.baseUrl || 'https://api.ng.termii.com';
|
|
21
|
+
this.client = axios_1.default.create({
|
|
22
|
+
baseURL: this.baseUrl,
|
|
23
|
+
timeout: config.timeout || 30000,
|
|
24
|
+
headers: {
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
if (config.debug) {
|
|
29
|
+
this.client.interceptors.request.use((request) => {
|
|
30
|
+
townkrier_core_1.Logger.debug('[Termii Request]', {
|
|
31
|
+
url: request.url,
|
|
32
|
+
method: request.method,
|
|
33
|
+
data: request.data,
|
|
34
|
+
});
|
|
35
|
+
return request;
|
|
36
|
+
});
|
|
37
|
+
this.client.interceptors.response.use((response) => {
|
|
38
|
+
townkrier_core_1.Logger.debug('[Termii Response]', {
|
|
39
|
+
status: response.status,
|
|
40
|
+
data: response.data,
|
|
41
|
+
});
|
|
42
|
+
return response;
|
|
43
|
+
}, (error) => {
|
|
44
|
+
townkrier_core_1.Logger.error('[Termii Error]', {
|
|
45
|
+
message: error.message,
|
|
46
|
+
response: error.response?.data,
|
|
47
|
+
});
|
|
48
|
+
return Promise.reject(error);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async sendSms(request) {
|
|
53
|
+
try {
|
|
54
|
+
const recipients = Array.isArray(request.to) ? request.to : [request.to];
|
|
55
|
+
if (recipients.length === 0) {
|
|
56
|
+
throw new townkrier_core_1.NotificationConfigurationException('No recipients provided', {
|
|
57
|
+
recipients,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const data = termii_mapper_1.TermiiMapper.toTermiiData(request, this.termiiConfig);
|
|
61
|
+
const endpoint = Array.isArray(data.to) ? '/api/sms/send/bulk' : '/api/sms/send';
|
|
62
|
+
const response = await this.client.post(endpoint, data);
|
|
63
|
+
if (!response.data || !response.data.message_id) {
|
|
64
|
+
if (response.data && response.data.message && !response.data.message_id) {
|
|
65
|
+
throw new Error(response.data.message);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return termii_mapper_1.TermiiMapper.toSuccessResponse(response.data, request);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
let finalError = error;
|
|
72
|
+
if (axios_1.default.isAxiosError(error) && error.response) {
|
|
73
|
+
const errorData = error.response.data;
|
|
74
|
+
let message = errorData?.message || errorData?.error || error.message;
|
|
75
|
+
if (typeof message === 'object') {
|
|
76
|
+
message = JSON.stringify(message);
|
|
77
|
+
}
|
|
78
|
+
finalError = new Error(message);
|
|
79
|
+
}
|
|
80
|
+
return termii_mapper_1.TermiiMapper.toErrorResponse(finalError, 'Failed to send SMS');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
isValidNotificationRequest(request) {
|
|
84
|
+
return request && request.message && (request.to || Array.isArray(request.to));
|
|
85
|
+
}
|
|
86
|
+
handleError(error, defaultMessage) {
|
|
87
|
+
return termii_mapper_1.TermiiMapper.toErrorResponse(error, defaultMessage);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.TermiiChannel = TermiiChannel;
|
|
91
|
+
function createTermiiChannel(config) {
|
|
92
|
+
return new TermiiChannel(config);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=termii-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"termii-channel.js","sourceRoot":"","sources":["../../src/core/termii-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"termii-channel.spec.d.ts","sourceRoot":"","sources":["../../src/core/termii-channel.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const termii_channel_1 = require("./termii-channel");
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
jest.mock('axios');
|
|
9
|
+
const mockedAxios = axios_1.default;
|
|
10
|
+
describe('TermiiChannel', () => {
|
|
11
|
+
let channel;
|
|
12
|
+
const config = {
|
|
13
|
+
apiKey: 'test-api-key',
|
|
14
|
+
from: 'Townkrier',
|
|
15
|
+
};
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.clearAllMocks();
|
|
18
|
+
mockedAxios.create.mockReturnThis();
|
|
19
|
+
mockedAxios.post.mockResolvedValue({
|
|
20
|
+
data: { message_id: '12345', message: 'Successfully Sent' },
|
|
21
|
+
});
|
|
22
|
+
channel = new termii_channel_1.TermiiChannel(config);
|
|
23
|
+
});
|
|
24
|
+
it('should send single SMS via standard endpoint', async () => {
|
|
25
|
+
const request = {
|
|
26
|
+
to: { phone: '2341234567890' },
|
|
27
|
+
message: 'Hello World',
|
|
28
|
+
text: 'Hello World',
|
|
29
|
+
};
|
|
30
|
+
await channel.sendSms(request);
|
|
31
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('/api/sms/send', expect.objectContaining({
|
|
32
|
+
to: '2341234567890',
|
|
33
|
+
}));
|
|
34
|
+
});
|
|
35
|
+
it('should send bulk SMS via bulk endpoint', async () => {
|
|
36
|
+
const request = {
|
|
37
|
+
to: [{ phone: '2341234567890' }, { phone: '2341234567891' }],
|
|
38
|
+
message: 'Hello World Bulk',
|
|
39
|
+
text: 'Hello World Bulk',
|
|
40
|
+
};
|
|
41
|
+
await channel.sendSms(request);
|
|
42
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('/api/sms/send/bulk', expect.objectContaining({
|
|
43
|
+
to: ['2341234567890', '2341234567891'],
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
it('should throw error if API returns error message with 200 OK', async () => {
|
|
47
|
+
mockedAxios.post.mockResolvedValue({
|
|
48
|
+
data: {
|
|
49
|
+
message: 'Invalid API Key',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const request = {
|
|
53
|
+
to: { phone: '2341234567890' },
|
|
54
|
+
message: 'Hello World',
|
|
55
|
+
text: 'Hello World',
|
|
56
|
+
};
|
|
57
|
+
await expect(channel.sendSms(request)).resolves.toEqual(expect.objectContaining({
|
|
58
|
+
status: 'failed',
|
|
59
|
+
error: expect.objectContaining({
|
|
60
|
+
message: 'Invalid API Key',
|
|
61
|
+
}),
|
|
62
|
+
}));
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=termii-channel.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"termii-channel.spec.js","sourceRoot":"","sources":["../../src/core/termii-channel.spec.ts"],"names":[],"mappings":";;;;;AAAA,qDAAiD;AACjD,kDAA0B;AAG1B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACnB,MAAM,WAAW,GAAG,eAAkC,CAAC;AAEvD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,OAAsB,CAAC;IAC3B,MAAM,MAAM,GAAG;QACb,MAAM,EAAE,cAAc;QACtB,IAAI,EAAE,WAAW;KAClB,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,WAAW,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QACpC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC;YACjC,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE;SAC5D,CAAC,CAAC;QACH,OAAO,GAAG,IAAI,8BAAa,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,OAAO,GAAmB;YAC9B,EAAE,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE;YAC9B,OAAO,EAAE,aAAa;YACtB,IAAI,EAAE,aAAa;SACpB,CAAC;QAEF,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE/B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,oBAAoB,CAC3C,eAAe,EACf,MAAM,CAAC,gBAAgB,CAAC;YACtB,EAAE,EAAE,eAAe;SACpB,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,OAAO,GAAmB;YAC9B,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;YAC5D,OAAO,EAAE,kBAAkB;YAC3B,IAAI,EAAE,kBAAkB;SACzB,CAAC;QAEF,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE/B,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,oBAAoB,CAC3C,oBAAoB,EACpB,MAAM,CAAC,gBAAgB,CAAC;YACtB,EAAE,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC;SACvC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC;YACjC,IAAI,EAAE;gBACJ,OAAO,EAAE,iBAAiB;aAC3B;SACF,CAAC,CAAC;QAEH,MAAM,OAAO,GAAmB;YAC9B,EAAE,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE;YAC9B,OAAO,EAAE,aAAa;YACtB,IAAI,EAAE,aAAa;SACpB,CAAC;QAEF,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CACrD,MAAM,CAAC,gBAAgB,CAAC;YACtB,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC;gBAC7B,OAAO,EAAE,iBAAiB;aAC3B,CAAC;SACH,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SendSmsRequest, SendSmsResponse } from 'townkrier-core';
|
|
2
|
+
import { TermiiSmsData, TermiiApiResponse } from '../interfaces';
|
|
3
|
+
import { TermiiConfig } from '../types';
|
|
4
|
+
export declare class TermiiMapper {
|
|
5
|
+
static toTermiiData(request: SendSmsRequest, config: TermiiConfig): TermiiSmsData;
|
|
6
|
+
static toSuccessResponse(data: TermiiApiResponse, request: SendSmsRequest): SendSmsResponse;
|
|
7
|
+
static toErrorResponse(error: unknown, defaultMessage: string): SendSmsResponse;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=termii.mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"termii.mapper.d.ts","sourceRoot":"","sources":["../../src/core/termii.mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,eAAe,EAIhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,qBAAa,YAAY;IACvB,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,GAAG,aAAa;IA0BjF,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,cAAc,GAAG,eAAe;IAgB3F,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,eAAe;CAuBhF"}
|