JSPM

@mirad-work/sms-core

0.3.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 15
  • Score
    100M100P100Q47967F
  • License MIT

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

Package Exports

  • @mirad-work/sms-core

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

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