@bernierllc/电子邮件-template-service
电子邮件模板管理服务,提供商同步,可变上下文验证,以及基础模板支持.
特征
- 使用验证完成 CRUD 模板操作
- 电子邮件服务集成的提供者插件系统( SendGrid, Mailgun等)
- 地方数据库与提供者服务之间的双向同步
- 可变上下文登记和验证
- 一致品牌的基础模板支持
- 发现和解决冲突战略
- 批次同步与错误跟踪
- TypeScript 首个严格类型安全
- 可扩展的数据库适配器接口
安装
npm install @bernierllc/email-template-service
快速启动
import {
EmailTemplateService,
InMemoryDatabaseAdapter,
MockProviderPlugin
} from '@bernierllc/email-template-service';
// Initialize service
const service = new EmailTemplateService({
database: new InMemoryDatabaseAdapter(),
templateEngine: myTemplateEngine,
variableRegistry: myVariableRegistry,
providers: [new MockProviderPlugin()],
syncConfig: {
enabled: true,
providers: {
sendgrid: {
enabled: true,
strategy: 'auto',
direction: 'bidirectional'
}
},
defaultStrategy: 'auto',
conflictResolution: 'local_wins'
}
});
// Create a template
const template = await service.createTemplate({
name: 'Welcome Email',
subject: 'Welcome to our platform, {{firstName}}!',
htmlContent: '<html><body><h1>Welcome {{firstName}} {{lastName}}!</h1></body></html>',
textContent: 'Welcome {{firstName}} {{lastName}}!',
tags: ['welcome', 'onboarding'],
createdBy: 'admin'
});
// Sync to provider
await service.syncToProvider(template.id, 'sendgrid');
// List templates
const result = await service.listTemplates({
category: 'transactional',
page: 1,
limit: 10
});
核心概念
模板
模板是电子邮件定义,支持:
- HTML 和文本内容
- 可变占位符(例如,
{{firstName}}(中文(简体) ) - 有变量的主题行
- 分类和标记
- 版本
- 提供者同步状态
提供者插件
提供者插件允许与电子邮件服务供应商进行集成 :
- 发送Grid: 模板管理和同步
- 邮件枪: 模板操作和跟踪
- 自定义: 执行
TemplateProviderPlugin接口
插件支持 :
- 供应商系统中的模板 CRUD 操作
- 双向同步
- 特征能力检测
- 卫生监测和状况报告
可变上下文
可变背景定义模板的现有变量 :
- 类型安全可变定义
- 需要 vs 可选变量
- 环境继承
- 针对上下文的模板验证
- 自动补全建议
基准模板
基础模板提供一致的品牌:
- 重用页眉/页脚 HTML 和 CSS
- 主题管理
- 品牌元素(日志、颜色、字体)
- 动态内容插入
- 从 Base + 内容创建模板
API 参考
电子邮件模板服务
模板操作
创建模板( 定义: 模板定义): 承诺
创建新的电子邮件模板 .
const template = await service.createTemplate({
name: 'Password Reset',
subject: 'Reset your password',
htmlContent: '<html><body>Click here to reset: {{resetLink}}</body></html>',
context: 'auth',
createdBy: 'admin'
});
更新 Template( id: string, 更新: Template Update): 承诺
更新现有模板.
const updated = await service.updateTemplate(template.id, {
subject: 'Reset your password - Updated',
lastModifiedBy: 'admin'
});
删除模板( id: string): 保证
删除模板及其供应商副本.
await service.deleteTemplate(template.id);
获取Template( id: string): 保证<Template QQ 无效>
通过ID获取模板 .
const template = await service.getTemplate('tpl_123');
列表模板( 选项: 列表选项): 承诺 < PaginatedResult >
带有过滤和页码的列表模板.
const result = await service.listTemplates({
category: 'marketing',
tags: ['promo'],
isActive: true,
search: 'holiday',
page: 1,
limit: 20,
sortBy: 'createdAt',
sortOrder: 'desc'
});
提供者同步
同步到提供( 模板: 字符串, 提供者: 字符串): 保证
同步模板到特定提供者 .
const result = await service.syncToProvider('tpl_123', 'sendgrid');
console.log(result.action); // 'created' or 'updated'
console.log(result.providerTemplateId);
从提供方同步( 提供方TemplateId: 字符串, 提供方Id: 字符串): 保证
从提供者导入模板 .
const template = await service.syncFromProvider('sg_template_456', 'sendgrid');
同步 AllTemplades( 提供者: 字符串): 保证
将所有本地模板同步到提供者 .
const result = await service.syncAllTemplates('sendgrid');
console.log(`Synced: ${result.successful}/${result.total}`);
console.log(`Failed: ${result.failed}`);
基础模板操作
创建BaseTemplate( 定义: BaseTemplate 定义): 承诺
创建可重用的基础模板 .
const baseTemplate = await service.createBaseTemplate({
name: 'Corporate Email Template',
headerHtml: '<header><img src="{{logo}}" /></header>',
footerHtml: '<footer>© 2025 Company Name</footer>',
theme: 'corporate'
});
构建Template( baseTemplateId: 字符串, 内容: 字符串, 变量? : 记录 < 字符串, 未知 > ): 答应
从 Base + 内容建立完整的模板.
const built = await service.buildTemplate(
baseTemplate.id,
'<main><h1>{{title}}</h1><p>{{content}}</p></main>',
{
logo: 'https://example.com/logo.png',
title: 'Important Update',
content: 'This is the email body'
}
);
console.log(built.html); // Complete HTML with header, content, footer
console.log(built.text); // Plain text version
可变背景管理
注册连接( 名称: 字符串, 上下文: 可变连接): 承诺
注册模板的可变上下文 .
await service.registerContext('user', {
description: 'User-related variables',
variables: {
firstName: { type: 'string', required: true, description: 'User first name' },
lastName: { type: 'string', required: true, description: 'User last name' },
email: { type: 'string', required: true, description: 'User email address' },
accountAge: { type: 'number', required: false, description: 'Days since signup' }
}
});
验证Template( TemplateId: 字符串, 上下文? Override: 字符串): 保证
对照可变上下文验证模板.
const validation = await service.validateTemplate('tpl_123');
if (!validation.isValid) {
console.log('Errors:', validation.errors);
console.log('Undefined variables:', validation.undefinedVariables);
}
获得可变建议( 文本: 字符串, 前缀 ? : 字符串): 保证 < 可变建议 >
获取自动补全的可变建议 .
const suggestions = await service.getVariableSuggestions('user', 'first');
// Returns: [{ name: 'firstName', type: 'string', ... }]
数据库适配器
该服务支持通过 DatabaseAdapter 接口.
记忆适应器(试验/开发)
import { InMemoryDatabaseAdapter } from '@bernierllc/email-template-service';
const adapter = new InMemoryDatabaseAdapter();
自定义适配器
执行 DatabaseAdapter 用于数据库的界面 :
import { DatabaseAdapter, Template, BaseTemplate } from '@bernierllc/email-template-service';
class PostgresDatabaseAdapter implements DatabaseAdapter {
async createTemplate(template: Template): Promise<Template> {
// Insert into PostgreSQL
}
async updateTemplate(id: string, updates: Partial<Template>): Promise<Template> {
// Update PostgreSQL row
}
// Implement other required methods...
}
提供者插件
创建提供者插件
import {
BaseProviderPlugin,
Template,
ProviderTemplate,
SyncResult
} from '@bernierllc/email-template-service';
class SendGridTemplatePlugin extends BaseProviderPlugin {
readonly name = 'SendGrid Template Plugin';
readonly version = '1.0.0';
readonly providerId = 'sendgrid';
readonly capabilities = [
{
feature: 'template-versioning',
description: 'Supports template versions',
methods: ['createTemplate', 'updateTemplate']
}
];
async initialize(config: PluginConfig): Promise<void> {
await super.initialize(config);
this.client = new SendGridClient(config.apiKey);
}
async createTemplate(template: Template): Promise<string> {
this.ensureInitialized();
const result = await this.client.createTemplate({
name: template.name,
generation: 'dynamic',
subject: template.subject,
html_content: template.htmlContent
});
return result.id;
}
// Implement other required methods...
}
配置
同步配置
{
enabled: true, // Enable synchronization
providers: {
sendgrid: {
enabled: true,
strategy: 'auto', // 'auto', 'manual', or 'scheduled'
direction: 'bidirectional', // 'bidirectional', 'push_only', 'pull_only'
schedule: '0 */6 * * *', // Cron expression for scheduled sync
batchSize: 50 // Batch size for bulk operations
}
},
defaultStrategy: 'manual', // Default sync strategy
conflictResolution: 'local_wins' // 'local_wins', 'remote_wins', 'timestamp', 'manual'
}
处理错误
该服务提供特定错误类型 :
import {
TemplateNotFoundError,
TemplateValidationError,
ProviderNotFoundError,
SyncError,
SyncConflictError
} from '@bernierllc/email-template-service';
try {
await service.updateTemplate('invalid-id', { name: 'New Name' });
} catch (error) {
if (error instanceof TemplateNotFoundError) {
console.error('Template not found');
} else if (error instanceof TemplateValidationError) {
console.error('Validation errors:', error.errors);
} else if (error instanceof SyncError) {
console.error('Sync failed:', error.message);
}
}
测试
该套件包括使用真实数据进行的全面测试:
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests once (CI)
npm run test:run
依赖关系
需求
@bernierllc/template-variable-registry- 可变背景管理@bernierllc/email-template-engine- 模板处理@bernierllc/email-sender- 电子邮件发送抽象@bernierllc/logger- 服务记录
可选
@bernierllc/cache-manager- 模板缓存@bernierllc/retry-policy- 供应商业务复试
一体化状况
- 锁定器: 集成 - 所有服务业务和提供者同步事件记录
- 多克套装: 准备 - 有示例的完整 API 文档
- 从不: 需要 - 模板活动、同步状态和提供者健康监测
许可证
版权(c)2025 Bernier有限责任公司。 版权所有.
另见
- @bernierllc/电子邮件-template-engine - 模板处理和渲染
- @bernierllc/template-可变登记 - 可变背景管理
- @bernierllc/电子邮件发送器 - 电子邮件发送服务
- @bernierlc/电子邮件-sendgrid-plugin - 发送Grid 提供者插件