@skoolite/notify-hub 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/retry.ts","../src/utils/phone.ts","../src/providers/sms/twilio.provider.ts","../src/providers/sms/local/base.provider.ts","../src/providers/sms/local/telenor.provider.ts","../src/providers/sms/local/jazz.provider.ts","../src/providers/sms/local/zong.provider.ts","../src/providers/whatsapp/meta.provider.ts","../src/notify-hub.ts","../src/webhooks/twilio.handler.ts","../src/webhooks/whatsapp.handler.ts"],"names":["mapTwilioStatus","crypto2"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { RetryConfig, NotifyError } from '../types.js';\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxAttempts: 3,\n backoffMs: 1000,\n backoffMultiplier: 2,\n maxBackoffMs: 30000,\n jitter: true,\n};\n\n/**\n * Error codes that should be retried\n */\nconst RETRIABLE_ERROR_CODES = new Set([\n 'ETIMEDOUT',\n 'ECONNRESET',\n 'ECONNREFUSED',\n 'ENOTFOUND',\n 'EPIPE',\n 'RATE_LIMIT',\n 'SERVICE_UNAVAILABLE',\n 'GATEWAY_TIMEOUT',\n '429', // Too Many Requests\n '500', // Internal Server Error\n '502', // Bad Gateway\n '503', // Service Unavailable\n '504', // Gateway Timeout\n]);\n\n/**\n * Check if an error is retriable\n */\nexport function isRetriableError(error: unknown): boolean {\n if (!error) return false;\n\n // Check for NotifyError with retriable flag\n if (typeof error === 'object' && 'retriable' in error) {\n return (error as NotifyError).retriable;\n }\n\n // Check error code\n const errorCode = getErrorCode(error);\n if (errorCode && RETRIABLE_ERROR_CODES.has(errorCode)) {\n return true;\n }\n\n // Check status code\n const statusCode = getStatusCode(error);\n if (statusCode && RETRIABLE_ERROR_CODES.has(String(statusCode))) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Extract error code from various error types\n */\nfunction getErrorCode(error: unknown): string | undefined {\n if (typeof error === 'object' && error !== null) {\n const err = error as Record<string, unknown>;\n if (typeof err['code'] === 'string') {\n return err['code'];\n }\n if (typeof err['errorCode'] === 'string') {\n return err['errorCode'];\n }\n }\n return undefined;\n}\n\n/**\n * Extract status code from various error types\n */\nfunction getStatusCode(error: unknown): number | undefined {\n if (typeof error === 'object' && error !== null) {\n const err = error as Record<string, unknown>;\n if (typeof err['status'] === 'number') {\n return err['status'];\n }\n if (typeof err['statusCode'] === 'number') {\n return err['statusCode'];\n }\n // Axios-style error\n if (\n typeof err['response'] === 'object' &&\n err['response'] !== null &&\n typeof (err['response'] as Record<string, unknown>)['status'] === 'number'\n ) {\n return (err['response'] as Record<string, unknown>)['status'] as number;\n }\n }\n return undefined;\n}\n\n/**\n * Calculate backoff delay with optional jitter\n */\nexport function calculateBackoff(\n attempt: number,\n config: RetryConfig,\n): number {\n const exponentialDelay = config.backoffMs * Math.pow(config.backoffMultiplier, attempt - 1);\n const maxDelay = config.maxBackoffMs ?? 30000;\n const baseDelay = Math.min(exponentialDelay, maxDelay);\n\n if (config.jitter) {\n // Add jitter: random value between 0 and baseDelay\n const jitter = Math.random() * baseDelay * 0.5;\n return Math.floor(baseDelay + jitter);\n }\n\n return Math.floor(baseDelay);\n}\n\n/**\n * Sleep for a specified number of milliseconds\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Retry result containing the value or error\n */\nexport interface RetryResult<T> {\n success: boolean;\n value?: T;\n error?: Error;\n attempts: number;\n totalDurationMs: number;\n}\n\n/**\n * Execute a function with retries\n * @param fn Function to execute\n * @param config Retry configuration\n * @param shouldRetry Optional custom retry predicate\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n config: RetryConfig = DEFAULT_RETRY_CONFIG,\n shouldRetry: (error: unknown) => boolean = isRetriableError,\n): Promise<RetryResult<T>> {\n const startTime = Date.now();\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {\n try {\n const value = await fn();\n return {\n success: true,\n value,\n attempts: attempt,\n totalDurationMs: Date.now() - startTime,\n };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Check if we should retry\n const isLastAttempt = attempt >= config.maxAttempts;\n const canRetry = !isLastAttempt && shouldRetry(error);\n\n if (!canRetry) {\n return {\n success: false,\n error: lastError,\n attempts: attempt,\n totalDurationMs: Date.now() - startTime,\n };\n }\n\n // Calculate and wait for backoff\n const backoffMs = calculateBackoff(attempt, config);\n await sleep(backoffMs);\n }\n }\n\n return {\n success: false,\n error: lastError,\n attempts: config.maxAttempts,\n totalDurationMs: Date.now() - startTime,\n };\n}\n\n/**\n * Create a NotifyError from an unknown error\n */\nexport function createNotifyError(\n error: unknown,\n defaultCode = 'UNKNOWN_ERROR',\n): NotifyError {\n if (typeof error === 'object' && error !== null) {\n const err = error as Record<string, unknown>;\n return {\n code: (typeof err['code'] === 'string' ? err['code'] : defaultCode),\n message: err['message'] as string ?? String(error),\n retriable: isRetriableError(error),\n originalError: error,\n };\n }\n\n return {\n code: defaultCode,\n message: String(error),\n retriable: false,\n originalError: error,\n };\n}\n","import { parsePhoneNumber, isValidPhoneNumber, CountryCode } from 'libphonenumber-js';\n\n/**\n * Phone number validation result\n */\nexport interface PhoneValidationResult {\n isValid: boolean;\n e164?: string;\n countryCode?: string;\n nationalNumber?: string;\n error?: string;\n}\n\n/**\n * Validate and parse a phone number to E.164 format\n * @param phone Phone number in any format\n * @param defaultCountry Default country code for numbers without country prefix\n */\nexport function validatePhoneNumber(\n phone: string,\n defaultCountry: CountryCode = 'PK',\n): PhoneValidationResult {\n try {\n // Clean the phone number\n const cleaned = cleanPhoneNumber(phone);\n\n // Check if it's valid\n if (!isValidPhoneNumber(cleaned, defaultCountry)) {\n return {\n isValid: false,\n error: 'Invalid phone number format',\n };\n }\n\n // Parse the number\n const parsed = parsePhoneNumber(cleaned, defaultCountry);\n\n return {\n isValid: true,\n e164: parsed.format('E.164'),\n countryCode: parsed.country,\n nationalNumber: parsed.nationalNumber,\n };\n } catch (error) {\n return {\n isValid: false,\n error: error instanceof Error ? error.message : 'Failed to parse phone number',\n };\n }\n}\n\n/**\n * Clean a phone number by removing common formatting characters\n */\nexport function cleanPhoneNumber(phone: string): string {\n // Remove common formatting characters but keep + at the start\n let cleaned = phone.trim();\n\n // Preserve leading +\n const hasPlus = cleaned.startsWith('+');\n cleaned = cleaned.replace(/[\\s\\-().]/g, '');\n\n if (hasPlus && !cleaned.startsWith('+')) {\n cleaned = '+' + cleaned;\n }\n\n return cleaned;\n}\n\n/**\n * Format phone number to E.164 format\n * @param phone Phone number in any format\n * @param defaultCountry Default country code\n * @returns E.164 formatted number or null if invalid\n */\nexport function toE164(phone: string, defaultCountry: CountryCode = 'PK'): string | null {\n const result = validatePhoneNumber(phone, defaultCountry);\n return result.e164 ?? null;\n}\n\n/**\n * Check if a phone number belongs to a specific country\n * @param phone Phone number in E.164 format\n * @param countryCode Two-letter country code\n */\nexport function isCountry(phone: string, countryCode: CountryCode): boolean {\n try {\n const parsed = parsePhoneNumber(phone);\n return parsed.country === countryCode;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the country code from a phone number\n * @param phone Phone number in E.164 format\n */\nexport function getCountryCode(phone: string): string | null {\n try {\n const parsed = parsePhoneNumber(phone);\n return parsed.country ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the calling code (e.g., +92 for Pakistan)\n * @param phone Phone number in E.164 format\n */\nexport function getCallingCode(phone: string): string | null {\n try {\n const parsed = parsePhoneNumber(phone);\n return parsed.countryCallingCode ? `+${parsed.countryCallingCode}` : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a phone number is a Pakistan mobile number\n * Pakistan mobile numbers start with 03xx\n */\nexport function isPakistanMobile(phone: string): boolean {\n try {\n const parsed = parsePhoneNumber(phone, 'PK');\n if (parsed.country !== 'PK') return false;\n\n // Pakistan mobile numbers: national format starts with 3\n const national = parsed.nationalNumber;\n return national.startsWith('3');\n } catch {\n return false;\n }\n}\n\n/**\n * Get the Pakistan mobile network from a phone number\n * @param phone Phone number\n * @returns Network name or null if not a Pakistan mobile\n */\nexport function getPakistanNetwork(phone: string): 'jazz' | 'telenor' | 'zong' | 'ufone' | null {\n try {\n const parsed = parsePhoneNumber(phone, 'PK');\n if (parsed.country !== 'PK') return null;\n\n const national = parsed.nationalNumber;\n if (!national.startsWith('3')) return null;\n\n // Get the prefix (first 3 digits of national number)\n const prefix = national.substring(0, 3);\n\n // Network prefixes (not exhaustive, but covers common ranges)\n // Jazz/Warid: 30x, 31x, 32x, 33x\n if (['300', '301', '302', '303', '304', '305', '306', '307', '308', '309'].includes(prefix) ||\n ['310', '311', '312', '313', '314', '315', '316', '317', '318', '319'].includes(prefix) ||\n ['320', '321', '322', '323', '324', '325', '326', '327', '328', '329'].includes(prefix) ||\n ['330', '331', '332', '333', '334', '335', '336', '337', '338', '339'].includes(prefix)) {\n return 'jazz';\n }\n\n // Telenor: 34x, 35x\n if (['340', '341', '342', '343', '344', '345', '346', '347', '348', '349'].includes(prefix) ||\n ['350', '351', '352', '353', '354', '355', '356', '357', '358', '359'].includes(prefix)) {\n return 'telenor';\n }\n\n // Zong: 31x (some ranges)\n if (['310', '311', '312', '313', '314', '315', '316', '317', '318', '319'].includes(prefix)) {\n // Actually Jazz owns most 31x, but Zong has some specific ranges\n // This is simplified - real implementation would need more detailed prefix data\n return 'zong';\n }\n\n // Ufone: 33x (some ranges)\n if (['330', '331', '332', '333'].includes(prefix)) {\n return 'ufone';\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Determine the best provider for a phone number based on prefix\n * @param phone Phone number in E.164 format\n * @param routing Routing configuration\n * @returns 'primary' or 'fallback'\n */\nexport function routeByPrefix(\n phone: string,\n routing: Record<string, 'primary' | 'fallback'>,\n): 'primary' | 'fallback' {\n // Sort prefixes by length (longest first) for most specific match\n const prefixes = Object.keys(routing)\n .filter((k) => k !== '*')\n .sort((a, b) => b.length - a.length);\n\n for (const prefix of prefixes) {\n if (phone.startsWith(prefix)) {\n return routing[prefix]!;\n }\n }\n\n // Return default routing or fallback to primary\n return routing['*'] ?? 'primary';\n}\n","import type { Twilio as TwilioClient } from 'twilio';\nimport type {\n SmsProvider,\n SendResult,\n SmsOptions,\n SmsMessage,\n BulkResult,\n BulkOptions,\n MessageStatus,\n TwilioConfig,\n Logger,\n RetryConfig,\n} from '../../types.js';\nimport { withRetry, createNotifyError, DEFAULT_RETRY_CONFIG } from '../../utils/retry.js';\nimport { toE164 } from '../../utils/phone.js';\n\n/**\n * Map Twilio status to our MessageStatus\n */\nfunction mapTwilioStatus(twilioStatus: string): MessageStatus {\n const statusMap: Record<string, MessageStatus> = {\n queued: 'queued',\n sending: 'queued',\n sent: 'sent',\n delivered: 'delivered',\n undelivered: 'undelivered',\n failed: 'failed',\n read: 'read',\n accepted: 'queued',\n };\n return statusMap[twilioStatus] ?? 'unknown';\n}\n\n/**\n * Twilio SMS provider implementation\n */\nexport class TwilioSmsProvider implements SmsProvider {\n readonly name = 'twilio';\n\n private client: TwilioClient | null = null;\n private readonly config: TwilioConfig;\n private readonly logger?: Logger;\n private readonly retryConfig: RetryConfig;\n\n constructor(\n config: TwilioConfig,\n options?: { logger?: Logger; retryConfig?: RetryConfig },\n ) {\n this.config = config;\n this.logger = options?.logger;\n this.retryConfig = options?.retryConfig ?? DEFAULT_RETRY_CONFIG;\n }\n\n /**\n * Initialize the Twilio client\n */\n async initialize(): Promise<void> {\n if (this.client) return;\n\n // Dynamic import to avoid bundling issues\n const twilio = await import('twilio');\n this.client = twilio.default(this.config.accountSid, this.config.authToken);\n this.logger?.debug('TwilioSmsProvider initialized');\n }\n\n /**\n * Ensure client is initialized\n */\n private async ensureClient(): Promise<TwilioClient> {\n if (!this.client) {\n await this.initialize();\n }\n if (!this.client) {\n throw new Error('Twilio client not initialized');\n }\n return this.client;\n }\n\n /**\n * Send an SMS message\n */\n async send(to: string, message: string, options?: SmsOptions): Promise<SendResult> {\n const timestamp = new Date();\n const from = options?.from ?? this.config.fromNumber;\n\n // Validate and format phone number\n const e164To = toE164(to);\n if (!e164To) {\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: this.name,\n error: {\n code: 'INVALID_PHONE_NUMBER',\n message: `Invalid phone number: ${to}`,\n retriable: false,\n },\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n this.logger?.debug(`Sending SMS to ${e164To}`);\n\n const result = await withRetry(\n async () => {\n const client = await this.ensureClient();\n\n const messageParams: {\n to: string;\n body: string;\n from?: string;\n messagingServiceSid?: string;\n } = {\n to: e164To,\n body: message,\n };\n\n // Use messaging service SID if available, otherwise use from number\n if (this.config.messagingServiceSid) {\n messageParams.messagingServiceSid = this.config.messagingServiceSid;\n } else {\n messageParams.from = from;\n }\n\n return client.messages.create(messageParams);\n },\n this.retryConfig,\n );\n\n if (result.success && result.value) {\n const twilioMessage = result.value;\n this.logger?.info(`SMS sent successfully: ${twilioMessage.sid}`);\n\n return {\n success: true,\n messageId: twilioMessage.sid,\n channel: 'sms',\n status: mapTwilioStatus(twilioMessage.status),\n provider: this.name,\n cost: twilioMessage.price\n ? {\n amount: Math.abs(parseFloat(twilioMessage.price)),\n currency: twilioMessage.priceUnit ?? 'USD',\n }\n : undefined,\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n this.logger?.error(`SMS send failed: ${result.error?.message}`);\n\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: this.name,\n error: createNotifyError(result.error, 'TWILIO_ERROR'),\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n /**\n * Get delivery status of a message\n */\n async getStatus(messageId: string): Promise<MessageStatus> {\n try {\n const client = await this.ensureClient();\n const message = await client.messages(messageId).fetch();\n return mapTwilioStatus(message.status);\n } catch (error) {\n this.logger?.error(`Failed to get status for ${messageId}: ${error}`);\n return 'unknown';\n }\n }\n\n /**\n * Send bulk SMS messages\n */\n async sendBulk(messages: SmsMessage[], options?: BulkOptions): Promise<BulkResult> {\n const startTime = Date.now();\n const results: SendResult[] = [];\n let sent = 0;\n let failed = 0;\n let totalCost = 0;\n\n const concurrency = options?.concurrency ?? 10;\n const messagesPerSecond = options?.rateLimit?.messagesPerSecond ?? 10;\n const delayBetweenBatches = Math.ceil(1000 / messagesPerSecond) * concurrency;\n\n // Process in batches\n for (let i = 0; i < messages.length; i += concurrency) {\n const batch = messages.slice(i, i + concurrency);\n\n // Send batch concurrently\n const batchResults = await Promise.all(\n batch.map((msg) =>\n this.send(msg.to, msg.message, { metadata: msg.metadata }),\n ),\n );\n\n // Collect results\n for (const result of batchResults) {\n results.push(result);\n if (result.success) {\n sent++;\n if (result.cost) {\n totalCost += result.cost.amount;\n }\n } else {\n failed++;\n if (options?.stopOnError) {\n return {\n results,\n summary: {\n total: messages.length,\n sent,\n failed,\n cost: { amount: totalCost, currency: 'USD' },\n durationMs: Date.now() - startTime,\n },\n };\n }\n }\n }\n\n // Report progress\n options?.onProgress?.(sent + failed, messages.length);\n\n // Rate limiting delay between batches\n if (i + concurrency < messages.length) {\n await new Promise((resolve) => setTimeout(resolve, delayBetweenBatches));\n }\n }\n\n return {\n results,\n summary: {\n total: messages.length,\n sent,\n failed,\n cost: { amount: totalCost, currency: 'USD' },\n durationMs: Date.now() - startTime,\n },\n };\n }\n\n /**\n * Cleanup resources\n */\n async destroy(): Promise<void> {\n this.client = null;\n this.logger?.debug('TwilioSmsProvider destroyed');\n }\n}\n","import type {\n SmsProvider,\n SendResult,\n SmsOptions,\n SmsMessage,\n BulkResult,\n BulkOptions,\n MessageStatus,\n LocalSmsConfig,\n Logger,\n RetryConfig,\n} from '../../../types.js';\nimport { withRetry, createNotifyError, DEFAULT_RETRY_CONFIG } from '../../../utils/retry.js';\nimport { toE164 } from '../../../utils/phone.js';\n\n/**\n * Abstract base class for Pakistan local SMS providers\n * Each provider (Telenor, Jazz, Zong) extends this class\n */\nexport abstract class BaseLocalSmsProvider implements SmsProvider {\n abstract readonly name: string;\n\n protected readonly config: LocalSmsConfig;\n protected readonly logger?: Logger;\n protected readonly retryConfig: RetryConfig;\n protected abstract readonly baseUrl: string;\n\n constructor(\n config: LocalSmsConfig,\n options?: { logger?: Logger; retryConfig?: RetryConfig },\n ) {\n this.config = config;\n this.logger = options?.logger;\n this.retryConfig = options?.retryConfig ?? DEFAULT_RETRY_CONFIG;\n }\n\n /**\n * Initialize the provider\n */\n async initialize(): Promise<void> {\n if (!this.config.apiKey) {\n throw new Error(`${this.name}: apiKey is required`);\n }\n if (!this.config.senderId) {\n throw new Error(`${this.name}: senderId is required`);\n }\n this.logger?.debug(`${this.name} provider initialized`);\n }\n\n /**\n * Format phone number for local provider\n * Pakistan providers typically want: 923001234567 (no + prefix)\n */\n protected formatPhoneNumber(phone: string): string | null {\n const e164 = toE164(phone, 'PK');\n if (!e164) return null;\n\n // Remove + prefix for local providers\n return e164.replace('+', '');\n }\n\n /**\n * Make API request to the provider\n * Each provider implements this differently\n */\n protected abstract makeRequest(\n to: string,\n message: string,\n ): Promise<{ success: boolean; messageId?: string; error?: string }>;\n\n /**\n * Send an SMS message\n */\n async send(to: string, message: string, options?: SmsOptions): Promise<SendResult> {\n const timestamp = new Date();\n\n // Format phone number\n const formattedTo = this.formatPhoneNumber(to);\n if (!formattedTo) {\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: this.name,\n error: {\n code: 'INVALID_PHONE_NUMBER',\n message: `Invalid phone number: ${to}`,\n retriable: false,\n },\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n // Check if it's a Pakistan number\n if (!formattedTo.startsWith('92')) {\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: this.name,\n error: {\n code: 'UNSUPPORTED_DESTINATION',\n message: 'Local SMS providers only support Pakistan numbers',\n retriable: false,\n },\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n this.logger?.debug(`Sending SMS via ${this.name} to ${formattedTo}`);\n\n const result = await withRetry(\n async () => this.makeRequest(formattedTo, message),\n this.retryConfig,\n );\n\n if (result.success && result.value?.success) {\n this.logger?.info(`SMS sent via ${this.name}: ${result.value.messageId}`);\n\n return {\n success: true,\n messageId: result.value.messageId,\n channel: 'sms',\n status: 'sent',\n provider: this.name,\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n this.logger?.error(`SMS send via ${this.name} failed: ${result.error?.message ?? result.value?.error}`);\n\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: this.name,\n error: createNotifyError(result.error ?? new Error(result.value?.error ?? 'Unknown error'), `${this.name.toUpperCase()}_ERROR`),\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n /**\n * Get delivery status (most local providers don't support this)\n */\n async getStatus(_messageId: string): Promise<MessageStatus> {\n this.logger?.warn(`${this.name} does not support status queries`);\n return 'unknown';\n }\n\n /**\n * Send bulk SMS messages\n */\n async sendBulk(messages: SmsMessage[], options?: BulkOptions): Promise<BulkResult> {\n const startTime = Date.now();\n const results: SendResult[] = [];\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n const result = await this.send(msg.to, msg.message, { metadata: msg.metadata });\n results.push(result);\n\n if (result.success) {\n sent++;\n } else {\n failed++;\n if (options?.stopOnError) {\n break;\n }\n }\n\n options?.onProgress?.(i + 1, messages.length);\n\n // Rate limiting\n if (options?.rateLimit?.messagesPerSecond && i < messages.length - 1) {\n const delay = 1000 / options.rateLimit.messagesPerSecond;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n return {\n results,\n summary: {\n total: messages.length,\n sent,\n failed,\n durationMs: Date.now() - startTime,\n },\n };\n }\n\n /**\n * Cleanup resources\n */\n async destroy(): Promise<void> {\n this.logger?.debug(`${this.name} provider destroyed`);\n }\n}\n","import type { LocalSmsConfig, Logger, RetryConfig } from '../../../types.js';\nimport { BaseLocalSmsProvider } from './base.provider.js';\n\n/**\n * Telenor Pakistan SMS API response\n */\ninterface TelenorApiResponse {\n response?: {\n status?: string;\n message_id?: string;\n error?: string;\n };\n error?: string;\n}\n\n/**\n * Telenor Pakistan SMS provider\n *\n * API Documentation: Contact Telenor Pakistan for API access\n *\n * Note: This is a simplified implementation. Actual Telenor API\n * may have different endpoints and authentication methods.\n */\nexport class TelenorSmsProvider extends BaseLocalSmsProvider {\n readonly name = 'telenor';\n protected readonly baseUrl: string;\n\n constructor(\n config: LocalSmsConfig,\n options?: { logger?: Logger; retryConfig?: RetryConfig },\n ) {\n super(config, options);\n // Default Telenor SMS API URL (placeholder - get actual URL from Telenor)\n this.baseUrl = config.baseUrl ?? 'https://api.telenor.com.pk/sms/v2/send';\n }\n\n /**\n * Make API request to Telenor\n */\n protected async makeRequest(\n to: string,\n message: string,\n ): Promise<{ success: boolean; messageId?: string; error?: string }> {\n try {\n const response = await fetch(this.baseUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n to,\n message,\n sender_id: this.config.senderId,\n ...(this.config.apiSecret && { api_secret: this.config.apiSecret }),\n }),\n });\n\n const data = await response.json() as TelenorApiResponse;\n\n if (!response.ok || data.error) {\n return {\n success: false,\n error: data.error ?? data.response?.error ?? `HTTP ${response.status}`,\n };\n }\n\n return {\n success: true,\n messageId: data.response?.message_id ?? `tel-${Date.now()}`,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","import type { LocalSmsConfig, Logger, RetryConfig } from '../../../types.js';\nimport { BaseLocalSmsProvider } from './base.provider.js';\n\n/**\n * Jazz (Mobilink) Pakistan SMS API response\n */\ninterface JazzApiResponse {\n status?: string;\n messageId?: string;\n errorCode?: string;\n errorMessage?: string;\n}\n\n/**\n * Jazz (Mobilink) Pakistan SMS provider\n *\n * API Documentation: Contact Jazz Pakistan for API access\n *\n * Note: This is a simplified implementation. Actual Jazz API\n * may have different endpoints and authentication methods.\n */\nexport class JazzSmsProvider extends BaseLocalSmsProvider {\n readonly name = 'jazz';\n protected readonly baseUrl: string;\n\n constructor(\n config: LocalSmsConfig,\n options?: { logger?: Logger; retryConfig?: RetryConfig },\n ) {\n super(config, options);\n // Default Jazz SMS API URL (placeholder - get actual URL from Jazz)\n this.baseUrl = config.baseUrl ?? 'https://api.jazz.com.pk/sms/v1/send';\n }\n\n /**\n * Make API request to Jazz\n */\n protected async makeRequest(\n to: string,\n message: string,\n ): Promise<{ success: boolean; messageId?: string; error?: string }> {\n try {\n // Jazz often uses URL-encoded form data\n const params = new URLSearchParams({\n username: this.config.apiKey,\n ...(this.config.apiSecret && { password: this.config.apiSecret }),\n to,\n text: message,\n from: this.config.senderId,\n });\n\n const response = await fetch(this.baseUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: params.toString(),\n });\n\n const data = await response.json() as JazzApiResponse;\n\n if (!response.ok || data.errorCode) {\n return {\n success: false,\n error: data.errorMessage ?? data.errorCode ?? `HTTP ${response.status}`,\n };\n }\n\n return {\n success: true,\n messageId: data.messageId ?? `jazz-${Date.now()}`,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","import type { LocalSmsConfig, Logger, RetryConfig } from '../../../types.js';\nimport { BaseLocalSmsProvider } from './base.provider.js';\n\n/**\n * Zong Pakistan SMS API response\n */\ninterface ZongApiResponse {\n responseCode?: string;\n responseMessage?: string;\n messageId?: string;\n}\n\n/**\n * Zong Pakistan SMS provider\n *\n * API Documentation: Contact Zong Pakistan for API access\n *\n * Note: This is a simplified implementation. Actual Zong API\n * may have different endpoints and authentication methods.\n */\nexport class ZongSmsProvider extends BaseLocalSmsProvider {\n readonly name = 'zong';\n protected readonly baseUrl: string;\n\n constructor(\n config: LocalSmsConfig,\n options?: { logger?: Logger; retryConfig?: RetryConfig },\n ) {\n super(config, options);\n // Default Zong SMS API URL (placeholder - get actual URL from Zong)\n this.baseUrl = config.baseUrl ?? 'https://api.zong.com.pk/sms/send';\n }\n\n /**\n * Make API request to Zong\n */\n protected async makeRequest(\n to: string,\n message: string,\n ): Promise<{ success: boolean; messageId?: string; error?: string }> {\n try {\n const response = await fetch(this.baseUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.config.apiKey,\n },\n body: JSON.stringify({\n recipient: to,\n message,\n senderId: this.config.senderId,\n ...(this.config.apiSecret && { apiSecret: this.config.apiSecret }),\n }),\n });\n\n const data = await response.json() as ZongApiResponse;\n\n // Zong typically uses '00' or '0' for success\n if (!response.ok || (data.responseCode && data.responseCode !== '00' && data.responseCode !== '0')) {\n return {\n success: false,\n error: data.responseMessage ?? `Error code: ${data.responseCode}`,\n };\n }\n\n return {\n success: true,\n messageId: data.messageId ?? `zong-${Date.now()}`,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","import type {\n WhatsAppProvider,\n SendResult,\n WhatsAppTemplate,\n WhatsAppOptions,\n MessageStatus,\n MetaWhatsAppConfig,\n Logger,\n RetryConfig,\n} from '../../types.js';\nimport { withRetry, createNotifyError, DEFAULT_RETRY_CONFIG } from '../../utils/retry.js';\nimport { toE164 } from '../../utils/phone.js';\n\n/**\n * Meta WhatsApp Cloud API response types\n */\ninterface MetaApiResponse {\n messaging_product: 'whatsapp';\n contacts: Array<{ input: string; wa_id: string }>;\n messages: Array<{ id: string }>;\n}\n\ninterface MetaApiError {\n error: {\n message: string;\n type: string;\n code: number;\n error_subcode?: number;\n fbtrace_id: string;\n };\n}\n\n/**\n * Map Meta status to our MessageStatus\n * Used by webhook handler, exported for use there\n */\nexport function mapMetaStatus(status: string): MessageStatus {\n const statusMap: Record<string, MessageStatus> = {\n sent: 'sent',\n delivered: 'delivered',\n read: 'read',\n failed: 'failed',\n };\n return statusMap[status] ?? 'unknown';\n}\n\n/**\n * Meta WhatsApp Cloud API provider implementation\n * @see https://developers.facebook.com/docs/whatsapp/cloud-api\n */\nexport class MetaWhatsAppProvider implements WhatsAppProvider {\n readonly name = 'meta';\n\n private readonly config: MetaWhatsAppConfig;\n private readonly logger?: Logger;\n private readonly retryConfig: RetryConfig;\n private readonly apiVersion: string;\n private readonly baseUrl: string;\n\n constructor(\n config: MetaWhatsAppConfig,\n options?: { logger?: Logger; retryConfig?: RetryConfig },\n ) {\n this.config = config;\n this.logger = options?.logger;\n this.retryConfig = options?.retryConfig ?? DEFAULT_RETRY_CONFIG;\n this.apiVersion = config.apiVersion ?? 'v18.0';\n this.baseUrl = `https://graph.facebook.com/${this.apiVersion}/${config.phoneNumberId}/messages`;\n }\n\n /**\n * Initialize the provider (no-op for Meta, just validates config)\n */\n async initialize(): Promise<void> {\n if (!this.config.accessToken) {\n throw new Error('Meta WhatsApp: accessToken is required');\n }\n if (!this.config.phoneNumberId) {\n throw new Error('Meta WhatsApp: phoneNumberId is required');\n }\n this.logger?.debug('MetaWhatsAppProvider initialized');\n }\n\n /**\n * Make an API request to Meta WhatsApp Cloud API\n */\n private async makeRequest(body: unknown): Promise<MetaApiResponse> {\n const response = await fetch(this.baseUrl, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.config.accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n });\n\n const data = await response.json() as MetaApiResponse | MetaApiError;\n\n if (!response.ok || 'error' in data) {\n const error = (data as MetaApiError).error;\n const err = new Error(error?.message ?? 'Unknown Meta API error') as Error & { code: string; statusCode: number };\n err.code = String(error?.code ?? 'UNKNOWN');\n err.statusCode = response.status;\n throw err;\n }\n\n return data as MetaApiResponse;\n }\n\n /**\n * Send a text message (within 24hr conversation window)\n */\n async sendText(to: string, message: string, options?: WhatsAppOptions): Promise<SendResult> {\n const timestamp = new Date();\n\n // Validate and format phone number (remove + for WhatsApp)\n const e164 = toE164(to);\n if (!e164) {\n return {\n success: false,\n channel: 'whatsapp',\n status: 'failed',\n provider: this.name,\n error: {\n code: 'INVALID_PHONE_NUMBER',\n message: `Invalid phone number: ${to}`,\n retriable: false,\n },\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n // WhatsApp uses number without + prefix\n const whatsappNumber = e164.replace('+', '');\n\n this.logger?.debug(`Sending WhatsApp text to ${whatsappNumber}`);\n\n const result = await withRetry(\n async () => {\n return this.makeRequest({\n messaging_product: 'whatsapp',\n recipient_type: 'individual',\n to: whatsappNumber,\n type: 'text',\n text: {\n preview_url: false,\n body: message,\n },\n });\n },\n this.retryConfig,\n );\n\n if (result.success && result.value) {\n const messageId = result.value.messages[0]?.id;\n this.logger?.info(`WhatsApp text sent successfully: ${messageId}`);\n\n return {\n success: true,\n messageId,\n channel: 'whatsapp',\n status: 'sent',\n provider: this.name,\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n this.logger?.error(`WhatsApp text send failed: ${result.error?.message}`);\n\n return {\n success: false,\n channel: 'whatsapp',\n status: 'failed',\n provider: this.name,\n error: createNotifyError(result.error, 'META_API_ERROR'),\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n /**\n * Send a template message (works outside 24hr window)\n */\n async sendTemplate(\n to: string,\n template: WhatsAppTemplate,\n options?: WhatsAppOptions,\n ): Promise<SendResult> {\n const timestamp = new Date();\n\n // Validate and format phone number\n const e164 = toE164(to);\n if (!e164) {\n return {\n success: false,\n channel: 'whatsapp',\n status: 'failed',\n provider: this.name,\n error: {\n code: 'INVALID_PHONE_NUMBER',\n message: `Invalid phone number: ${to}`,\n retriable: false,\n },\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n const whatsappNumber = e164.replace('+', '');\n\n this.logger?.debug(`Sending WhatsApp template \"${template.name}\" to ${whatsappNumber}`);\n\n // Build template components\n const components: Array<{\n type: string;\n parameters?: Array<{ type: string; text?: string; image?: { link: string }; document?: { link: string }; video?: { link: string } }>;\n sub_type?: string;\n index?: number;\n }> = [];\n\n // Add header component if present\n if (template.header) {\n const headerComponent: typeof components[0] = {\n type: 'header',\n parameters: [],\n };\n\n if (template.header.type === 'text' && template.header.text) {\n headerComponent.parameters = [{ type: 'text', text: template.header.text }];\n } else if (template.header.type === 'image' && template.header.url) {\n headerComponent.parameters = [{ type: 'image', image: { link: template.header.url } }];\n } else if (template.header.type === 'document' && template.header.url) {\n headerComponent.parameters = [{ type: 'document', document: { link: template.header.url } }];\n } else if (template.header.type === 'video' && template.header.url) {\n headerComponent.parameters = [{ type: 'video', video: { link: template.header.url } }];\n }\n\n if (headerComponent.parameters && headerComponent.parameters.length > 0) {\n components.push(headerComponent);\n }\n }\n\n // Add body component with variables\n if (template.variables) {\n const variables = Array.isArray(template.variables)\n ? template.variables\n : Object.values(template.variables);\n\n if (variables.length > 0) {\n components.push({\n type: 'body',\n parameters: variables.map((text) => ({\n type: 'text',\n text: String(text),\n })),\n });\n }\n }\n\n // Add button components if present\n if (template.buttons && template.buttons.length > 0) {\n for (const button of template.buttons) {\n if (button.payload) {\n components.push({\n type: 'button',\n sub_type: button.type === 'url' ? 'url' : 'quick_reply',\n index: button.index,\n parameters: [{ type: 'text', text: button.payload }],\n });\n }\n }\n }\n\n const result = await withRetry(\n async () => {\n return this.makeRequest({\n messaging_product: 'whatsapp',\n recipient_type: 'individual',\n to: whatsappNumber,\n type: 'template',\n template: {\n name: template.name,\n language: {\n code: template.language,\n },\n components: components.length > 0 ? components : undefined,\n },\n });\n },\n this.retryConfig,\n );\n\n if (result.success && result.value) {\n const messageId = result.value.messages[0]?.id;\n this.logger?.info(`WhatsApp template sent successfully: ${messageId}`);\n\n return {\n success: true,\n messageId,\n channel: 'whatsapp',\n status: 'sent',\n provider: this.name,\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n this.logger?.error(`WhatsApp template send failed: ${result.error?.message}`);\n\n return {\n success: false,\n channel: 'whatsapp',\n status: 'failed',\n provider: this.name,\n error: createNotifyError(result.error, 'META_API_ERROR'),\n timestamp,\n metadata: options?.metadata,\n };\n }\n\n /**\n * Get delivery status of a message\n * Note: Meta doesn't have a direct status lookup API - statuses come via webhooks\n */\n async getStatus(_messageId: string): Promise<MessageStatus> {\n // Meta WhatsApp doesn't have a direct status query API\n // Statuses are received via webhooks\n this.logger?.warn('Meta WhatsApp does not support direct status queries. Use webhooks instead.');\n return 'unknown';\n }\n\n /**\n * Cleanup resources (no-op for Meta)\n */\n async destroy(): Promise<void> {\n this.logger?.debug('MetaWhatsAppProvider destroyed');\n }\n}\n","import type {\n NotifyHubConfig,\n SendResult,\n BulkResult,\n BulkOptions,\n SmsProvider,\n WhatsAppProvider,\n EmailProvider,\n SmsOptions,\n SmsMessage,\n WhatsAppTemplate,\n WhatsAppOptions,\n WhatsAppMessage,\n EmailMessage,\n EmailOptions,\n EmailMessageWithRecipient,\n Notification,\n Logger,\n RetryConfig,\n MessageStatus,\n} from './types.js';\nimport { TwilioSmsProvider } from './providers/sms/twilio.provider.js';\nimport { TelenorSmsProvider, JazzSmsProvider, ZongSmsProvider } from './providers/sms/local/index.js';\nimport { MetaWhatsAppProvider } from './providers/whatsapp/meta.provider.js';\nimport { routeByPrefix, toE164 } from './utils/phone.js';\nimport { DEFAULT_RETRY_CONFIG } from './utils/retry.js';\n\n/**\n * Console logger with noop for production\n */\nconst noopLogger: Logger = {\n debug: () => undefined,\n info: () => undefined,\n warn: () => undefined,\n error: () => undefined,\n};\n\n/**\n * NotifyHub - Multi-channel notification hub\n *\n * @example\n * ```typescript\n * const notifyHub = new NotifyHub({\n * sms: {\n * primary: {\n * provider: 'twilio',\n * config: {\n * accountSid: 'xxx',\n * authToken: 'xxx',\n * fromNumber: '+1234567890',\n * },\n * },\n * },\n * });\n *\n * await notifyHub.sms('+923001234567', 'Hello!');\n * ```\n */\nexport class NotifyHub {\n private readonly config: NotifyHubConfig;\n private readonly logger: Logger;\n private readonly retryConfig: RetryConfig;\n\n // Providers\n private primarySmsProvider?: SmsProvider;\n private fallbackSmsProvider?: SmsProvider;\n private whatsappProvider?: WhatsAppProvider;\n private emailProvider?: EmailProvider;\n\n // Initialization state\n private initialized = false;\n\n constructor(config: NotifyHubConfig) {\n this.config = config;\n this.logger = config.logger ?? noopLogger;\n this.retryConfig = config.retry ?? DEFAULT_RETRY_CONFIG;\n }\n\n /**\n * Initialize all configured providers\n */\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n this.logger.debug('Initializing NotifyHub');\n\n // Initialize SMS providers\n if (this.config.sms) {\n this.primarySmsProvider = await this.createSmsProvider(\n this.config.sms.primary,\n );\n if (this.config.sms.fallback) {\n this.fallbackSmsProvider = await this.createSmsProvider(\n this.config.sms.fallback,\n );\n }\n }\n\n // Initialize WhatsApp provider\n if (this.config.whatsapp) {\n this.whatsappProvider = await this.createWhatsAppProvider(\n this.config.whatsapp,\n );\n }\n\n // Initialize Email provider\n if (this.config.email) {\n this.emailProvider = await this.createEmailProvider(this.config.email);\n }\n\n this.initialized = true;\n this.logger.info('NotifyHub initialized');\n }\n\n /**\n * Create an SMS provider from configuration\n */\n private async createSmsProvider(\n config: { provider: string; config?: unknown; instance?: SmsProvider },\n ): Promise<SmsProvider> {\n if (config.provider === 'custom' && config.instance) {\n return config.instance;\n }\n\n if (config.provider === 'twilio') {\n const twilioConfig = config.config as {\n accountSid: string;\n authToken: string;\n fromNumber: string;\n messagingServiceSid?: string;\n };\n const provider = new TwilioSmsProvider(twilioConfig, {\n logger: this.logger,\n retryConfig: this.retryConfig,\n });\n await provider.initialize();\n return provider;\n }\n\n if (config.provider === 'local') {\n const localConfig = config.config as {\n provider: 'telenor' | 'jazz' | 'zong';\n apiKey: string;\n apiSecret?: string;\n senderId: string;\n baseUrl?: string;\n };\n\n let provider;\n switch (localConfig.provider) {\n case 'telenor':\n provider = new TelenorSmsProvider(localConfig, {\n logger: this.logger,\n retryConfig: this.retryConfig,\n });\n break;\n case 'jazz':\n provider = new JazzSmsProvider(localConfig, {\n logger: this.logger,\n retryConfig: this.retryConfig,\n });\n break;\n case 'zong':\n provider = new ZongSmsProvider(localConfig, {\n logger: this.logger,\n retryConfig: this.retryConfig,\n });\n break;\n default:\n throw new Error(`Unknown local SMS provider: ${localConfig.provider}`);\n }\n\n await provider.initialize();\n return provider;\n }\n\n throw new Error(`Unknown SMS provider: ${config.provider}`);\n }\n\n /**\n * Create a WhatsApp provider from configuration\n */\n private async createWhatsAppProvider(\n config: { provider: string; config?: unknown; instance?: WhatsAppProvider },\n ): Promise<WhatsAppProvider> {\n if (config.provider === 'custom' && config.instance) {\n return config.instance;\n }\n\n if (config.provider === 'meta') {\n const metaConfig = config.config as {\n accessToken: string;\n phoneNumberId: string;\n businessAccountId?: string;\n apiVersion?: string;\n webhookVerifyToken?: string;\n };\n const provider = new MetaWhatsAppProvider(metaConfig, {\n logger: this.logger,\n retryConfig: this.retryConfig,\n });\n await provider.initialize();\n return provider;\n }\n\n throw new Error(`Unknown WhatsApp provider: ${config.provider}`);\n }\n\n /**\n * Create an Email provider from configuration\n */\n private async createEmailProvider(\n config: { provider: string; config?: unknown; instance?: EmailProvider },\n ): Promise<EmailProvider> {\n if (config.provider === 'custom' && config.instance) {\n return config.instance;\n }\n\n if (config.provider === 'ses') {\n // SES provider will be implemented in Sprint 3\n throw new Error('SES email provider not yet implemented');\n }\n\n throw new Error(`Unknown email provider: ${config.provider}`);\n }\n\n /**\n * Ensure NotifyHub is initialized\n */\n private async ensureInitialized(): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n }\n\n /**\n * Get the appropriate SMS provider based on phone number\n */\n private getSmsProvider(to: string): SmsProvider {\n if (!this.primarySmsProvider) {\n throw new Error('SMS provider not configured');\n }\n\n // If no routing or no fallback, use primary\n if (!this.config.sms?.routing || !this.fallbackSmsProvider) {\n return this.primarySmsProvider;\n }\n\n // Validate and format phone number\n const e164 = toE164(to);\n if (!e164) {\n return this.primarySmsProvider;\n }\n\n // Route based on prefix\n const route = routeByPrefix(e164, this.config.sms.routing);\n return route === 'fallback' && this.fallbackSmsProvider\n ? this.fallbackSmsProvider\n : this.primarySmsProvider;\n }\n\n // ==================== SMS METHODS ====================\n\n /**\n * Send an SMS message\n * @param to Phone number in any format (will be converted to E.164)\n * @param message Message content\n * @param options Additional options\n */\n async sms(to: string, message: string, options?: SmsOptions): Promise<SendResult> {\n await this.ensureInitialized();\n\n const provider = this.getSmsProvider(to);\n this.logger.debug(`Sending SMS via ${provider.name} to ${to}`);\n\n try {\n const result = await provider.send(to, message, options);\n\n // If failed and we have a fallback, try it\n if (\n !result.success &&\n result.error?.retriable &&\n this.fallbackSmsProvider &&\n provider !== this.fallbackSmsProvider\n ) {\n this.logger.warn(\n `Primary SMS provider failed, trying fallback: ${result.error.message}`,\n );\n return this.fallbackSmsProvider.send(to, message, options);\n }\n\n return result;\n } catch (error) {\n this.logger.error(`SMS send error: ${error}`);\n\n // Try fallback on exception\n if (\n this.fallbackSmsProvider &&\n provider !== this.fallbackSmsProvider\n ) {\n this.logger.warn('Primary SMS provider threw, trying fallback');\n return this.fallbackSmsProvider.send(to, message, options);\n }\n\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: provider.name,\n error: {\n code: 'SEND_ERROR',\n message: error instanceof Error ? error.message : String(error),\n retriable: false,\n },\n timestamp: new Date(),\n metadata: options?.metadata,\n };\n }\n }\n\n /**\n * Send bulk SMS messages\n */\n async bulkSms(messages: SmsMessage[], options?: BulkOptions): Promise<BulkResult> {\n await this.ensureInitialized();\n\n if (!this.primarySmsProvider) {\n throw new Error('SMS provider not configured');\n }\n\n // If provider supports native bulk, use it\n if (this.primarySmsProvider.sendBulk) {\n return this.primarySmsProvider.sendBulk(messages, options);\n }\n\n // Otherwise, implement our own bulk logic\n const startTime = Date.now();\n const results: SendResult[] = [];\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n const result = await this.sms(msg.to, msg.message, { metadata: msg.metadata });\n results.push(result);\n\n if (result.success) {\n sent++;\n } else {\n failed++;\n if (options?.stopOnError) {\n break;\n }\n }\n\n options?.onProgress?.(i + 1, messages.length);\n\n // Rate limiting\n if (options?.rateLimit?.messagesPerSecond && i < messages.length - 1) {\n const delay = 1000 / options.rateLimit.messagesPerSecond;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n return {\n results,\n summary: {\n total: messages.length,\n sent,\n failed,\n durationMs: Date.now() - startTime,\n },\n };\n }\n\n /**\n * Get SMS delivery status\n */\n async getSmsStatus(messageId: string): Promise<MessageStatus> {\n await this.ensureInitialized();\n\n if (!this.primarySmsProvider?.getStatus) {\n throw new Error('SMS provider does not support status checks');\n }\n\n return this.primarySmsProvider.getStatus(messageId);\n }\n\n // ==================== WHATSAPP METHODS ====================\n\n /**\n * Send a WhatsApp text message (within 24hr window)\n */\n async whatsapp(to: string, message: string, options?: WhatsAppOptions): Promise<SendResult> {\n await this.ensureInitialized();\n\n if (!this.whatsappProvider) {\n throw new Error('WhatsApp provider not configured');\n }\n\n return this.whatsappProvider.sendText(to, message, options);\n }\n\n /**\n * Send a WhatsApp template message\n */\n async whatsappTemplate(\n to: string,\n template: WhatsAppTemplate,\n options?: WhatsAppOptions,\n ): Promise<SendResult> {\n await this.ensureInitialized();\n\n if (!this.whatsappProvider) {\n throw new Error('WhatsApp provider not configured');\n }\n\n return this.whatsappProvider.sendTemplate(to, template, options);\n }\n\n /**\n * Send bulk WhatsApp messages\n */\n async bulkWhatsApp(messages: WhatsAppMessage[], options?: BulkOptions): Promise<BulkResult> {\n await this.ensureInitialized();\n\n if (!this.whatsappProvider) {\n throw new Error('WhatsApp provider not configured');\n }\n\n const startTime = Date.now();\n const results: SendResult[] = [];\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n let result: SendResult;\n\n if (msg.template) {\n result = await this.whatsappTemplate(msg.to, msg.template, {\n metadata: msg.metadata,\n });\n } else if (msg.message) {\n result = await this.whatsapp(msg.to, msg.message, { metadata: msg.metadata });\n } else {\n result = {\n success: false,\n channel: 'whatsapp',\n status: 'failed',\n provider: this.whatsappProvider.name,\n error: {\n code: 'INVALID_MESSAGE',\n message: 'Message must have either message or template',\n retriable: false,\n },\n timestamp: new Date(),\n };\n }\n\n results.push(result);\n if (result.success) {\n sent++;\n } else {\n failed++;\n if (options?.stopOnError) {\n break;\n }\n }\n\n options?.onProgress?.(i + 1, messages.length);\n\n // Rate limiting (WhatsApp has strict limits)\n if (options?.rateLimit?.messagesPerSecond && i < messages.length - 1) {\n const delay = 1000 / options.rateLimit.messagesPerSecond;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n return {\n results,\n summary: {\n total: messages.length,\n sent,\n failed,\n durationMs: Date.now() - startTime,\n },\n };\n }\n\n // ==================== EMAIL METHODS ====================\n\n /**\n * Send an email\n */\n async email(to: string, email: EmailMessage, options?: EmailOptions): Promise<SendResult> {\n await this.ensureInitialized();\n\n if (!this.emailProvider) {\n throw new Error('Email provider not configured');\n }\n\n return this.emailProvider.send(to, email, options);\n }\n\n /**\n * Send bulk emails\n */\n async bulkEmail(\n messages: EmailMessageWithRecipient[],\n options?: BulkOptions,\n ): Promise<BulkResult> {\n await this.ensureInitialized();\n\n if (!this.emailProvider) {\n throw new Error('Email provider not configured');\n }\n\n // If provider supports native bulk, use it\n if (this.emailProvider.sendBulk) {\n return this.emailProvider.sendBulk(messages, options);\n }\n\n const startTime = Date.now();\n const results: SendResult[] = [];\n let sent = 0;\n let failed = 0;\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n const result = await this.email(msg.to, msg, { metadata: msg.metadata });\n results.push(result);\n\n if (result.success) {\n sent++;\n } else {\n failed++;\n if (options?.stopOnError) {\n break;\n }\n }\n\n options?.onProgress?.(i + 1, messages.length);\n }\n\n return {\n results,\n summary: {\n total: messages.length,\n sent,\n failed,\n durationMs: Date.now() - startTime,\n },\n };\n }\n\n // ==================== GENERIC SEND ====================\n\n /**\n * Send a notification using the specified channel\n */\n async send(notification: Notification): Promise<SendResult> {\n switch (notification.channel) {\n case 'sms':\n if (!notification.message) {\n return {\n success: false,\n channel: 'sms',\n status: 'failed',\n provider: 'unknown',\n error: {\n code: 'INVALID_NOTIFICATION',\n message: 'SMS notification requires message',\n retriable: false,\n },\n timestamp: new Date(),\n };\n }\n return this.sms(notification.to, notification.message, {\n metadata: notification.metadata,\n });\n\n case 'whatsapp':\n if (notification.template) {\n return this.whatsappTemplate(notification.to, notification.template, {\n metadata: notification.metadata,\n });\n }\n if (notification.message) {\n return this.whatsapp(notification.to, notification.message, {\n metadata: notification.metadata,\n });\n }\n return {\n success: false,\n channel: 'whatsapp',\n status: 'failed',\n provider: 'unknown',\n error: {\n code: 'INVALID_NOTIFICATION',\n message: 'WhatsApp notification requires message or template',\n retriable: false,\n },\n timestamp: new Date(),\n };\n\n case 'email':\n if (!notification.email) {\n return {\n success: false,\n channel: 'email',\n status: 'failed',\n provider: 'unknown',\n error: {\n code: 'INVALID_NOTIFICATION',\n message: 'Email notification requires email object',\n retriable: false,\n },\n timestamp: new Date(),\n };\n }\n return this.email(notification.to, notification.email, {\n metadata: notification.metadata,\n });\n\n default:\n return {\n success: false,\n channel: notification.channel,\n status: 'failed',\n provider: 'unknown',\n error: {\n code: 'INVALID_CHANNEL',\n message: `Unknown channel: ${notification.channel}`,\n retriable: false,\n },\n timestamp: new Date(),\n };\n }\n }\n\n // ==================== LIFECYCLE ====================\n\n /**\n * Cleanup and destroy all providers\n */\n async destroy(): Promise<void> {\n this.logger.debug('Destroying NotifyHub');\n\n await Promise.all([\n this.primarySmsProvider?.destroy?.(),\n this.fallbackSmsProvider?.destroy?.(),\n this.whatsappProvider?.destroy?.(),\n this.emailProvider?.destroy?.(),\n ]);\n\n this.primarySmsProvider = undefined;\n this.fallbackSmsProvider = undefined;\n this.whatsappProvider = undefined;\n this.emailProvider = undefined;\n this.initialized = false;\n\n this.logger.info('NotifyHub destroyed');\n }\n}\n","import * as crypto from 'crypto';\nimport type {\n WebhookHandler,\n StatusWebhookEvent,\n IncomingMessageEvent,\n MessageStatus,\n WebhookEvent,\n} from '../types.js';\n\n/**\n * Twilio webhook payload for message status updates\n */\ninterface TwilioStatusPayload {\n MessageSid: string;\n MessageStatus: string;\n To: string;\n From?: string;\n ErrorCode?: string;\n ErrorMessage?: string;\n AccountSid?: string;\n ApiVersion?: string;\n}\n\n/**\n * Twilio webhook payload for incoming messages\n */\ninterface TwilioIncomingPayload {\n MessageSid: string;\n Body: string;\n From: string;\n To: string;\n NumMedia?: string;\n MediaUrl0?: string;\n MediaContentType0?: string;\n AccountSid?: string;\n}\n\n/**\n * Map Twilio status to our MessageStatus\n */\nfunction mapTwilioStatus(status: string): MessageStatus {\n const statusMap: Record<string, MessageStatus> = {\n queued: 'queued',\n sending: 'queued',\n sent: 'sent',\n delivered: 'delivered',\n undelivered: 'undelivered',\n failed: 'failed',\n read: 'read',\n accepted: 'queued',\n };\n return statusMap[status.toLowerCase()] ?? 'unknown';\n}\n\n/**\n * Twilio webhook handler\n */\nexport class TwilioWebhookHandler implements WebhookHandler<TwilioStatusPayload | TwilioIncomingPayload> {\n private readonly authToken: string;\n\n constructor(authToken: string) {\n this.authToken = authToken;\n }\n\n /**\n * Verify Twilio webhook signature\n * @see https://www.twilio.com/docs/usage/webhooks/webhooks-security\n */\n verify(body: unknown, headers: Record<string, string>): boolean {\n const signature = headers['x-twilio-signature'] ?? headers['X-Twilio-Signature'];\n const url = headers['x-original-url'] ?? headers['X-Original-Url'] ?? '';\n\n if (!signature || !url) {\n return false;\n }\n\n // Build the validation string\n const params = body as Record<string, string>;\n let validationString = url;\n\n // Sort and concatenate POST parameters\n if (params && typeof params === 'object') {\n const sortedKeys = Object.keys(params).sort();\n for (const key of sortedKeys) {\n validationString += key + params[key];\n }\n }\n\n // Compute expected signature\n const expectedSignature = crypto\n .createHmac('sha1', this.authToken)\n .update(validationString, 'utf-8')\n .digest('base64');\n\n // Constant-time comparison to prevent timing attacks\n try {\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature),\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Parse Twilio webhook payload\n */\n parse(body: TwilioStatusPayload | TwilioIncomingPayload): WebhookEvent[] {\n const events: WebhookEvent[] = [];\n\n // Check if this is a status update or incoming message\n if ('MessageStatus' in body) {\n // Status update\n const statusEvent: StatusWebhookEvent = {\n type: 'status',\n messageId: body.MessageSid,\n channel: 'sms',\n timestamp: new Date(),\n provider: 'twilio',\n status: mapTwilioStatus(body.MessageStatus),\n to: body.To,\n error: body.ErrorCode\n ? {\n code: body.ErrorCode,\n message: body.ErrorMessage ?? 'Unknown error',\n retriable: false,\n }\n : undefined,\n };\n events.push(statusEvent);\n } else if ('Body' in body) {\n // Incoming message\n const messageEvent: IncomingMessageEvent = {\n type: 'message',\n messageId: body.MessageSid,\n channel: 'sms',\n timestamp: new Date(),\n provider: 'twilio',\n from: body.From,\n message: body.Body,\n mediaUrl: body.MediaUrl0,\n mediaType: body.MediaContentType0,\n };\n events.push(messageEvent);\n }\n\n return events;\n }\n}\n\n/**\n * Create a Twilio webhook handler\n */\nexport function createTwilioWebhookHandler(authToken: string): TwilioWebhookHandler {\n return new TwilioWebhookHandler(authToken);\n}\n","import * as crypto from 'crypto';\nimport type {\n WebhookHandler,\n StatusWebhookEvent,\n IncomingMessageEvent,\n MessageStatus,\n WebhookEvent,\n} from '../types.js';\n\n/**\n * Meta WhatsApp webhook payload structure\n * @see https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components\n */\ninterface MetaWebhookPayload {\n object: 'whatsapp_business_account';\n entry: Array<{\n id: string;\n changes: Array<{\n value: {\n messaging_product: 'whatsapp';\n metadata: {\n display_phone_number: string;\n phone_number_id: string;\n };\n contacts?: Array<{\n profile: { name: string };\n wa_id: string;\n }>;\n messages?: Array<{\n from: string;\n id: string;\n timestamp: string;\n type: 'text' | 'image' | 'document' | 'audio' | 'video' | 'sticker' | 'location' | 'contacts' | 'button' | 'interactive';\n text?: { body: string };\n image?: { id: string; mime_type: string; sha256: string };\n document?: { id: string; mime_type: string; sha256: string; filename?: string };\n audio?: { id: string; mime_type: string };\n video?: { id: string; mime_type: string };\n button?: { text: string; payload: string };\n interactive?: { type: string; button_reply?: { id: string; title: string }; list_reply?: { id: string; title: string } };\n }>;\n statuses?: Array<{\n id: string;\n status: 'sent' | 'delivered' | 'read' | 'failed';\n timestamp: string;\n recipient_id: string;\n errors?: Array<{\n code: number;\n title: string;\n message?: string;\n error_data?: { details: string };\n }>;\n }>;\n };\n field: 'messages';\n }>;\n }>;\n}\n\n/**\n * Map Meta status to our MessageStatus\n */\nfunction mapMetaStatus(status: string): MessageStatus {\n const statusMap: Record<string, MessageStatus> = {\n sent: 'sent',\n delivered: 'delivered',\n read: 'read',\n failed: 'failed',\n };\n return statusMap[status.toLowerCase()] ?? 'unknown';\n}\n\n/**\n * Meta WhatsApp Cloud API webhook handler\n */\nexport class WhatsAppWebhookHandler implements WebhookHandler<MetaWebhookPayload> {\n private readonly appSecret: string;\n private readonly verifyToken: string;\n\n constructor(appSecret: string, verifyToken: string) {\n this.appSecret = appSecret;\n this.verifyToken = verifyToken;\n }\n\n /**\n * Verify WhatsApp webhook challenge (for initial setup)\n */\n verifyChallenge(verifyToken: string, challenge: string): string | null {\n if (verifyToken === this.verifyToken) {\n return challenge;\n }\n return null;\n }\n\n /**\n * Verify Meta webhook signature\n * @see https://developers.facebook.com/docs/graph-api/webhooks/getting-started#verification-requests\n */\n verify(body: unknown, headers: Record<string, string>): boolean {\n const signature = headers['x-hub-signature-256'] ?? headers['X-Hub-Signature-256'];\n\n if (!signature || !this.appSecret) {\n return false;\n }\n\n // Get raw body string\n const rawBody = typeof body === 'string' ? body : JSON.stringify(body);\n\n // Compute expected signature\n const expectedSignature =\n 'sha256=' +\n crypto\n .createHmac('sha256', this.appSecret)\n .update(rawBody, 'utf-8')\n .digest('hex');\n\n // Constant-time comparison\n try {\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature),\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Parse Meta WhatsApp webhook payload\n */\n parse(body: MetaWebhookPayload): WebhookEvent[] {\n const events: WebhookEvent[] = [];\n\n if (body.object !== 'whatsapp_business_account') {\n return events;\n }\n\n for (const entry of body.entry) {\n for (const change of entry.changes) {\n if (change.field !== 'messages') continue;\n\n const value = change.value;\n\n // Process status updates\n if (value.statuses) {\n for (const status of value.statuses) {\n const statusEvent: StatusWebhookEvent = {\n type: 'status',\n messageId: status.id,\n channel: 'whatsapp',\n timestamp: new Date(parseInt(status.timestamp) * 1000),\n provider: 'meta',\n status: mapMetaStatus(status.status),\n to: status.recipient_id,\n error:\n status.errors && status.errors.length > 0\n ? {\n code: String(status.errors[0]!.code),\n message: status.errors[0]!.message ?? status.errors[0]!.title,\n retriable: false,\n }\n : undefined,\n };\n events.push(statusEvent);\n }\n }\n\n // Process incoming messages\n if (value.messages) {\n for (const message of value.messages) {\n let messageText: string | undefined;\n let mediaType: string | undefined;\n\n // Extract message content based on type\n switch (message.type) {\n case 'text':\n messageText = message.text?.body;\n break;\n case 'button':\n messageText = message.button?.text;\n break;\n case 'interactive':\n messageText =\n message.interactive?.button_reply?.title ??\n message.interactive?.list_reply?.title;\n break;\n case 'image':\n mediaType = message.image?.mime_type;\n break;\n case 'document':\n mediaType = message.document?.mime_type;\n break;\n case 'audio':\n mediaType = message.audio?.mime_type;\n break;\n case 'video':\n mediaType = message.video?.mime_type;\n break;\n }\n\n const messageEvent: IncomingMessageEvent = {\n type: 'message',\n messageId: message.id,\n channel: 'whatsapp',\n timestamp: new Date(parseInt(message.timestamp) * 1000),\n provider: 'meta',\n from: message.from,\n message: messageText,\n mediaType,\n };\n events.push(messageEvent);\n }\n }\n }\n }\n\n return events;\n }\n}\n\n/**\n * Create a WhatsApp webhook handler\n */\nexport function createWhatsAppWebhookHandler(\n appSecret: string,\n verifyToken: string,\n): WhatsAppWebhookHandler {\n return new WhatsAppWebhookHandler(appSecret, verifyToken);\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@skoolite/notify-hub",
3
+ "version": "0.1.0",
4
+ "description": "Multi-channel notification hub for SMS, WhatsApp, and Email",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "test:coverage": "vitest run --coverage",
24
+ "test:integration": "vitest run --config vitest.integration.config.ts",
25
+ "lint": "eslint src --ext .ts",
26
+ "lint:fix": "eslint src --ext .ts --fix",
27
+ "typecheck": "tsc --noEmit",
28
+ "clean": "rm -rf dist coverage"
29
+ },
30
+ "keywords": [
31
+ "sms",
32
+ "whatsapp",
33
+ "email",
34
+ "notifications",
35
+ "twilio",
36
+ "meta",
37
+ "aws-ses"
38
+ ],
39
+ "author": "Skoolyte",
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://gitlab.com/skoolyte/notify-hub"
44
+ },
45
+ "dependencies": {
46
+ "twilio": "^5.0.0",
47
+ "libphonenumber-js": "^1.10.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^20.11.0",
51
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
52
+ "@typescript-eslint/parser": "^7.0.0",
53
+ "@vitest/coverage-v8": "^1.3.0",
54
+ "eslint": "^8.57.0",
55
+ "tsup": "^8.0.0",
56
+ "typescript": "^5.3.0",
57
+ "vitest": "^1.3.0"
58
+ },
59
+ "peerDependencies": {
60
+ "@aws-sdk/client-ses": "^3.500.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@aws-sdk/client-ses": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "engines": {
68
+ "node": ">=20.0.0"
69
+ }
70
+ }