Skip to content

Repository files navigation

📨 WebVentures Comms SDK

Unified Communication SDK for Modern Applications

Send emails, SMS, push notifications, and more with a single, type-safe API

npm version npm downloads TypeScript Node.js MIT License CI

FeaturesInstallationQuick StartDocumentationExamples


🎯 Overview

WebVentures Comms SDK is a production-ready, type-safe communication library that provides a unified interface for sending transactional notifications across multiple channels and providers. Built entirely in TypeScript with first-class support for modern frameworks.

Why WebVentures Comms SDK?

// One SDK, multiple channels, full type safety
import CommsSdk from '@webventures/comms'

const comms = new CommsSdk({
  channels: {
    email: { providers: [{ type: 'sendgrid', apiKey: process.env.SENDGRID_KEY }] },
    sms: { providers: [{ type: 'twilio', accountSid: '...', authToken: '...' }] },
    push: { providers: [{ type: 'fcm', id: 'your-fcm-key' }] },
  },
})

// Send notifications with intelligent fallback
await comms.send({
  email: { to: 'user@example.com', subject: 'Welcome!', html: '<h1>Hello!</h1>' },
  sms: { to: '+1234567890', text: 'Welcome to WebVentures!' },
  push: { registrationToken: 'device-token', title: 'Welcome!', body: 'Get started' },
})

Key Benefits

Feature Description
🎯 Unified API Single interface for all notification channels
🛡️ Type-Safe Full TypeScript support with comprehensive IntelliSense
⚡ Multi-Provider Built-in failover & load balancing across 40+ providers
🚀 Framework-First Optimized for Next.js 16+, React 19, React Native, Expo
🔧 Production-Ready Battle-tested error handling, logging, and provider abstraction
🎨 Developer-Friendly Local testing tools, extensive docs, and real-world examples
📦 Tree-Shakeable Modular exports for optimal bundle size
🔌 Extensible Custom providers and strategies support

✨ Features

📬 Supported Channels

📧 Email

SMTP, SendGrid, AWS SES, Mailgun, Mandrill, SparkPost, Sendmail

💬 SMS

Twilio, Vonage, Plivo, Infobip, OVH, Callr, Clickatell, 46elks, Seven

📱 Push

APNs (iOS), FCM (Android/iOS), WNS (Windows), ADM (Amazon)

🔊 Voice

Twilio Voice with TwiML support

🌐 Webpush

Web Push with VAPID authentication

💼 Slack

Webhook integration with rich formatting

💚 WhatsApp

Infobip WhatsApp Business API

📱 Telegram

Telegram Bot API with rich formatting

🎯 Custom

Build your own providers

More channels coming soon

🏗️ Framework Support

  • Next.js 16+ - Server Components, Server Actions, API Routes, Edge Runtime
  • React 19 - Latest React with full concurrent features
  • React Native - Native mobile app integration
  • Expo - Managed React Native workflow with push notifications
  • Node.js 18+ - Standard Node.js applications, CLI tools, serverless

🔄 Multi-Provider Strategies

Strategy Description Use Case
Fallback Automatic failover to backup providers High availability, 99.9% uptime
Round-robin Load balancing across providers Cost optimization, rate limiting
No-fallback Single provider with immediate errors Testing, debugging
Weighted Probability-based provider selection Gradual rollouts, A/B testing
Custom Define your own selection logic Geographic routing, custom logic

🚀 Installation

# Using npm
npm install @webventures/comms

# Using yarn
yarn add @webventures/comms

# Using pnpm
pnpm add @webventures/comms

Requirements

  • Node.js: 18.0.0 or higher
  • TypeScript: 5.0.0 or higher (optional)

Optional Development Tools

For local testing:

npm install --save-dev notification-catcher

⚡ Quick Start

1. Basic Email Sending

import CommsSdk from '@webventures/comms'

const comms = new CommsSdk({
  channels: {
    email: {
      providers: [
        {
          type: 'sendgrid',
          apiKey: process.env.SENDGRID_API_KEY,
        },
      ],
    },
  },
})

const result = await comms.send({
  email: {
    from: 'noreply@example.com',
    to: 'user@example.com',
    subject: 'Welcome to WebVentures!',
    html: '<h1>Hello!</h1><p>Thanks for signing up.</p>',
  },
})

console.log(result)
// { status: 'success', channels: { email: { id: 'msg-123', providerId: 'sendgrid' } } }

2. Multi-Channel with High Availability

const comms = new CommsSdk({
  channels: {
    email: {
      multiProviderStrategy: 'fallback', // Automatic failover
      providers: [
        { type: 'sendgrid', apiKey: process.env.SENDGRID_KEY }, // Primary
        { type: 'ses', region: 'us-east-1', accessKeyId: '...', secretAccessKey: '...' }, // Backup
        { type: 'mailgun', apiKey: '...', domainName: 'mg.example.com' }, // Fallback
      ],
    },
    sms: {
      providers: [
        {
          type: 'twilio',
          accountSid: process.env.TWILIO_SID,
          authToken: process.env.TWILIO_TOKEN,
        },
      ],
    },
  },
})

// If SendGrid fails, automatically tries SES, then Mailgun
await comms.send({
  email: {
    from: 'alerts@example.com',
    to: 'user@example.com',
    subject: 'Critical Alert',
    text: 'Your account requires immediate attention.',
  },
  sms: {
    from: '+1234567890',
    to: '+0987654321',
    text: 'Critical alert - check your email',
  },
})

3. Next.js 16+ Server Actions

// app/actions/notifications.ts
'use server'

import { createNextJSComms } from '@webventures/comms/adapters'

export async function sendWelcomeEmail(email: string) {
  const comms = createNextJSComms({
    channels: {
      email: {
        providers: [{ type: 'sendgrid', apiKey: process.env.SENDGRID_API_KEY! }],
      },
    },
  })

  return await comms.send({
    email: {
      from: 'noreply@example.com',
      to: email,
      subject: 'Welcome!',
      html: '<h1>Thanks for joining!</h1>',
    },
  })
}
// app/signup/page.tsx
import { sendWelcomeEmail } from '../actions/notifications'

export default function SignupPage() {
  return (
    <form action={async (formData) => {
      'use server'
      const email = formData.get('email') as string
      await sendWelcomeEmail(email)
    }}>
      <input type="email" name="email" required />
      <button type="submit">Sign Up</button>
    </form>
  )
}

4. React Native Push Notifications

import { createReactNativeComms } from '@webventures/comms/adapters'

const comms = createReactNativeComms({
  channels: {
    push: {
      providers: [
        {
          type: 'fcm',
          id: process.env.FCM_SERVER_KEY,
        },
      ],
    },
  },
})

await comms.send({
  push: {
    registrationToken: deviceToken,
    title: 'New Message',
    body: 'You have a new message from John',
    badge: 1,
    sound: 'default',
    custom: {
      messageId: '123',
      type: 'chat',
    },
  },
})

🎨 Framework Integration

Next.js 16+ (App Router)

// lib/comms.ts - Reusable SDK instance
import { withComms } from '@webventures/comms/adapters'

export const sendNotification = withComms(
  async (comms, options) => {
    return await comms.send(options)
  },
  {
    channels: {
      email: {
        providers: [{ type: 'sendgrid', apiKey: process.env.SENDGRID_API_KEY! }],
      },
    },
  }
)
// app/api/notify/route.ts - API Route
import { sendNotification } from '@/lib/comms'

export async function POST(request: Request) {
  const { email, message } = await request.json()

  const result = await sendNotification({
    email: {
      from: 'noreply@example.com',
      to: email,
      subject: 'Notification',
      text: message,
    },
  })

  return Response.json(result)
}

Expo with Push Notifications

import { createExpoComms } from '@webventures/comms/adapters'
import * as Notifications from 'expo-notifications'

const comms = createExpoComms({
  channels: {
    push: {
      providers: [
        {
          type: 'fcm',
          id: process.env.EXPO_FCM_KEY,
        },
      ],
    },
  },
})

// Get push token
const token = (await Notifications.getExpoPushTokenAsync()).data

// Send notification
await comms.send({
  push: {
    registrationToken: token,
    title: 'Expo Notification',
    body: 'Hello from WebVentures Comms!',
  },
})

Node.js Express API

import express from 'express'
import { createNodeComms } from '@webventures/comms/adapters'

const app = express()
const comms = createNodeComms({
  channels: {
    email: { providers: [{ type: 'smtp', host: 'smtp.gmail.com', port: 587 }] },
  },
})

app.post('/api/send-email', async (req, res) => {
  const result = await comms.send({
    email: {
      from: 'noreply@example.com',
      to: req.body.email,
      subject: 'Hello',
      text: 'Your message here',
    },
  })

  res.json(result)
})

app.listen(3000)

See complete framework guides →


📘 Documentation

Complete Guides

Quick Links

Topic Link
Error Handling docs/README.md#error-handling
Multi-Provider Strategies docs/README.md#multi-provider-strategies
TypeScript Types docs/API.md#types
Custom Providers docs/PROVIDERS.md#custom-providers
Production Patterns docs/EXAMPLES.md#production
Testing Guide docs/EXAMPLES.md#testing

💡 Examples

Email with Attachments

await comms.send({
  email: {
    from: 'billing@example.com',
    to: 'customer@example.com',
    subject: 'Invoice #12345',
    html: '<h1>Your Invoice</h1><p>Please find attached.</p>',
    attachments: [
      {
        filename: 'invoice.pdf',
        content: pdfBuffer,
        contentType: 'application/pdf',
      },
    ],
    cc: ['accounting@example.com'],
    bcc: ['archive@example.com'],
  },
})

SMS with Unicode

await comms.send({
  sms: {
    from: '+1234567890',
    to: '+0987654321',
    text: '您的验证码是: 123456',
    type: 'unicode',
  },
})

Push with Rich Notifications

await comms.send({
  push: {
    registrationToken: 'device-token',
    title: 'New Message from John',
    body: 'Hey, are you coming to the meeting?',
    icon: 'https://example.com/avatar.png',
    image: 'https://example.com/preview.jpg',
    badge: 5,
    sound: 'default',
    priority: 'high',
    clickAction: 'OPEN_CHAT',
    custom: {
      chatId: '123',
      senderId: '456',
      type: 'chat_message',
    },
  },
})

Slack Rich Messages

await comms.send({
  slack: {
    text: 'Production deployment completed! 🎉',
    attachments: [
      {
        color: 'good',
        title: 'v2.0.5 Deployment',
        text: 'All systems operational',
        fields: [
          { title: 'Environment', value: 'Production', short: true },
          { title: 'Version', value: 'v2.0.5', short: true },
          { title: 'Deploy Time', value: '2 minutes', short: true },
          { title: 'Status', value: '✅ Success', short: true },
        ],
        footer: 'WebVentures Deploy Bot',
        ts: Math.floor(Date.now() / 1000),
      },
    ],
  },
})

Telegram Notifications

await comms.send({
  telegram: {
    chatId: '-1001234567890',
    text: `
<b>🚀 Deployment Complete</b>

<b>Environment:</b> Production
<b>Version:</b> <code>v2.0.5</code>
<b>Status:</b> ✅ Success

<i>All systems operational</i>

<a href="https://status.example.com">View Status</a>
    `.trim(),
    parseMode: 'HTML',
  },
})

Custom Strategy (Geographic Routing)

import type { StrategyFunction } from '@webventures/comms'

const geographicRouting: StrategyFunction = (providers, notification) => {
  const userCountry = notification.metadata?.country

  // Route EU users to EU provider, US users to US provider
  if (userCountry === 'DE' || userCountry === 'FR') {
    return providers.find((p) => p.id === 'eu-provider')
  }

  if (userCountry === 'US') {
    return providers.find((p) => p.id === 'us-provider')
  }

  return providers[0] // Default
}

const comms = new CommsSdk({
  channels: {
    email: {
      providers: [
        { type: 'ses', id: 'us-provider', region: 'us-east-1' },
        { type: 'ses', id: 'eu-provider', region: 'eu-west-1' },
      ],
      customStrategy: geographicRouting,
    },
  },
})

See more examples →


🛡️ Error Handling

Response Status Checking

const result = await comms.send({
  /* ... */
})

if (result.status === 'success') {
  console.log('✓ Notification sent:', result.channels.email?.id)
} else {
  console.error('✗ Notification failed:', result.errors)
  result.errors?.forEach((error) => {
    console.error(`${error.channel}: ${error.message}`)
  })
}

Using Type Guards

import { isSuccessResponse, isErrorResponse, getErrors, isCommsError } from '@webventures/comms'

const result = await comms.send({
  /* ... */
})

if (isSuccessResponse(result)) {
  console.log('Success!', result.channels)
}

if (isErrorResponse(result)) {
  const errors = getErrors(result)
  errors.forEach((err) => console.error(err.message))
}

Try-Catch Pattern

import { CommsError, ProviderError } from '@webventures/comms'

try {
  await comms.send({
    /* ... */
  })
} catch (error) {
  if (error instanceof ProviderError) {
    console.error(`Provider ${error.providerId} failed on ${error.channel}:`, error.message)
    // Implement fallback logic or alerting
  } else if (error instanceof CommsError) {
    console.error('SDK Error:', error.code, error.message)
  } else {
    console.error('Unexpected error:', error)
  }
}

🧪 Local Development & Testing

Notification Catcher

For local development, use Notification Catcher to intercept all notifications in a web UI:

# Install
npm install --save-dev notification-catcher

# Start catcher (runs on port 1080)
npx notification-catcher

Configure SDK:

const comms = new CommsSdk({
  useNotificationCatcher: true, // Sends all to http://localhost:1080
  channels: {
    email: { providers: [{ type: 'logger' }] }, // Optional: also log to console
  },
})

await comms.send({
  email: {
    from: 'test@example.com',
    to: 'user@example.com',
    subject: 'Test Email',
    html: '<h1>Testing</h1>',
  },
})

Open http://localhost:1080 to view all sent notifications with full headers, content, and metadata.

Environment-Based Configuration

const isDev = process.env.NODE_ENV === 'development'
const isProd = process.env.NODE_ENV === 'production'

const comms = new CommsSdk({
  useNotificationCatcher: isDev,
  channels: {
    email: {
      providers: isProd
        ? [
            { type: 'sendgrid', apiKey: process.env.SENDGRID_API_KEY! },
            { type: 'ses', region: 'us-east-1', accessKeyId: '...', secretAccessKey: '...' },
          ]
        : [{ type: 'logger' }],
    },
  },
})

📦 TypeScript Support

WebVentures Comms SDK is built with TypeScript and provides comprehensive type definitions:

Import Types

import CommsSdk, {
  // Configuration Types
  CommsSdkConfig,
  ChannelConfig,
  ProviderConfig,

  // Request Types
  NotificationRequest,
  EmailRequest,
  SmsRequest,
  PushRequest,
  VoiceRequest,
  WebpushRequest,
  SlackRequest,
  WhatsappRequest,
  TelegramRequest,

  // Response Types
  NotificationStatus,
  SuccessNotificationStatus,
  ErrorNotificationStatus,
  ChannelStatus,

  // Error Types
  CommsError,
  ProviderError,
  ConfigurationError,
  ValidationError,
  NetworkError,

  // Provider Types
  EmailProvider,
  SmsProvider,
  PushProvider,

  // Strategy Types
  StrategyFunction,
  MultiProviderStrategyType,

  // Utility Functions
  isSuccessResponse,
  isErrorResponse,
  getErrors,
  isCommsError,
} from '@webventures/comms'

Type-Safe Configuration

const config: CommsSdkConfig = {
  channels: {
    email: {
      multiProviderStrategy: 'fallback',
      providers: [
        {
          type: 'sendgrid',
          apiKey: 'your-key',
        }, // TypeScript validates provider config
      ],
    },
  },
}

const comms = new CommsSdk(config)

Type-Safe Requests

const emailRequest: EmailRequest = {
  from: 'noreply@example.com',
  to: 'user@example.com',
  subject: 'Hello',
  html: '<h1>World</h1>',
  attachments: [
    {
      filename: 'doc.pdf',
      content: buffer,
      contentType: 'application/pdf',
    },
  ],
}

const request: NotificationRequest = {
  email: emailRequest,
  // TypeScript ensures correct structure
}

const result: NotificationStatus = await comms.send(request)
// TypeScript knows result.channels, result.status, result.errors

⚙️ Supported Providers

Email Providers (7)

Provider Type Features
SMTP smtp Any SMTP server, OAuth 2.0 support
SendGrid sendgrid API v3, templates, tracking
AWS SES ses High volume, cost-effective
Mailgun mailgun EU/US regions, validation API
Mandrill mandrill MailChimp integration, templates
SparkPost sparkpost Analytics, A/B testing
Sendmail sendmail Local sendmail binary

SMS Providers (9)

Provider Type Countries
Twilio twilio 180+ countries
Vonage (Nexmo) nexmo Global coverage
Plivo plivo 190+ countries
Infobip infobip Global, enterprise
OVH ovh Europe focus
Callr callr Europe, North America
Clickatell clickatell Global coverage
46elks 46elks Sweden focus
Seven seven Europe, APAC

Push Notification Providers (4)

Provider Type Platform
APNs apn iOS (Token & Certificate auth)
FCM fcm Android, iOS, Web
WNS wns Windows
ADM adm Amazon Fire devices

Other Providers

  • Voice: Twilio (TwiML support)
  • Webpush: Web Push with VAPID
  • Slack: Webhook with rich formatting
  • WhatsApp: Infobip Business API
  • Telegram: Telegram Bot API with HTML/Markdown formatting

See provider configuration guide →


🏗️ Architecture

WebVentures Comms SDK follows enterprise-grade design patterns:

  • Factory Pattern - Provider and strategy instantiation
  • Strategy Pattern - Multi-provider selection algorithms
  • Facade Pattern - Simplified API over complex provider logic
  • Registry Pattern - Provider instance management
  • Adapter Pattern - Framework-specific optimizations

See architecture documentation →


🚀 Performance & Best Practices

✅ Reuse SDK Instances

// ✓ Good - Reuse instance (connection pooling, caching)
const comms = new CommsSdk({
  /* config */
})

export async function sendEmail(to: string, subject: string) {
  return await comms.send({ email: { from: 'noreply@example.com', to, subject, text: '...' } })
}

// ✗ Bad - Creating new instance per call (expensive)
export async function sendEmail(to: string, subject: string) {
  const comms = new CommsSdk({
    /* config */
  }) // Don't do this!
  return await comms.send({
    /* ... */
  })
}

✅ Use Environment Variables

import { createNodeCommsFromEnv } from '@webventures/comms/adapters'

// Reads COMMS_EMAIL_PROVIDER, COMMS_SMS_PROVIDER, etc.
const comms = createNodeCommsFromEnv()

✅ Configure Logging

import winston from 'winston'

const comms = new CommsSdk({
  /* ... */
})

// Mute logs in production
if (process.env.NODE_ENV === 'production') {
  comms.logger.mute()
}

// Custom logging
comms.logger.configure([
  new winston.transports.File({ filename: 'notifications.log', level: 'error' }),
  new winston.transports.Console({ level: 'info' }),
])

✅ Handle Errors Gracefully

const result = await comms.send({
  /* ... */
})

if (result.status === 'error') {
  // Log for monitoring
  logger.error('Notification failed', { errors: result.errors })

  // Alert dev team for critical notifications
  if (isCritical) {
    await alertOps(result.errors)
  }

  // Retry or queue for later
  await retryQueue.add(notification, { attempts: 3 })
}

🤝 Contributing

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

Development Setup

# Clone repository
git clone https://github.com/CryptVenture/Comms.git
cd comms

# Install dependencies
pnpm install

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Type check
pnpm type-check

# Build
pnpm build

# Lint & format
pnpm lint:fix

Running Tests

# All tests
pnpm test

# Coverage report
pnpm test:coverage

# UI mode
pnpm test:ui

📊 Stats

  • 556 Tests - 100% passing
  • 40+ Providers - Production-ready integrations
  • 8 Channels - Email, SMS, Push, Voice, Webpush, Slack, WhatsApp, Telegram
  • TypeScript 100% - Full type safety
  • Node.js 18+ - Modern JavaScript features
  • Production Ready - Battle-tested error handling

📄 License

MIT License - see LICENSE file for details.


🆘 Support & Community


🔗 Related Projects


Built with ❤️ by the WebVentures team

WebsiteGitHubnpm

About

Unified communication SDK for TypeScript & JavaScript. Send emails, SMS, push notifications, and more with a single, type-safe API. First-class support for Next.js 16+, React 19, React Native, and Expo.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages