ussd-flow
v0.1.2
Published
A lightweight TypeScript framework for building modular, scalable USSD applications.
Downloads
21
Maintainers
Readme
ussd-flow
A lightweight TypeScript framework for building modular, scalable USSD applications.
Features
- 🚀 Session Management - In-memory, Redis, SQLite, MySQL, PostgreSQL session stores
- 📱 Menu System - Easy-to-use menu navigation and state management
- 🔄 Context Management - Track user state and navigation history
- 🛠️ Middleware Support - Pre/post processing of requests
- 🗄️ Database Integration - Support for multiple database backends
- 📊 Production Ready - Metrics, health checks, graceful shutdown, security
- 📦 Framework Agnostic - Works with Express, NestJS, Fastify, and more
- 🎯 TypeScript First - Full type safety and modern development experience
- 🏗️ SOLID Principles - Clean, maintainable architecture
Quick Start
npm install ussd-flowimport { USSDApp, State, USSDContext, Menu, DefaultMenu } from 'ussd-flow';
// Define your states
class WelcomeState implements State {
readonly name = 'welcome';
async render(context: USSDContext): Promise<Menu> {
return new DefaultMenu('Welcome to USSD Flow', [
{ key: '1', text: 'Get Started', action: 'start' },
{ key: '0', text: 'Exit', action: 'exit' },
]);
}
}
// Create and configure your app
const app = new USSDApp();
app.registerState(new WelcomeState());
// Handle USSD requests
app.handleRequest({
sessionId: 'session_123',
phoneNumber: '+1234567890',
serviceCode: '*123#',
text: '1'
}).then(response => {
console.log(response.message);
});Framework Integration
Express.js Example
import express from 'express';
import { USSDApp } from 'ussd-flow';
const app = express();
const ussd = new USSDApp();
app.post('/ussd', async (req, res) => {
const response = await ussd.handleRequest(req.body);
res.json(response);
});
app.listen(3000);NestJS Example
import { Controller, Post, Body } from '@nestjs/common';
import { USSDApp } from 'ussd-flow';
@Controller('ussd')
export class USSDController {
private ussd = new USSDApp();
@Post()
async handleUSSD(@Body() request: any) {
return await this.ussd.handleRequest(request);
}
}Architecture
The framework follows SOLID principles and provides:
- Single Responsibility: Each class has one clear purpose
- Open/Closed: Easy to extend without modifying existing code
- Liskov Substitution: All implementations are interchangeable
- Interface Segregation: Small, focused interfaces
- Dependency Inversion: Depend on abstractions, not concretions
Core Components
States
States define the different screens/menus in your USSD application:
class MyState implements State {
readonly name = 'my_state';
async render(context: USSDContext): Promise<Menu> {
return new DefaultMenu('My Menu', [
{ key: '1', text: 'Option 1', action: 'option1' },
{ key: '2', text: 'Option 2', action: 'option2' },
]);
}
}Session Management
Sessions automatically track user state and navigation:
// Sessions are automatically created and managed
// Access session data through context
const sessionData = context.session.data;
context.session.updateData({ key: 'value' });Middleware
Add custom logic to process requests:
app.addMiddleware({
async execute(context: USSDContext, next: () => Promise<void>): Promise<void> {
console.log(`Processing request for ${context.session.phoneNumber}`);
await next();
}
});CLI Tool
The framework includes a powerful CLI tool for generating providers and states:
Installation
npm install -g ussd-flowUsage
Important: When using npm scripts, you must use the -- separator to pass arguments:
# Correct way to use npm scripts
npm run cli -- make:provider MyProvider --template=appsNmobile
npm run cli -- make:state WelcomeState
npm run cli -- list:templates
# Or use the direct CLI command
ussd-flow make:provider MyProvider --template=appsNmobile
ussd-flow make:state WelcomeState
ussd-flow list:templatesAvailable Commands
make:provider <name> [options]- Generate a custom USSD providermake:state <name> [options]- Generate a USSD state classlist:templates- List available provider templateshelp- Show help information
Provider Templates
- appsNmobile - appsNmobile Orchard API format
- Ghana - Ghana USSD provider format
- AfricasTalking - AfricasTalking USSD provider
- Twilio - Twilio USSD provider
- Hubtel - Hubtel USSD provider
- Nalo - Nalo USSD provider
- Generic - Generic template for custom implementations
Examples
# Generate appsNmobile provider
npm run cli -- make:provider AppsNmobileProvider --template=appsNmobile
# Generate Ghana provider
npm run cli -- make:provider GhanaProvider --template=Ghana
# Generate state
npm run cli -- make:state WelcomeState --output=./src/statesDatabase Integration
The framework supports multiple database backends for session storage. Database packages are optional peer dependencies, so you only install what you need.
Supported Databases
- Redis - High-performance in-memory data store
- SQLite - Lightweight file-based database
- MySQL - Popular relational database
- PostgreSQL - Advanced open-source database
Installation
Install the database packages you need:
# For Redis
npm install redis
# For SQLite
npm install sqlite3
# For MySQL
npm install mysql2
# For PostgreSQL
npm install pgUsage Examples
Redis Configuration
import { USSDApp, USSDUtils } from 'ussd-flow';
const app = new USSDApp();
// Use Redis database
await app.useDatabase({
type: 'redis',
host: 'localhost',
port: 6379,
// Or use connection string
// connectionString: 'redis://localhost:6379'
});
// Or use helper function
const redisConfig = USSDUtils.createRedisConfig('localhost', 6379);
await app.useDatabase(redisConfig);SQLite Configuration
// Use SQLite database
await app.useDatabase({
type: 'sqlite',
database: './ussd_sessions.db'
});
// Or use helper function
const sqliteConfig = USSDUtils.createSQLiteConfig('./ussd_sessions.db');
await app.useDatabase(sqliteConfig);MySQL Configuration
// Use MySQL database
await app.useDatabase({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'ussd_user',
password: 'ussd_password',
database: 'ussd_sessions'
});
// Or use helper function
const mysqlConfig = USSDUtils.createMySQLConfig(
'localhost',
'ussd_user',
'ussd_password',
'ussd_sessions'
);
await app.useDatabase(mysqlConfig);PostgreSQL Configuration
// Use PostgreSQL database
await app.useDatabase({
type: 'postgresql',
host: 'localhost',
port: 5432,
username: 'ussd_user',
password: 'ussd_password',
database: 'ussd_sessions'
});
// Or use helper function
const postgresConfig = USSDUtils.createPostgreSQLConfig(
'localhost',
'ussd_user',
'ussd_password',
'ussd_sessions'
);
await app.useDatabase(postgresConfig);Production Configuration
import { USSDApp } from 'ussd-flow';
const app = new USSDApp({
// Database configuration
database: {
type: 'redis',
connectionString: process.env.REDIS_URL,
options: {
retryDelayOnFailover: 100,
maxRetriesPerRequest: 3
}
},
// Production-ready options
environment: 'production',
enableMetrics: true,
enableHealthCheck: true,
enableGracefulShutdown: true,
enableRateLimiting: true,
enableSecurityHeaders: true,
enableAuditLogging: true,
enablePerformanceMonitoring: true,
// Security settings
securityHeaders: {
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY',
'X-XSS-Protection': '1; mode=block'
},
// Rate limiting
rateLimitWindow: 60000, // 1 minute
rateLimitMax: 100, // 100 requests per window
// Performance monitoring
performanceThreshold: 1000, // 1 second
});
// Start health checks and cleanup
await app.startSessionCleanup(5 * 60 * 1000); // Every 5 minutesError Handling
The framework gracefully handles missing database packages:
try {
await app.useDatabase(redisConfig);
} catch (error) {
console.error('Database Error:', error.message);
// Error message will indicate which package to install
// e.g., "Redis package not installed. Install with: npm install redis"
}Example Application
See example.ts for a complete example application demonstrating:
- Multiple states and navigation
- Menu creation and rendering
- Session management
- Middleware usage
Documentation
For detailed documentation, examples, and advanced usage, visit our GitHub repository.
License
MIT License - see LICENSE file for details.
