UNPKG

@454creative/easy-email

Version:

A framework-agnostic email service library for Node.js with observability and monitoring

171 lines (149 loc) 5.07 kB
import { ITemplateService, TemplateInfo, TemplateValidationResult } from '../interfaces/template.interface'; import { EmailProviderType } from '../interfaces/email-options.interface'; import { SendGridTemplateService } from './templates/sendgrid-template.service'; import { SesTemplateService } from './templates/ses-template.service'; import { SendGridConfig, SesConfig } from '../interfaces/email-options.interface'; import { Logger } from '../utils/logger'; import { ConfigurationError } from '../errors'; export class TemplateManagerService { private templateServices: Map<EmailProviderType, ITemplateService> = new Map(); private logger: Logger; constructor() { this.logger = Logger.getInstance(); } /** * Register a template service for a specific provider */ registerTemplateService(provider: EmailProviderType, service: ITemplateService): void { this.templateServices.set(provider, service); this.logger.debug(`Template service registered for provider: ${provider}`); } /** * Register SendGrid template service */ registerSendGridService(config: SendGridConfig): void { const service = new SendGridTemplateService(config); this.registerTemplateService(EmailProviderType.SENDGRID, service); } /** * Register SES template service */ registerSesService(config: SesConfig): void { const service = new SesTemplateService(config); this.registerTemplateService(EmailProviderType.SES, service); } /** * Check if a template service is available for a provider */ hasTemplateService(provider: EmailProviderType): boolean { return this.templateServices.has(provider); } /** * Get template service for a specific provider */ getTemplateService(provider: EmailProviderType): ITemplateService { const service = this.templateServices.get(provider); if (!service) { throw new ConfigurationError(`Template service not available for provider: ${provider}`); } return service; } /** * Render template using the appropriate service */ async renderTemplate( templateId: string, data: Record<string, any>, provider: EmailProviderType ): Promise<string> { const service = this.getTemplateService(provider); return service.renderTemplate(templateId, data, provider); } /** * Validate template using the appropriate service */ async validateTemplate( templateId: string, provider: EmailProviderType ): Promise<boolean> { const service = this.getTemplateService(provider); return service.validateTemplate(templateId, provider); } /** * Get template info using the appropriate service */ async getTemplateInfo( templateId: string, provider: EmailProviderType ): Promise<TemplateInfo> { const service = this.getTemplateService(provider); return service.getTemplateInfo(templateId, provider); } /** * Validate template with detailed results */ async validateTemplateWithDetails( templateId: string, data: Record<string, any>, provider: EmailProviderType ): Promise<TemplateValidationResult> { const service = this.getTemplateService(provider); // Check if the service has the extended validation method if ('validateTemplateWithDetails' in service) { return (service as any).validateTemplateWithDetails(templateId, data); } // Fallback to basic validation const isValid = await service.validateTemplate(templateId, provider); return { isValid, errors: isValid ? [] : [`Template validation failed: ${templateId}`], warnings: [], variables: [], missingVariables: [] }; } /** * List available templates for a provider */ async listTemplates(provider: EmailProviderType): Promise<string[]> { const service = this.getTemplateService(provider); // Check if the service has the listTemplates method if ('listTemplates' in service) { return (service as any).listTemplates(); } // Fallback: return empty array this.logger.warn(`Provider ${provider} does not support listing templates`); return []; } /** * Get all available template services */ getAvailableProviders(): EmailProviderType[] { return Array.from(this.templateServices.keys()); } /** * Clear all registered template services */ clearServices(): void { this.templateServices.clear(); this.logger.debug('All template services cleared'); } /** * Get service statistics */ getServiceStats(): Record<string, any> { const stats: Record<string, any> = { totalServices: this.templateServices.size, availableProviders: this.getAvailableProviders(), services: {} }; for (const [provider, service] of this.templateServices.entries()) { stats.services[provider] = { serviceName: service.constructor.name, hasExtendedValidation: 'validateTemplateWithDetails' in service, hasListTemplates: 'listTemplates' in service }; } return stats; } }