termii-nestjs
Version:
A NestJS SDK for Termii API
309 lines (244 loc) • 8.93 kB
Markdown
# Termii NestJS SDK
[](https://badge.fury.io/js/termii-nestjs)
[](https://opensource.org/licenses/MIT)
A robust, well-structured, and fully-typed NestJS SDK for interacting with the [Termii API](https://developers.termii.com/). This library simplifies sending SMS and WhatsApp messages with a developer-friendly API.
## Features
- ✅ Easy integration with any NestJS application
- ✅ Static (`forRoot`) and async (`forRootAsync`) module configuration
- ✅ Strongly-typed DTOs for both requests and responses
- ✅ **Full Termii API Coverage:**
- **Messaging:** Send SMS & WhatsApp messages, manage Sender IDs, and Phone Books.
- **Token:** Send, verify, and generate OTPs via SMS, Voice, and Email.
- **Insights:** Check account balance, search history, and perform number lookups.
## Installation
```bash
npm install termii-nestjs
```
or
```bash
yarn add termii-nestjs
```
This library has peer dependencies on several NestJS packages. If they are not already installed in your project, you will need to add them:
```bash
npm install /common /core reflect-metadata
```
## Getting Started
### 1. Import the Module
Import `TermiiModule` into your root `AppModule`.
#### Static Configuration (`forRoot`)
This method is suitable for simple configurations where credentials are not loaded dynamically.
```typescript
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TermiiModule } from 'termii-nestjs';
export class AppModule {}
```
#### Async Configuration (`forRootAsync`)
This is the recommended approach, especially when using `/config` to manage environment variables.
```typescript
// src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TermiiModule } from 'termii-nestjs';
export class AppModule {}
```
### 2. Inject and Use `TermiiService`
You can now inject `TermiiService` into any of your services or controllers. The service is namespaced to provide easy access to different parts of the Termii API:
- `termiiService.messaging`
- `termiiService.token`
- `termiiService.insight`
Below are examples for each service.
### Messaging API
The `messaging` service handles sending messages and managing related resources like Sender IDs and Phone Books.
#### Example: Sending an SMS
```typescript
import { Injectable, Logger } from '@nestjs/common';
import { TermiiService, TermiiSendMessageRequest } from 'termii-nestjs';
export class NotificationService {
private readonly logger = new Logger(NotificationService.name);
constructor(private readonly termiiService: TermiiService) {}
async sendWelcomeMessage(phoneNumber: string) {
const payload: TermiiSendMessageRequest = {
to: phoneNumber,
from: 'YourSenderID', // This will be the sender ID displayed on the recipient's device
sms: 'Hi there, welcome to our service!',
channel: 'generic', // Use 'generic' for SMS, 'dnd' to bypass DND, or 'whatsapp'
};
try {
const response = await this.termiiService.messaging.sendMessage(payload);
this.logger.log(`Message sent. Message ID: ${response.message_id}`);
} catch (error) {
this.logger.error(
'Failed to send SMS',
error.response?.data || error.message
);
}
}
}
```
#### Example: Requesting a Sender ID
```typescript
import { Injectable, Logger } from '@nestjs/common';
import { TermiiService, TermiiRequestSenderIdRequest } from 'termii-nestjs';
export class OnboardingService {
private readonly logger = new Logger(OnboardingService.name);
constructor(private readonly termiiService: TermiiService) {}
async requestNewSenderId() {
const payload: TermiiRequestSenderIdRequest = {
sender_id: 'NewBrand',
usecase:
'We will use this to send transaction notifications to our customers.',
company: 'My Awesome Company',
};
try {
const response = await this.termiiService.messaging.requestSenderId(
payload
);
this.logger.log(`Sender ID request successful: ${response.message}`);
} catch (error) {
this.logger.error(
'Failed to request Sender ID',
error.response?.data || error.message
);
}
}
}
```
### Token API
The `token` service is used for sending and verifying One-Time Passwords (OTPs) through various channels.
#### Example: Sending an OTP via SMS
```typescript
import { Injectable, Logger } from '@nestjs/common';
import { TermiiService, TermiiSendTokenRequest } from 'termii-nestjs';
export class AuthService {
private readonly logger = new Logger(AuthService.name);
constructor(private readonly termiiService: TermiiService) {}
async sendLoginOtp(phoneNumber: string) {
const payload: TermiiSendTokenRequest = {
message_type: 'NUMERIC',
to: phoneNumber,
from: 'YourSenderID',
channel: 'generic',
pin_attempts: 3,
pin_time_to_live: 5, // In minutes
pin_length: 6,
pin_placeholder: '< 1234 >',
message_text: 'Your login code is < 1234 >. It will expire in 5 minutes.',
};
try {
const response = await this.termiiService.token.sendToken(payload);
this.logger.log(`OTP sent. Pin ID: ${response.pinId}`);
return response.pinId; // Return pinId to be used for verification
} catch (error) {
this.logger.error(
'Failed to send OTP',
error.response?.data || error.message
);
}
}
}
```
#### Example: Verifying an OTP
```typescript
import { Injectable, Logger } from '@nestjs/common';
import { TermiiService, TermiiVerifyTokenRequest } from 'termii-nestjs';
export class AuthService {
private readonly logger = new Logger(AuthService.name);
constructor(private readonly termiiService: TermiiService) {}
async verifyLoginOtp(pinId: string, pin: string) {
const payload: TermiiVerifyTokenRequest = { pin_id: pinId, pin: pin };
try {
const response = await this.termiiService.token.verifyToken(payload);
if (response.verified) {
this.logger.log(`OTP verification successful for ${response.msisdn}`);
return true;
}
this.logger.warn(`OTP verification failed for pinId: ${pinId}`);
return false;
} catch (error) {
this.logger.error(
'Failed to verify OTP',
error.response?.data || error.message
);
return false;
}
}
}
```
### Insight API
The `insight` service provides tools for checking your account status and looking up information about phone numbers.
#### Example: Checking Your Balance
```typescript
import { Injectable, Logger } from '@nestjs/common';
import { TermiiService } from 'termii-nestjs';
export class AdminService {
private readonly logger = new Logger(AdminService.name);
constructor(private readonly termiiService: TermiiService) {}
async checkAccountBalance() {
try {
const response = await this.termiiService.insight.getBalance();
this.logger.log(
`Account balance: ${response.balance} ${response.currency}`
);
} catch (error) {
this.logger.error(
'Failed to fetch balance',
error.response?.data || error.message
);
}
}
}
```
#### Example: Checking DND Status of a Phone Number
```typescript
import { Injectable, Logger } from '@nestjs/common';
import { TermiiService } from 'termii-nestjs';
export class CustomerSupportService {
private readonly logger = new Logger(CustomerSupportService.name);
constructor(private readonly termiiService: TermiiService) {}
async checkDndStatus(phoneNumber: string) {
try {
// The search method checks the DND status of a number
const response = await this.termiiService.insight.search(phoneNumber);
this.logger.log(`DND status for ${response.number}:`, {
dndActive: response.dnd_active,
network: response.network_code,
});
} catch (error) {
this.logger.error(
`Failed to check DND status for ${phoneNumber}`,
error.response?.data || error.message
);
}
}
}
```
## License
This project is licensed under the MIT License.