SMS
Transactional SMS sending with pluggable transport backends. The contract provides a concrete SmsService that applies config defaults (from) and delegates to an abstract SmsTransport sub-contract — the same pattern as mail (MailService + MailTransport).
Contract (@modularityjs/sms)
class SmsService {
send(message: SmsMessage): Promise<SmsSendResult>;
}
abstract class SmsTransport {
abstract send(message: SmsMessage): Promise<SmsSendResult>;
}SmsService is concrete — it composes config defaults and delegates to SmsTransport. Drivers implement SmsTransport.
Setup
import { SmsModule } from '@modularityjs/sms';
import { SmsTwilioModule } from '@modularityjs/sms-twilio';
const modules = [
SmsModule.forRoot({ from: '+15551234567' }),
SmsTwilioModule.forRoot({
accountSid: 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
authToken: 'your_auth_token',
}),
];Config
| Field | Type | Default | Description |
|---|---|---|---|
from | string | — | Default sender number |
Per-message from overrides the config default.
Drivers
Twilio (@modularityjs/sms-twilio)
SMS delivery via Twilio. Sends messages through the Twilio REST API.
SmsTwilioModule.forRoot({
accountSid: 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
authToken: 'your_auth_token',
});| Field | Type | Default | Description |
|---|---|---|---|
accountSid | string | — | Twilio Account SID |
authToken | string | — | Twilio Auth Token |
Memory (@modularityjs/sms-memory)
In-memory transport for testing. Stores sent messages in an array with getSent() and clear().
import { SmsMemoryModule, MemorySmsTransport } from '@modularityjs/sms-memory';
const modules = [SmsModule.forRoot({ from: '+15551234567' }), SmsMemoryModule];
// In tests — get the transport from the container
const transport = container.get(MemorySmsTransport);
expect(transport.getSent()).toHaveLength(1);
transport.clear();Sending SMS
Simple message
await smsService.send({
to: '+15559876543',
body: 'Your verification code is 123456.',
});Multiple recipients
await smsService.send({
to: ['+15559876543', '+15551112222'],
body: 'Server maintenance scheduled for tonight at 10 PM.',
});Queue Bridge (@modularityjs/sms-queue)
Async SMS delivery via the queue system. Publishes SmsMessage to a queue topic instead of sending synchronously. Follows the same pattern as @modularityjs/mail-queue.
import { SmsQueueModule, SMS_SEND_TOPIC } from '@modularityjs/sms-queue';Web process — enqueues SMS
const modules = [
RedisModule.forRoot({ host: 'localhost', port: 6379 }),
SmsModule.forRoot({ from: '+15551234567' }),
SmsQueueModule, // overrides SmsTransport with queue publisher
QueueModule,
QueueRedisModule,
];Worker process — sends via Twilio
const modules = [
RedisModule.forRoot({ host: 'localhost', port: 6379 }),
SmsModule.forRoot({ from: '+15551234567' }),
SmsTwilioModule.forRoot({
accountSid: 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
authToken: 'your_auth_token',
}),
QueueModule,
QueueRedisModule,
AppSmsConsumerModule, // your @Consume({ topic: 'sms.send', name: 'sms-send-handler' }) handler
];The consumer listens to SMS_SEND_TOPIC ('sms.send') and sends via the real SmsService (which resolves to Twilio in the worker process).
Custom Transport
Implement SmsTransport for any backend:
@Injectable()
class VonageSmsTransport extends SmsTransport {
async send(message: SmsMessage): Promise<SmsSendResult> {
// Use Vonage SMS API directly
const result = await vonage.sms.send({ ... });
return { messageId: result.messageId, accepted: [...], rejected: [] };
}
}
@Module({
name: 'sms-vonage',
imports: [SmsModule],
providers: [VonageSmsTransport],
preferences: [{ provide: SmsTransport, useClass: VonageSmsTransport }],
})
class SmsVonageModule {}Notification Integration
SMS works as a notification channel via @modularityjs/notification-sms. See the Notification docs for setup and usage.