@454creative/easy-email
Version:
A framework-agnostic email service library for Node.js with observability and monitoring
171 lines (149 loc) • 5.07 kB
text/typescript
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;
}
}