UNPKG

@454creative/easy-email

Version:

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

192 lines 9.06 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SesTemplateService = void 0; const email_options_interface_1 = require("../../interfaces/email-options.interface"); const logger_1 = require("../../utils/logger"); const errors_1 = require("../../errors"); const client_ses_1 = require("@aws-sdk/client-ses"); const { GetTemplateCommand, ListTemplatesCommand } = require('@aws-sdk/client-ses'); class SesTemplateService { constructor(config) { this.config = config; this.logger = logger_1.Logger.getInstance(); this.client = this.createSesClient(); } renderTemplate(templateName, data, provider) { return __awaiter(this, void 0, void 0, function* () { if (provider !== email_options_interface_1.EmailProviderType.SES) { throw new errors_1.TemplateError(`Provider ${provider} not supported by SesTemplateService`); } try { this.logger.debug(`Rendering SES template: ${templateName}`, { data }); const template = yield this.getTemplate(templateName); const renderedContent = this.renderWithData(template, data); this.logger.debug(`SES template rendered successfully: ${templateName}`); return renderedContent; } catch (error) { this.logger.error(`Failed to render SES template: ${templateName}`, { error }); throw new errors_1.TemplateError(`Failed to render SES template: ${templateName}`, { error }); } }); } validateTemplate(templateName, provider) { return __awaiter(this, void 0, void 0, function* () { if (provider !== email_options_interface_1.EmailProviderType.SES) { return false; } try { yield this.getTemplate(templateName); return true; } catch (_a) { return false; } }); } getTemplateInfo(templateName, provider) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; if (provider !== email_options_interface_1.EmailProviderType.SES) { throw new errors_1.TemplateError(`Provider ${provider} not supported by SesTemplateService`); } try { const template = yield this.getTemplate(templateName); return { id: templateName, name: ((_a = template.Template) === null || _a === void 0 ? void 0 : _a.TemplateName) || templateName, version: ((_b = template.Template) === null || _b === void 0 ? void 0 : _b.Version) || '1.0.0', variables: this.extractVariables(((_c = template.Template) === null || _c === void 0 ? void 0 : _c.HtmlPart) || ''), lastModified: ((_d = template.Template) === null || _d === void 0 ? void 0 : _d.LastModifiedDate) || new Date(), provider: email_options_interface_1.EmailProviderType.SES }; } catch (error) { throw new errors_1.TemplateError(`Failed to get template info: ${templateName}`, { error }); } }); } validateTemplateWithDetails(templateName, data) { return __awaiter(this, void 0, void 0, function* () { var _a; try { const template = yield this.getTemplate(templateName); const templateVariables = this.extractVariables(((_a = template.Template) === null || _a === void 0 ? void 0 : _a.HtmlPart) || ''); const providedVariables = Object.keys(data); const missingVariables = templateVariables.filter(v => !providedVariables.includes(v)); const warnings = providedVariables.filter(v => !templateVariables.includes(v)); return { isValid: missingVariables.length === 0, errors: missingVariables.length > 0 ? [`Missing required variables: ${missingVariables.join(', ')}`] : [], warnings: warnings.length > 0 ? [`Unused variables provided: ${warnings.join(', ')}`] : [], variables: templateVariables, missingVariables }; } catch (error) { return { isValid: false, errors: [`Template not found or invalid: ${templateName}`], warnings: [], variables: [], missingVariables: [] }; } }); } listTemplates() { return __awaiter(this, void 0, void 0, function* () { var _a; try { const command = new ListTemplatesCommand({}); const response = yield this.client.send(command); return ((_a = response.TemplatesMetadata) === null || _a === void 0 ? void 0 : _a.map((t) => t.Name || '')) || []; } catch (error) { this.logger.error('Failed to list SES templates', { error }); throw new errors_1.TemplateError('Failed to list SES templates', { error }); } }); } createSesClient() { const clientConfig = { region: this.config.region, apiVersion: this.config.apiVersion || '2010-12-01', maxAttempts: this.config.maxRetries || 3, }; if (this.config.credentials) { clientConfig.credentials = this.config.credentials; } else if (this.config.accessKeyId && this.config.secretAccessKey) { clientConfig.credentials = { accessKeyId: this.config.accessKeyId, secretAccessKey: this.config.secretAccessKey, sessionToken: this.config.sessionToken, }; } if (this.config.endpoint) { clientConfig.endpoint = this.config.endpoint; } return new client_ses_1.SESClient(clientConfig); } getTemplate(templateName) { return __awaiter(this, void 0, void 0, function* () { try { const command = new GetTemplateCommand({ TemplateName: templateName }); const response = yield this.client.send(command); if (!response.Template) { throw new errors_1.InvalidTemplateError(`SES template not found: ${templateName}`); } return response; } catch (error) { if (error.name === 'TemplateDoesNotExist') { throw new errors_1.InvalidTemplateError(`SES template does not exist: ${templateName}`); } throw error; } }); } extractVariables(htmlContent) { // Extract variables from SES template format // SES uses {{variable}} format const variableRegex = /\{\{([^}]+)\}\}/g; const variables = []; let match; while ((match = variableRegex.exec(htmlContent)) !== null) { const variable = match[1].trim(); if (!variables.includes(variable)) { variables.push(variable); } } return variables; } renderWithData(template, data) { var _a, _b; let content = ((_a = template.Template) === null || _a === void 0 ? void 0 : _a.HtmlPart) || ((_b = template.Template) === null || _b === void 0 ? void 0 : _b.TextPart) || ''; // Replace variables with data Object.entries(data).forEach(([key, value]) => { const regex = new RegExp(`{{${key}}}`, 'g'); content = content.replace(regex, String(value)); }); // Replace any remaining variables with empty strings const remainingVariables = content.match(/\{\{([^}]+)\}\}/g) || []; remainingVariables.forEach((variable) => { const key = variable.slice(2, -2); // Remove {{ }} const regex = new RegExp(`{{${key}}}`, 'g'); content = content.replace(regex, ''); }); return content; } } exports.SesTemplateService = SesTemplateService; //# sourceMappingURL=ses-template.service.js.map