UNPKG

@mirad-work/sms-core

Version:

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

159 lines 5.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseSmsDriver = void 0; const sms_exceptions_1 = require("../exceptions/sms-exceptions"); /** * Abstract base class for all SMS drivers * Provides common functionality and enforces interface implementation */ class BaseSmsDriver { constructor(config, httpClient) { this.validateConfig(config); this.config = config; this.httpClient = httpClient; } /** * Build default headers for HTTP requests */ buildHeaders(additionalHeaders = {}) { return { "Content-Type": "application/json", Accept: "application/json", "User-Agent": "@mirad-work/sms-core", ...additionalHeaders, }; } /** * Build URL by combining base URL with endpoint */ buildUrl(endpoint) { if (!this.config.url) { throw new sms_exceptions_1.SmsDriverException("Driver URL is not configured"); } const baseUrl = this.config.url.replace(/\/$/, ""); const cleanEndpoint = endpoint.replace(/^\//, ""); return `${baseUrl}/${cleanEndpoint}`; } /** * Validate SMS message before sending */ validateMessage(message) { if (!message) { throw new sms_exceptions_1.MessageValidationException("Message is required"); } if (!message.to) { throw new sms_exceptions_1.MessageValidationException("Recipient phone number is required"); } if (!message.content && !message.template) { throw new sms_exceptions_1.MessageValidationException("Either content or template must be provided"); } if (message.template && !message.tokens) { throw new sms_exceptions_1.MessageValidationException("Tokens are required when using templates"); } // Basic phone number validation (should start with + or digits) if (!/^[+\d][\d\s-()]*$/.test(message.to)) { throw new sms_exceptions_1.MessageValidationException("Invalid phone number format"); } } /** * Validate driver configuration */ validateConfig(config) { if (!config) { throw new sms_exceptions_1.SmsDriverException("Driver configuration is required"); } if (!config.url) { throw new sms_exceptions_1.SmsDriverException("Driver URL is required"); } try { new URL(config.url); } catch { throw new sms_exceptions_1.SmsDriverException("Invalid driver URL format"); } } /** * Handle HTTP errors and convert to appropriate exceptions */ async handleHttpRequest(requestFn) { try { const response = await requestFn(); // Check for HTTP error status codes if (response.status >= 400) { throw new sms_exceptions_1.HttpException(`HTTP ${response.status}: ${response.statusText}`, response.status, response.data); } return response; } catch (error) { if (error instanceof sms_exceptions_1.HttpException) { throw error; } throw new sms_exceptions_1.SmsDriverException(`HTTP request failed: ${error.message}`, error, "HTTP_REQUEST_FAILED"); } } /** * Handle and standardize driver errors */ handleError(error, context = "Driver operation") { if (error instanceof sms_exceptions_1.SmsDriverException || error instanceof sms_exceptions_1.MessageValidationException) { throw error; } const errorMessage = error instanceof Error ? error.message : String(error); throw new sms_exceptions_1.SmsDriverException(`${context} failed: ${errorMessage}`, error, "DRIVER_ERROR"); } /** * Create a standardized success response */ createSuccessResponse(data, messageId) { return { success: true, messageId, data, }; } /** * Create a standardized error response */ createErrorResponse(error, errorCode, data) { return { success: false, error, errorCode, data, }; } /** * Extract message ID from provider response * This method can be overridden by concrete drivers if needed */ extractMessageId(response) { if (!response || typeof response !== "object") { return undefined; } const responseObj = response; // Common patterns for message ID extraction const messageId = responseObj.messageId || responseObj.id || responseObj.message_id || (responseObj.data && typeof responseObj.data === "object" && responseObj.data.messageId) || (responseObj.data && typeof responseObj.data === "object" && responseObj.data.id); return typeof messageId === "string" ? messageId : undefined; } /** * Log request/response for debugging (can be overridden) */ log(level, message, data) { // Simple console logging - can be replaced with proper logging library const timestamp = new Date().toISOString(); const logData = data ? JSON.stringify(data, null, 2) : ""; // eslint-disable-next-line no-console console[level](`[${timestamp}] [SMS-Driver] ${message}`, logData); } } exports.BaseSmsDriver = BaseSmsDriver; //# sourceMappingURL=base-driver.js.map