A powerful, framework-agnostic TypeScript SMS service library for Iranian SMS providers. Built with production-ready standards.
- π Framework Agnostic: Works with any Node.js framework (Express, NestJS, Fastify, etc.)
- π§ TypeScript First: Full TypeScript support with comprehensive type definitions
- ποΈ Modular Architecture: Clean separation of concerns with driver pattern
- π Multiple Providers: Support for major Iranian SMS providers
- βοΈ Configuration Flexibility: Environment variables, direct config, or factory methods
- π§ͺ Production Ready: Comprehensive error handling, logging, and testing
- π± OTP/Verification: Specialized support for verification and OTP messages
- π Secure: Input validation and security best practices
- π Well Documented: Extensive documentation and examples
- Kavenegar - Full support for verification APIs
- SMS.ir - Complete integration with template messaging
- Melipayamak - Pattern-based SMS support
- IPPanel - Pattern-based SMS with dynamic variables
- Mock Driver - For testing and development
β οΈ Breaking Change Notice: The package name has changed frommirad-sms-coreto@mirad-work/sms-core. If you're upgrading from a previous version, please see our Migration Guide for detailed instructions.
npm install @mirad-work/sms-coreimport { SmsService, SmsConfigManager } from "@mirad-work/sms-core";
// Using factory method (recommended)
const smsService = SmsConfigManager.createKavenegarConfig({
apiKey: "your-kavenegar-api-key",
lineNumber: "your-line-number",
});
// Send verification SMS
const result = await smsService.verify({
to: "+989123456789",
template: "verification-code",
tokens: { code: "12345" },
});
if (result.success) {
console.log("SMS sent successfully!", result.messageId);
} else {
console.error("Failed to send SMS:", result.error);
}Create a .env file in your project root:
# SMS Service Configuration
SMS_DEFAULT_DRIVER=kavenegar
SMS_TIMEOUT=10000
# Kavenegar Configuration
SMS_KAVENEGAR_API_KEY=your-kavenegar-api-key
SMS_KAVENEGAR_LINE_NUMBER=your-line-number
SMS_KAVENEGAR_URL=https://api.kavenegar.com/v1/
# SMS.ir Configuration
SMS_SMSIR_API_KEY=your-smsir-api-key
SMS_SMSIR_LINE_NUMBER=your-line-number
# Melipayamak Configuration
SMS_MELIPAYAMAK_URL=https://rest.payamak-panel.com/api/SendSMS/
SMS_MELIPAYAMAK_USERNAME=your-melipayamak-username
SMS_MELIPAYAMAK_PASSWORD=your-melipayamak-password-or-api-key
# IPPanel Configuration
SMS_IPPANEL_API_KEY=your-ippanel-api-key
SMS_IPPANEL_LINE_NUMBER=your-line-number
SMS_IPPANEL_URL=https://api2.ippanel.com/<ο½toolβcallsβbeginο½><ο½toolβcallβbeginο½> read_file
import { SmsService, SmsConfigManager } from "@mirad-work/sms-core";
const config = SmsConfigManager.fromEnvironment();
const smsService = new SmsService(config);import { SmsService, DriverType } from "@mirad-work/sms-core";
const smsService = new SmsService({
defaultDriver: DriverType.KAVENEGAR,
timeout: 10000,
drivers: {
kavenegar: {
url: "https://api.kavenegar.com/v1/",
apiKey: "your-api-key",
lineNumber: "your-line-number",
},
},
});// Simple verification code
await smsService.verify({
to: "+989123456789",
template: "verify",
tokens: { code: "123456" },
});
// Multiple tokens
await smsService.verify({
to: "+989123456789",
template: "welcome",
tokens: { name: "John", code: "123456" },
});
// Array tokens (positional)
await smsService.verify({
to: "+989123456789",
template: "order-status",
tokens: ["John Doe", "Delivered", "Order #12345"],
});// Force specific driver for this message
await smsService.verify({
to: "+989123456789",
template: "verify",
tokens: { code: "123456" },
driver: DriverType.SMSIR,
});try {
const result = await smsService.verify({
to: "+989123456789",
template: "verify",
tokens: { code: "123456" },
});
if (!result.success) {
console.error("SMS failed:", result.error);
console.error("Error code:", result.errorCode);
}
} catch (error) {
if (error instanceof MessageValidationException) {
console.error("Invalid message:", error.message);
} else if (error instanceof SmsDriverException) {
console.error("Driver error:", error.message);
}
}import express from "express";
import { createKavenegarSmsService } from "@mirad-work/sms-core";
const app = express();
const smsService = createKavenegarSmsService({
apiKey: process.env.KAVENEGAR_API_KEY!,
lineNumber: process.env.KAVENEGAR_LINE_NUMBER!,
});
app.post("/send-otp", async (req, res) => {
try {
const result = await smsService.verify({
to: req.body.phone,
template: "otp",
tokens: { code: generateOTP() },
});
res.json({ success: true, messageId: result.messageId });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});import { Injectable } from "@nestjs/common";
import { SmsService, SmsConfigManager } from "@mirad-work/sms-core";
@Injectable()
export class NotificationService {
private smsService: SmsService;
constructor() {
this.smsService = new SmsService(SmsConfigManager.fromEnvironment());
}
async sendVerificationCode(phone: string, code: string) {
return await this.smsService.verify({
to: phone,
template: "verification",
tokens: { code },
});
}
}import { createMockSmsService } from "@mirad-work/sms-core";
// For testing - always succeeds
const mockService = createMockSmsService();
// For testing failures
const failingMockService = createMockSmsService({
shouldFail: true,
});
// Simulate network delay
const slowMockService = createMockSmsService({
delay: 1000,
});import { SmsService, SmsConfigManager } from "@mirad-work/sms-core";
describe("SMS Service", () => {
let smsService: SmsService;
beforeEach(() => {
smsService = new SmsService(SmsConfigManager.createForTesting());
});
it("should send verification SMS", async () => {
const result = await smsService.verify({
to: "+989123456789",
template: "verify",
tokens: { code: "123456" },
});
expect(result.success).toBe(true);
expect(result.messageId).toBeDefined();
});
});- Always validate phone numbers before sending
- Use environment variables for sensitive configuration
- Implement rate limiting in your application
- Log SMS operations for audit trails
- Use HTTPS for all API communications
The library includes built-in logging for debugging:
// Enable debug logging
process.env.NODE_ENV = "development";
// Logs will appear in console for:
// - SMS send attempts
// - API responses
// - Error conditionsimport { SmsService, HttpClient } from "@mirad-work/sms-core";
const customHttpClient = new HttpClient(15000); // 15 second timeout
const smsService = new SmsService(config, undefined, customHttpClient);const config = {
defaultDriver: DriverType.KAVENEGAR,
drivers: {
kavenegar: {
url: "https://api.kavenegar.com/v1/",
apiKey: "kavenegar-key",
lineNumber: "kavenegar-line",
},
smsir: {
url: "https://api.sms.ir/v1/",
apiKey: "smsir-key",
lineNumber: "smsir-line",
},
},
};
// Use different providers for different purposes
await smsService.verify({
to: "+989123456789",
template: "otp",
tokens: { code: "123456" },
driver: DriverType.SMSIR, // Override default
});SmsService- Main service classSmsConfigManager- Configuration managementHttpClient- HTTP client implementation- Various driver classes and exceptions
ISmsMessage- SMS message structureISmsResponse- SMS response structureISmsConfig- Configuration interface
DriverType- Supported driver typesSmsStatus- Message status types
We welcome contributions! Please see our Contributing Guide for details.
- π Contributing Guide - How to contribute to the project
- π Code of Conduct - Community guidelines
- π Issue Templates - Templates for bug reports and feature requests
# Clone the repository
git clone https://github.com/mirad-work/sms-core.git
cd sms-core
# Install dependencies
npm install
# Run tests
npm test
# Run linting
npm run lint
# Build the project
npm run buildThis project is licensed under the MIT License - see the LICENSE file for details.
If you encounter any issues or need support:
- Check the documentation
- Search existing issues
- Create a new issue
- Additional SMS provider support
- Message queuing capabilities
- Advanced retry mechanisms
- Webhooks and delivery status
- Message templates management
- Bulk SMS operations
- Iranian SMS providers for their API documentation
- TypeScript community for excellent tooling
- All contributors who help improve this library
- π Website - Learn more about Mirad Work Organization
- π§ Open Source Team - Questions about our open source projects
Made with β€οΈ by Mirad Work Organization for the Iranian developer community