tzmail 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5091 -0
- package/dist/core/enums/template-part.enum.d.ts +7 -0
- package/dist/core/enums/template-part.enum.d.ts.map +1 -0
- package/dist/core/enums/template-part.enum.js +10 -0
- package/dist/core/enums/theme.enum.d.ts +8 -0
- package/dist/core/enums/theme.enum.d.ts.map +1 -0
- package/dist/core/enums/theme.enum.js +11 -0
- package/dist/core/interfaces/email.interface.d.ts +32 -0
- package/dist/core/interfaces/email.interface.d.ts.map +1 -0
- package/dist/core/interfaces/email.interface.js +2 -0
- package/dist/core/interfaces/template.interface.d.ts +56 -0
- package/dist/core/interfaces/template.interface.d.ts.map +1 -0
- package/dist/core/interfaces/template.interface.js +2 -0
- package/dist/factories/email-factory.d.ts +34 -0
- package/dist/factories/email-factory.d.ts.map +1 -0
- package/dist/factories/email-factory.js +52 -0
- package/dist/factories/template-factory.d.ts +15 -0
- package/dist/factories/template-factory.d.ts.map +1 -0
- package/dist/factories/template-factory.js +96 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +265 -0
- package/dist/services/attachment.service.d.ts +48 -0
- package/dist/services/attachment.service.d.ts.map +1 -0
- package/dist/services/attachment.service.js +93 -0
- package/dist/services/email.service.d.ts +31 -0
- package/dist/services/email.service.d.ts.map +1 -0
- package/dist/services/email.service.js +58 -0
- package/dist/services/template.service.d.ts +180 -0
- package/dist/services/template.service.d.ts.map +1 -0
- package/dist/services/template.service.js +507 -0
- package/dist/templates/base/template-builder.d.ts +23 -0
- package/dist/templates/base/template-builder.d.ts.map +1 -0
- package/dist/templates/base/template-builder.js +676 -0
- package/dist/templates/themes/corporate.theme.d.ts +65 -0
- package/dist/templates/themes/corporate.theme.d.ts.map +1 -0
- package/dist/templates/themes/corporate.theme.js +109 -0
- package/dist/templates/themes/minimal.theme.d.ts +70 -0
- package/dist/templates/themes/minimal.theme.d.ts.map +1 -0
- package/dist/templates/themes/minimal.theme.js +114 -0
- package/dist/templates/themes/modern.theme.d.ts +38 -0
- package/dist/templates/themes/modern.theme.d.ts.map +1 -0
- package/dist/templates/themes/modern.theme.js +81 -0
- package/dist/templates/themes/monokai.theme.d.ts +29 -0
- package/dist/templates/themes/monokai.theme.d.ts.map +1 -0
- package/dist/templates/themes/monokai.theme.js +73 -0
- package/dist/templates/themes/system.theme.d.ts +50 -0
- package/dist/templates/themes/system.theme.d.ts.map +1 -0
- package/dist/templates/themes/system.theme.js +54 -0
- package/dist/templates/themes/theme.interface.d.ts +42 -0
- package/dist/templates/themes/theme.interface.d.ts.map +1 -0
- package/dist/templates/themes/theme.interface.js +2 -0
- package/dist/tests/template.service.test.d.ts +1 -0
- package/dist/tests/template.service.test.d.ts.map +1 -0
- package/dist/tests/template.service.test.js +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateService = void 0;
|
|
4
|
+
const template_factory_1 = require("../factories/template-factory");
|
|
5
|
+
const theme_enum_1 = require("../core/enums/theme.enum");
|
|
6
|
+
/**
|
|
7
|
+
* TemplateService - Gerencia a criação, renderização e gerenciamento de templates de email
|
|
8
|
+
*
|
|
9
|
+
* Métodos:
|
|
10
|
+
* - createTemplate(themeType, variant, config, options): ITemplate
|
|
11
|
+
* Cria um novo template com as configurações especificadas.
|
|
12
|
+
*
|
|
13
|
+
* - cloneTemplate(template, modifications): ITemplate
|
|
14
|
+
* Cria um template a partir de um template existente (clone).
|
|
15
|
+
*
|
|
16
|
+
* - renderTemplate(template, data, options): Promise<string>
|
|
17
|
+
* Renderiza um template com os dados fornecidos.
|
|
18
|
+
*
|
|
19
|
+
* - previewTemplate(themeType, variant, config, data): Promise<string>
|
|
20
|
+
* Pré-visualiza um template sem enviar email.
|
|
21
|
+
*
|
|
22
|
+
* - getThemeInfo(themeType): object
|
|
23
|
+
* Obtém informações sobre um tema específico.
|
|
24
|
+
*
|
|
25
|
+
* - listThemes(): ThemeType[]
|
|
26
|
+
* Lista todos os temas disponíveis.
|
|
27
|
+
*
|
|
28
|
+
* - getTemplateStats(): object
|
|
29
|
+
* Obtém estatísticas de uso dos templates.
|
|
30
|
+
*
|
|
31
|
+
* - clearCache(themeType?): number
|
|
32
|
+
* Limpa o cache de templates, opcionalmente por tema.
|
|
33
|
+
*
|
|
34
|
+
* - getTemplateHistory(templateId): ITemplate[]
|
|
35
|
+
* Obtém histórico de versões de um template.
|
|
36
|
+
*
|
|
37
|
+
* - restoreTemplateVersion(templateId, versionIndex): ITemplate | null
|
|
38
|
+
* Restaura uma versão anterior do template.
|
|
39
|
+
*
|
|
40
|
+
* Exemplo de uso:
|
|
41
|
+
*
|
|
42
|
+
* const templateService = new TemplateService();
|
|
43
|
+
* const myTemplate = templateService.createTemplate(ThemeType.MODERN, 'light', { header: { show: true } });
|
|
44
|
+
* const html = await templateService.renderTemplate(myTemplate, { username: 'John' });
|
|
45
|
+
* console.log(html);
|
|
46
|
+
*/
|
|
47
|
+
class TemplateService {
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
this.options = options;
|
|
50
|
+
this.templateCache = new Map();
|
|
51
|
+
this.defaultTTL = 3600;
|
|
52
|
+
this.templateHistory = new Map();
|
|
53
|
+
this.options = {
|
|
54
|
+
cache: true,
|
|
55
|
+
cacheTTL: 3600,
|
|
56
|
+
validateConfig: true,
|
|
57
|
+
minify: true,
|
|
58
|
+
preview: false,
|
|
59
|
+
...options
|
|
60
|
+
};
|
|
61
|
+
setInterval(() => this.cleanExpiredCache(), 3600000);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Cria um novo template com as configurações especificadas
|
|
65
|
+
*/
|
|
66
|
+
createTemplate(themeType, variant, config, options) {
|
|
67
|
+
// Validar configuração se necessário
|
|
68
|
+
if (this.options.validateConfig || (options === null || options === void 0 ? void 0 : options.validateConfig)) {
|
|
69
|
+
this.validateTemplateConfig(config);
|
|
70
|
+
}
|
|
71
|
+
// Gerar ID único para o template
|
|
72
|
+
const templateId = this.generateTemplateId(themeType, variant, config);
|
|
73
|
+
// ckeck cache
|
|
74
|
+
if ((this.options.cache || (options === null || options === void 0 ? void 0 : options.cache)) && this.templateCache.has(templateId)) {
|
|
75
|
+
const cached = this.templateCache.get(templateId);
|
|
76
|
+
cached.hits++;
|
|
77
|
+
return cached.template;
|
|
78
|
+
}
|
|
79
|
+
// Criar template
|
|
80
|
+
const template = template_factory_1.TemplateFactory.createTemplate(themeType, variant, config);
|
|
81
|
+
// add métodos adicionais ao template
|
|
82
|
+
const enhancedTemplate = this.enhanceTemplate(template, templateId);
|
|
83
|
+
// store em cache
|
|
84
|
+
if (this.options.cache || (options === null || options === void 0 ? void 0 : options.cache)) {
|
|
85
|
+
const ttl = ((options === null || options === void 0 ? void 0 : options.cacheTTL) || this.options.cacheTTL || this.defaultTTL) * 1000;
|
|
86
|
+
this.templateCache.set(templateId, {
|
|
87
|
+
template: enhancedTemplate,
|
|
88
|
+
createdAt: new Date(),
|
|
89
|
+
expiresAt: new Date(Date.now() + ttl),
|
|
90
|
+
hits: 1
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// reg no histórico
|
|
94
|
+
this.addToHistory(templateId, enhancedTemplate);
|
|
95
|
+
return enhancedTemplate;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Cria um template a partir de um template existente (clone)
|
|
99
|
+
*/
|
|
100
|
+
cloneTemplate(template, modifications) {
|
|
101
|
+
const newConfig = {
|
|
102
|
+
...template.config,
|
|
103
|
+
...modifications
|
|
104
|
+
};
|
|
105
|
+
return this.createTemplate(template.theme, template.variant, newConfig);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Renderiza um template com os dados fornecidos
|
|
109
|
+
*/
|
|
110
|
+
async renderTemplate(template, data, options) {
|
|
111
|
+
try {
|
|
112
|
+
// add metadados para preview se necessário
|
|
113
|
+
const renderData = {
|
|
114
|
+
...data,
|
|
115
|
+
_meta: {
|
|
116
|
+
isPreview: (options === null || options === void 0 ? void 0 : options.preview) || this.options.preview,
|
|
117
|
+
renderDate: new Date().toISOString(),
|
|
118
|
+
templateName: template.name,
|
|
119
|
+
theme: template.theme,
|
|
120
|
+
variant: template.variant
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
// render template
|
|
124
|
+
let html = await template.render(renderData);
|
|
125
|
+
// Minificar HTML se necessário
|
|
126
|
+
if (this.options.minify) {
|
|
127
|
+
html = this.minifyHtml(html);
|
|
128
|
+
}
|
|
129
|
+
console.log(`Template ${template.name} rendered successfully.`);
|
|
130
|
+
console.log(`Render metadata:`, renderData._meta);
|
|
131
|
+
console.log(html);
|
|
132
|
+
return html;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
throw new Error(`Failed to render template: ${error}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Pré-visualiza um template sem enviar email
|
|
140
|
+
*/
|
|
141
|
+
async previewTemplate(themeType, variant, config, data) {
|
|
142
|
+
const template = this.createTemplate(themeType, variant, config, { cache: false });
|
|
143
|
+
return this.renderTemplate(template, data, { preview: true });
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Obtém informações sobre um tema específico
|
|
147
|
+
*/
|
|
148
|
+
getThemeInfo(themeType) {
|
|
149
|
+
const info = template_factory_1.TemplateFactory.getThemeInfo(themeType);
|
|
150
|
+
const theme = template_factory_1.TemplateFactory.getTheme(themeType);
|
|
151
|
+
return {
|
|
152
|
+
...info,
|
|
153
|
+
availableVariants: ['light', 'dark'],
|
|
154
|
+
defaultConfig: this.getDefaultConfigForTheme(themeType, theme)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Lista todos os temas disponíveis
|
|
159
|
+
*/
|
|
160
|
+
listThemes() {
|
|
161
|
+
return template_factory_1.TemplateFactory.listThemes();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Obtém estatísticas de uso dos templates
|
|
165
|
+
*/
|
|
166
|
+
getTemplateStats() {
|
|
167
|
+
const templatesByTheme = {
|
|
168
|
+
[theme_enum_1.ThemeType.SYSTEM]: 0,
|
|
169
|
+
[theme_enum_1.ThemeType.MONOKAI]: 0,
|
|
170
|
+
[theme_enum_1.ThemeType.MODERN]: 0,
|
|
171
|
+
[theme_enum_1.ThemeType.CORPORATE]: 0,
|
|
172
|
+
[theme_enum_1.ThemeType.MINIMAL]: 0
|
|
173
|
+
};
|
|
174
|
+
let totalHits = 0;
|
|
175
|
+
for (const cache of this.templateCache.values()) {
|
|
176
|
+
const theme = cache.template.theme;
|
|
177
|
+
templatesByTheme[theme]++;
|
|
178
|
+
totalHits += cache.hits;
|
|
179
|
+
}
|
|
180
|
+
const totalCached = this.templateCache.size;
|
|
181
|
+
const totalInHistory = this.templateHistory.size;
|
|
182
|
+
return {
|
|
183
|
+
totalTemplates: totalInHistory,
|
|
184
|
+
cachedTemplates: totalCached,
|
|
185
|
+
totalHits,
|
|
186
|
+
templatesByTheme,
|
|
187
|
+
cacheHitRate: totalCached > 0 ? (totalHits / totalCached) * 100 : 0
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Limpa o cache de templates
|
|
192
|
+
*/
|
|
193
|
+
clearCache(themeType) {
|
|
194
|
+
let cleared = 0;
|
|
195
|
+
if (themeType) {
|
|
196
|
+
for (const [id, cache] of this.templateCache.entries()) {
|
|
197
|
+
if (cache.template.theme === themeType) {
|
|
198
|
+
this.templateCache.delete(id);
|
|
199
|
+
cleared++;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
cleared = this.templateCache.size;
|
|
205
|
+
this.templateCache.clear();
|
|
206
|
+
}
|
|
207
|
+
return cleared;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Obtém histórico de versões de um template
|
|
211
|
+
*/
|
|
212
|
+
getTemplateHistory(templateId) {
|
|
213
|
+
return this.templateHistory.get(templateId) || [];
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Restaura uma versão anterior do template
|
|
217
|
+
*/
|
|
218
|
+
restoreTemplateVersion(templateId, versionIndex) {
|
|
219
|
+
const history = this.templateHistory.get(templateId);
|
|
220
|
+
if (!history || versionIndex >= history.length) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
const oldTemplate = history[versionIndex];
|
|
224
|
+
return this.createTemplate(oldTemplate.theme, oldTemplate.variant, oldTemplate.config, { cache: false });
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Valida a configuração do template
|
|
228
|
+
*/
|
|
229
|
+
validateTemplateConfig(config) {
|
|
230
|
+
var _a, _b, _c;
|
|
231
|
+
const errors = [];
|
|
232
|
+
// Validar header
|
|
233
|
+
if (((_a = config.header) === null || _a === void 0 ? void 0 : _a.show) && ((_b = config.header) === null || _b === void 0 ? void 0 : _b.logo)) {
|
|
234
|
+
if (config.header.logo.type === 'image' && !config.header.logo.imageUrl) {
|
|
235
|
+
errors.push('Logo image requires imageUrl');
|
|
236
|
+
}
|
|
237
|
+
if (config.header.logo.type === 'text' && !config.header.logo.text) {
|
|
238
|
+
errors.push('Logo text requires text content');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Validar footer
|
|
242
|
+
if ((_c = config.footer) === null || _c === void 0 ? void 0 : _c.show) {
|
|
243
|
+
if (config.footer.links) {
|
|
244
|
+
for (const link of config.footer.links) {
|
|
245
|
+
if (!link.text || !link.url) {
|
|
246
|
+
errors.push('Footer links require both text and url');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Validar layout
|
|
252
|
+
const validLayouts = ['full', 'minimal'];
|
|
253
|
+
if (config.layout && !validLayouts.includes(config.layout)) {
|
|
254
|
+
errors.push(`Invalid layout: ${config.layout}. Must be one of: ${validLayouts.join(', ')}`);
|
|
255
|
+
}
|
|
256
|
+
// Validar spacing
|
|
257
|
+
const validSpacing = ['compact', 'normal', 'relaxed'];
|
|
258
|
+
if (config.spacing && !validSpacing.includes(config.spacing)) {
|
|
259
|
+
errors.push(`Invalid spacing: ${config.spacing}. Must be one of: ${validSpacing.join(', ')}`);
|
|
260
|
+
}
|
|
261
|
+
// Validar borderRadius
|
|
262
|
+
const validBorderRadius = ['none', 'small', 'medium', 'large'];
|
|
263
|
+
if (config.borderRadius && !validBorderRadius.includes(config.borderRadius)) {
|
|
264
|
+
errors.push(`Invalid borderRadius: ${config.borderRadius}. Must be one of: ${validBorderRadius.join(', ')}`);
|
|
265
|
+
}
|
|
266
|
+
if (errors.length > 0) {
|
|
267
|
+
throw new Error(`Template configuration validation failed:\n${errors.join('\n')}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Gera um ID único para o template baseado na configuração
|
|
272
|
+
*/
|
|
273
|
+
generateTemplateId(themeType, variant, config) {
|
|
274
|
+
const configString = JSON.stringify({
|
|
275
|
+
theme: themeType,
|
|
276
|
+
variant,
|
|
277
|
+
config
|
|
278
|
+
});
|
|
279
|
+
// Hash simples para ID
|
|
280
|
+
let hash = 0;
|
|
281
|
+
for (let i = 0; i < configString.length; i++) {
|
|
282
|
+
const char = configString.charCodeAt(i);
|
|
283
|
+
hash = ((hash << 5) - hash) + char;
|
|
284
|
+
hash = hash & hash;
|
|
285
|
+
}
|
|
286
|
+
return `${themeType}_${variant}_${Math.abs(hash)}`;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Adiciona funcionalidades extras ao template
|
|
290
|
+
*/
|
|
291
|
+
enhanceTemplate(template, templateId) {
|
|
292
|
+
const enhanced = { ...template };
|
|
293
|
+
// add método para obter versão
|
|
294
|
+
enhanced.getVersion = () => {
|
|
295
|
+
const history = this.templateHistory.get(templateId);
|
|
296
|
+
return history ? history.length : 1;
|
|
297
|
+
};
|
|
298
|
+
// add método para obter ID
|
|
299
|
+
enhanced.getId = () => templateId;
|
|
300
|
+
// add método para clonar
|
|
301
|
+
enhanced.clone = (modifications) => {
|
|
302
|
+
return this.cloneTemplate(enhanced, modifications);
|
|
303
|
+
};
|
|
304
|
+
return enhanced;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Adiciona template ao histórico
|
|
308
|
+
*/
|
|
309
|
+
addToHistory(templateId, template) {
|
|
310
|
+
if (!this.templateHistory.has(templateId)) {
|
|
311
|
+
this.templateHistory.set(templateId, []);
|
|
312
|
+
}
|
|
313
|
+
const history = this.templateHistory.get(templateId);
|
|
314
|
+
history.push(template);
|
|
315
|
+
// Manter apenas últimas 10 versões
|
|
316
|
+
if (history.length > 10) {
|
|
317
|
+
history.shift();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Remove templates expirados do cache
|
|
322
|
+
*/
|
|
323
|
+
cleanExpiredCache() {
|
|
324
|
+
const now = Date.now();
|
|
325
|
+
for (const [id, cache] of this.templateCache.entries()) {
|
|
326
|
+
if (cache.expiresAt.getTime() < now) {
|
|
327
|
+
this.templateCache.delete(id);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Minifica o HTML para reduzir tamanho
|
|
333
|
+
*/
|
|
334
|
+
minifyHtml(html) {
|
|
335
|
+
return html
|
|
336
|
+
.replace(/\s+/g, ' ')
|
|
337
|
+
.replace(/>\s+</g, '><')
|
|
338
|
+
.replace(/<!--.*?-->/g, '')
|
|
339
|
+
.trim();
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Obtém configuração padrão para um tema
|
|
343
|
+
*/
|
|
344
|
+
getDefaultConfigForTheme(themeType, theme) {
|
|
345
|
+
const baseConfig = {
|
|
346
|
+
header: {
|
|
347
|
+
show: true,
|
|
348
|
+
logo: {
|
|
349
|
+
type: 'text',
|
|
350
|
+
text: 'MyApp',
|
|
351
|
+
size: 'medium'
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
footer: {
|
|
355
|
+
show: true,
|
|
356
|
+
copyrightText: `© ${new Date().getFullYear()} MyApp. All rights reserved.`
|
|
357
|
+
},
|
|
358
|
+
layout: 'full',
|
|
359
|
+
spacing: 'normal',
|
|
360
|
+
borderRadius: 'medium'
|
|
361
|
+
};
|
|
362
|
+
// Ajustes específicos por tema
|
|
363
|
+
switch (themeType) {
|
|
364
|
+
case theme_enum_1.ThemeType.MONOKAI:
|
|
365
|
+
return {
|
|
366
|
+
...baseConfig,
|
|
367
|
+
borderRadius: 'small',
|
|
368
|
+
spacing: 'normal'
|
|
369
|
+
};
|
|
370
|
+
case theme_enum_1.ThemeType.MODERN:
|
|
371
|
+
return {
|
|
372
|
+
...baseConfig,
|
|
373
|
+
borderRadius: 'large',
|
|
374
|
+
spacing: 'relaxed'
|
|
375
|
+
};
|
|
376
|
+
case theme_enum_1.ThemeType.CORPORATE:
|
|
377
|
+
return {
|
|
378
|
+
...baseConfig,
|
|
379
|
+
borderRadius: 'small',
|
|
380
|
+
spacing: 'normal'
|
|
381
|
+
};
|
|
382
|
+
case theme_enum_1.ThemeType.MINIMAL:
|
|
383
|
+
return {
|
|
384
|
+
...baseConfig,
|
|
385
|
+
borderRadius: 'none',
|
|
386
|
+
spacing: 'relaxed'
|
|
387
|
+
};
|
|
388
|
+
default:
|
|
389
|
+
return baseConfig;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Pré-carrega templates no cache
|
|
394
|
+
*/
|
|
395
|
+
async preloadTemplates(templates) {
|
|
396
|
+
const promises = templates.map(async ({ themeType, variant, config }) => {
|
|
397
|
+
this.createTemplate(themeType, variant, config);
|
|
398
|
+
});
|
|
399
|
+
await Promise.all(promises);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Exporta template para formato JSON
|
|
403
|
+
*/
|
|
404
|
+
exportTemplate(template) {
|
|
405
|
+
var _a, _b;
|
|
406
|
+
return JSON.stringify({
|
|
407
|
+
name: template.name,
|
|
408
|
+
theme: template.theme,
|
|
409
|
+
variant: template.variant,
|
|
410
|
+
config: template.config,
|
|
411
|
+
exportedAt: new Date().toISOString(),
|
|
412
|
+
version: ((_b = (_a = template).getVersion) === null || _b === void 0 ? void 0 : _b.call(_a)) || 1
|
|
413
|
+
}, null, 2);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Importa template de formato JSON
|
|
417
|
+
*/
|
|
418
|
+
importTemplate(jsonData) {
|
|
419
|
+
try {
|
|
420
|
+
const data = JSON.parse(jsonData);
|
|
421
|
+
if (!data.theme || !data.variant || !data.config) {
|
|
422
|
+
throw new Error('Invalid template data: missing required fields');
|
|
423
|
+
}
|
|
424
|
+
return this.createTemplate(data.theme, data.variant, data.config);
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
throw new Error(`Failed to import template: ${error}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Gera um template de exemplo para demonstração
|
|
432
|
+
*/
|
|
433
|
+
generateExampleTemplate(themeType = theme_enum_1.ThemeType.MODERN, variant = 'light') {
|
|
434
|
+
const exampleConfig = {
|
|
435
|
+
header: {
|
|
436
|
+
show: true,
|
|
437
|
+
logo: {
|
|
438
|
+
type: 'text',
|
|
439
|
+
text: 'ExampleApp',
|
|
440
|
+
size: 'medium'
|
|
441
|
+
},
|
|
442
|
+
backgroundColor: variant === 'light' ? '#ffffff' : '#1a1a1a',
|
|
443
|
+
textColor: variant === 'light' ? '#111827' : '#f9fafb'
|
|
444
|
+
},
|
|
445
|
+
footer: {
|
|
446
|
+
show: true,
|
|
447
|
+
links: [
|
|
448
|
+
{ text: 'Privacy Policy', url: 'https://example.com/privacy' },
|
|
449
|
+
{ text: 'Terms of Service', url: 'https://example.com/terms' },
|
|
450
|
+
{ text: 'Contact', url: 'https://example.com/contact' }
|
|
451
|
+
],
|
|
452
|
+
socialLinks: [
|
|
453
|
+
{ platform: 'twitter', url: 'https://twitter.com/example' },
|
|
454
|
+
{ platform: 'github', url: 'https://github.com/example' },
|
|
455
|
+
{ platform: 'linkedin', url: 'https://linkedin.com/company/example' }
|
|
456
|
+
],
|
|
457
|
+
copyrightText: `© ${new Date().getFullYear()} ExampleApp. All rights reserved.`,
|
|
458
|
+
unsubscribeText: 'Unsubscribe',
|
|
459
|
+
backgroundColor: variant === 'light' ? '#f9fafb' : '#111827',
|
|
460
|
+
textColor: variant === 'light' ? '#6b7280' : '#9ca3af'
|
|
461
|
+
},
|
|
462
|
+
layout: 'full',
|
|
463
|
+
spacing: 'normal',
|
|
464
|
+
borderRadius: themeType === theme_enum_1.ThemeType.MINIMAL ? 'none' : 'medium'
|
|
465
|
+
};
|
|
466
|
+
return this.createTemplate(themeType, variant, exampleConfig);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Valida se um template é válido
|
|
470
|
+
*/
|
|
471
|
+
isValidTemplate(template) {
|
|
472
|
+
try {
|
|
473
|
+
// Verificar propriedades obrigatórias
|
|
474
|
+
if (!template || typeof template !== 'object')
|
|
475
|
+
return false;
|
|
476
|
+
if (!template.name || typeof template.name !== 'string')
|
|
477
|
+
return false;
|
|
478
|
+
if (!template.theme || !Object.values(theme_enum_1.ThemeType).includes(template.theme))
|
|
479
|
+
return false;
|
|
480
|
+
if (!template.variant || !['light', 'dark'].includes(template.variant))
|
|
481
|
+
return false;
|
|
482
|
+
if (!template.config || typeof template.config !== 'object')
|
|
483
|
+
return false;
|
|
484
|
+
if (typeof template.render !== 'function')
|
|
485
|
+
return false;
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Obtém estatísticas detalhadas de um template específico
|
|
494
|
+
*/
|
|
495
|
+
getTemplateDetails(templateId) {
|
|
496
|
+
const cacheInfo = this.templateCache.get(templateId) || null;
|
|
497
|
+
const history = this.templateHistory.get(templateId) || [];
|
|
498
|
+
const usageCount = (cacheInfo === null || cacheInfo === void 0 ? void 0 : cacheInfo.hits) || 0;
|
|
499
|
+
return {
|
|
500
|
+
template: (cacheInfo === null || cacheInfo === void 0 ? void 0 : cacheInfo.template) || history[history.length - 1] || null,
|
|
501
|
+
history,
|
|
502
|
+
cacheInfo,
|
|
503
|
+
usageCount
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
exports.TemplateService = TemplateService;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ITemplateConfig } from '../../core/interfaces/template.interface';
|
|
2
|
+
import { ITheme } from '../themes/theme.interface';
|
|
3
|
+
export declare class TemplateBuilder {
|
|
4
|
+
private template;
|
|
5
|
+
private theme;
|
|
6
|
+
private config;
|
|
7
|
+
private variant;
|
|
8
|
+
constructor(theme: ITheme, config: ITemplateConfig, variant: 'light' | 'dark');
|
|
9
|
+
buildHeader(content?: string): this;
|
|
10
|
+
private buildLogo;
|
|
11
|
+
buildBody(content: string): this;
|
|
12
|
+
private formatCorporateContent;
|
|
13
|
+
private formatMinimalContent;
|
|
14
|
+
private highlightCode;
|
|
15
|
+
private applySyntaxHighlighting;
|
|
16
|
+
buildButton(text: string, url: string, variant?: 'primary' | 'secondary'): this;
|
|
17
|
+
buildFooter(): this;
|
|
18
|
+
private buildFooterLinks;
|
|
19
|
+
private buildSocialLinks;
|
|
20
|
+
private getSocialIcon;
|
|
21
|
+
build(): string;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=template-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-builder.d.ts","sourceRoot":"","sources":["../../../src/templates/base/template-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAMnD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAmB;gBAEtB,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM;IAM7E,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAoFnC,OAAO,CAAC,SAAS;IA8EjB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAwEhC,OAAO,CAAC,sBAAsB;IAuB9B,OAAO,CAAC,oBAAoB;IA0B5B,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,uBAAuB;IAuB/B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,GAAG,WAAuB,GAAG,IAAI;IAsG1F,WAAW,IAAI,IAAI;IA0GnB,OAAO,CAAC,gBAAgB;IA8DxB,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,aAAa;IAsBrB,KAAK,IAAI,MAAM;CA6DhB"}
|