import fs from 'fs'; import path from 'path'; import { createLogger } from './logger'; const log = createLogger('email:templates'); // Cache for loaded templates const templateCache = new Map(); /** * Template variable type for type-safe template rendering */ export type TemplateVariables = { [key: string]: string | number | undefined; }; /** * Load an email template from the templates directory * @param templateName Name of the template file (without extension) * @param language Language code (default: 'en') * @returns Template content as string */ export function loadTemplate(templateName: string, language: string = 'en'): string { const cacheKey = `${templateName}--${language}`; // Check cache first if (templateCache.has(cacheKey)) { log(`Using cached template: ${cacheKey}`); return templateCache.get(cacheKey)!; } // Construct template file path const templateFileName = `email-template--${templateName}--${language}.html`; const templatePath = path.join(__dirname, '../../email-templates', templateFileName); try { const content = fs.readFileSync(templatePath, 'utf-8'); templateCache.set(cacheKey, content); log(`Loaded template: ${templateFileName}`); return content; } catch (error) { log(`Failed to load template ${templateFileName}: ${error}`); throw new Error(`Template not found: ${templateFileName}`); } } /** * Render a template by replacing variables * @param template Template content * @param variables Object with variable values * @returns Rendered HTML string */ export function renderTemplate(template: string, variables: TemplateVariables): string { let rendered = template; // Replace all ${variable} occurrences for (const [key, value] of Object.entries(variables)) { if (value !== undefined) { const regex = new RegExp(`\\$\\{${key}\\}`, 'g'); rendered = rendered.replace(regex, String(value)); } } // Log warning if there are unreplaced variables const unreplacedMatches = rendered.match(/\$\{[^}]+\}/g); if (unreplacedMatches) { log(`Warning: Unreplaced variables in template: ${unreplacedMatches.join(', ')}`); } return rendered; } /** * Load and render an email template in one step * @param templateName Name of the template file (without extension) * @param variables Object with variable values * @param language Language code (default: 'en') * @returns Rendered HTML string */ export function loadAndRender( templateName: string, variables: TemplateVariables, language: string = 'en' ): string { const template = loadTemplate(templateName, language); return renderTemplate(template, variables); }