npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mirad-work/sms-core

v0.4.0

Published

A framework-agnostic TypeScript SMS service core with provider abstraction for Iranian SMS providers

Readme

Mirad SMS Core

A powerful, framework-agnostic TypeScript SMS service library for Iranian SMS providers. Built with production-ready standards.

npm version TypeScript License: MIT Node.js GitHub stars GitHub forks

✨ Features

  • 🚀 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

📦 Supported Providers

  • 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

🚀 Quick Start

⚠️ Breaking Change Notice: The package name has changed from mirad-sms-core to @mirad-work/sms-core. If you're upgrading from a previous version, please see our Migration Guide for detailed instructions.

Installation

npm install @mirad-work/sms-core

Basic Usage

import { 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);
}

🔧 Configuration

Environment Variables

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_API_KEY=your-melipayamak-api-key
SMS_MELIPAYAMAK_LINE_NUMBER=your-line-number

# 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

Using Environment Configuration

import { SmsService, SmsConfigManager } from "@mirad-work/sms-core";

const config = SmsConfigManager.fromEnvironment();
const smsService = new SmsService(config);

Manual Configuration

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",
    },
  },
});

📱 Usage Examples

Sending Verification Code

// 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"],
});

Using Specific Drivers

// Force specific driver for this message
await smsService.verify({
  to: "+989123456789",
  template: "verify",
  tokens: { code: "123456" },
  driver: DriverType.SMSIR,
});

Error Handling

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);
  }
}

🏗️ Framework Integration

Express.js

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 });
  }
});

NestJS

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 },
    });
  }
}

🧪 Testing

Using Mock Driver

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,
});

Jest Testing Example

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();
  });
});

🔒 Security Considerations

  • 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

📊 Monitoring and Logging

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 conditions

🔧 Advanced Configuration

Custom HTTP Client

import { SmsService, HttpClient } from "@mirad-work/sms-core";

const customHttpClient = new HttpClient(15000); // 15 second timeout
const smsService = new SmsService(config, undefined, customHttpClient);

Multiple Driver Support

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
});

📚 API Documentation

Classes

  • SmsService - Main service class
  • SmsConfigManager - Configuration management
  • HttpClient - HTTP client implementation
  • Various driver classes and exceptions

Interfaces

  • ISmsMessage - SMS message structure
  • ISmsResponse - SMS response structure
  • ISmsConfig - Configuration interface

Types

  • DriverType - Supported driver types
  • SmsStatus - Message status types

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# 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 build

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🐛 Issues and Support

If you encounter any issues or need support:

  1. Check the documentation
  2. Search existing issues
  3. Create a new issue

📈 Roadmap

  • [ ] Additional SMS provider support
  • [ ] Message queuing capabilities
  • [ ] Advanced retry mechanisms
  • [ ] Webhooks and delivery status
  • [ ] Message templates management
  • [ ] Bulk SMS operations

🙏 Acknowledgments

  • Iranian SMS providers for their API documentation
  • TypeScript community for excellent tooling
  • All contributors who help improve this library

Connect With Us

  • 🌐 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