@ackplus/nest-dynamic-templates 1.1.1 → 1.1.5
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/package.json +2 -2
- package/src/{index.ts → index.d.ts} +2 -14
- package/src/index.d.ts.map +1 -0
- package/src/index.js +25 -0
- package/src/lib/constant.d.ts +3 -0
- package/src/lib/constant.d.ts.map +1 -0
- package/src/lib/constant.js +5 -0
- package/src/lib/dto/create-template-layout.dto.d.ts +16 -0
- package/src/lib/dto/create-template-layout.dto.d.ts.map +1 -0
- package/src/lib/dto/create-template-layout.dto.js +86 -0
- package/src/lib/dto/create-template.dto.d.ts +18 -0
- package/src/lib/dto/create-template.dto.d.ts.map +1 -0
- package/src/lib/dto/create-template.dto.js +103 -0
- package/src/lib/dto/render-content-template-layout.dto.d.ts +8 -0
- package/src/lib/dto/render-content-template-layout.dto.d.ts.map +1 -0
- package/src/lib/dto/render-content-template-layout.dto.js +40 -0
- package/src/lib/dto/render-content-template.dto.d.ts +9 -0
- package/src/lib/dto/render-content-template.dto.d.ts.map +1 -0
- package/src/lib/dto/render-content-template.dto.js +46 -0
- package/src/lib/dto/render-template-layout.dto.d.ts +11 -0
- package/src/lib/dto/render-template-layout.dto.d.ts.map +1 -0
- package/src/lib/dto/render-template-layout.dto.js +66 -0
- package/src/lib/dto/render-template.dto.d.ts +15 -0
- package/src/lib/dto/render-template.dto.d.ts.map +1 -0
- package/src/lib/dto/render-template.dto.js +90 -0
- package/src/lib/dto/template-filter.dto.d.ts +9 -0
- package/src/lib/dto/template-filter.dto.d.ts.map +1 -0
- package/src/lib/dto/template-filter.dto.js +61 -0
- package/src/lib/dto/template-layout-filter.dto.d.ts +8 -0
- package/src/lib/dto/template-layout-filter.dto.d.ts.map +1 -0
- package/src/lib/dto/template-layout-filter.dto.js +60 -0
- package/src/lib/engines/language/html.engine.d.ts +10 -0
- package/src/lib/engines/language/html.engine.d.ts.map +1 -0
- package/src/lib/engines/language/html.engine.js +80 -0
- package/src/lib/engines/language/{index.ts → index.d.ts} +1 -0
- package/src/lib/engines/language/index.d.ts.map +1 -0
- package/src/lib/engines/language/index.js +11 -0
- package/src/lib/engines/language/markdown.engine.d.ts +10 -0
- package/src/lib/engines/language/markdown.engine.d.ts.map +1 -0
- package/src/lib/engines/language/markdown.engine.js +39 -0
- package/src/lib/engines/language/mjml.engine.d.ts +10 -0
- package/src/lib/engines/language/mjml.engine.d.ts.map +1 -0
- package/src/lib/engines/language/mjml.engine.js +75 -0
- package/src/lib/engines/language/text.engine.d.ts +8 -0
- package/src/lib/engines/language/text.engine.d.ts.map +1 -0
- package/src/lib/engines/language/text.engine.js +15 -0
- package/src/lib/engines/{language-engine.ts → language-engine.d.ts} +2 -7
- package/src/lib/engines/language-engine.d.ts.map +1 -0
- package/src/lib/engines/language-engine.js +6 -0
- package/src/lib/engines/template/ejs.engine.d.ts +11 -0
- package/src/lib/engines/template/ejs.engine.d.ts.map +1 -0
- package/src/lib/engines/template/ejs.engine.js +65 -0
- package/src/lib/engines/template/handlebars.engine.d.ts +11 -0
- package/src/lib/engines/template/handlebars.engine.d.ts.map +1 -0
- package/src/lib/engines/template/handlebars.engine.js +66 -0
- package/src/lib/engines/template/{index.ts → index.d.ts} +1 -0
- package/src/lib/engines/template/index.d.ts.map +1 -0
- package/src/lib/engines/template/index.js +11 -0
- package/src/lib/engines/template/nunjucks.engine.d.ts +17 -0
- package/src/lib/engines/template/nunjucks.engine.d.ts.map +1 -0
- package/src/lib/engines/template/{nunjucks.engine.ts → nunjucks.engine.js} +24 -30
- package/src/lib/engines/template/pug.engine.d.ts +13 -0
- package/src/lib/engines/template/pug.engine.d.ts.map +1 -0
- package/src/lib/engines/template/pug.engine.js +74 -0
- package/src/lib/engines/{template-engine.ts → template-engine.d.ts} +2 -6
- package/src/lib/engines/template-engine.d.ts.map +1 -0
- package/src/lib/engines/template-engine.js +6 -0
- package/src/lib/entities/template-layout.entity.d.ts +21 -0
- package/src/lib/entities/template-layout.entity.d.ts.map +1 -0
- package/src/lib/entities/template-layout.entity.js +120 -0
- package/src/lib/entities/template.entity.d.ts +22 -0
- package/src/lib/entities/template.entity.d.ts.map +1 -0
- package/src/lib/entities/template.entity.js +127 -0
- package/src/lib/errors/template.errors.d.ts +20 -0
- package/src/lib/errors/template.errors.d.ts.map +1 -0
- package/src/lib/errors/{template.errors.ts → template.errors.js} +22 -20
- package/src/lib/interfaces/{module-config.interface.ts → module-config.interface.d.ts} +2 -10
- package/src/lib/interfaces/module-config.interface.d.ts.map +1 -0
- package/src/lib/interfaces/module-config.interface.js +2 -0
- package/src/lib/interfaces/template.types.d.ts +23 -0
- package/src/lib/interfaces/template.types.d.ts.map +1 -0
- package/src/lib/interfaces/template.types.js +24 -0
- package/src/lib/nest-dynamic-templates.module.d.ts +11 -0
- package/src/lib/nest-dynamic-templates.module.d.ts.map +1 -0
- package/src/lib/nest-dynamic-templates.module.js +131 -0
- package/src/lib/services/template-config.service.d.ts +55 -0
- package/src/lib/services/template-config.service.d.ts.map +1 -0
- package/src/lib/services/{template-config.service.ts → template-config.service.js} +32 -43
- package/src/lib/services/template-engine.registry.d.ts +22 -0
- package/src/lib/services/template-engine.registry.d.ts.map +1 -0
- package/src/lib/services/template-engine.registry.js +93 -0
- package/src/lib/services/template-layout.service.d.ts +37 -0
- package/src/lib/services/template-layout.service.d.ts.map +1 -0
- package/src/lib/services/{template-layout.service.ts → template-layout.service.js} +101 -165
- package/src/lib/services/template.service.d.ts +39 -0
- package/src/lib/services/template.service.d.ts.map +1 -0
- package/src/lib/services/{template.service.ts → template.service.js} +137 -199
- package/src/test/helpers.d.ts +5 -0
- package/src/test/helpers.d.ts.map +1 -0
- package/src/test/{helpers.ts → helpers.js} +7 -5
- package/src/test/test-database.config.d.ts +5 -0
- package/src/test/test-database.config.d.ts.map +1 -0
- package/src/test/test-database.config.js +23 -0
- package/src/test/test.setup.d.ts +4 -0
- package/src/test/test.setup.d.ts.map +1 -0
- package/src/test/test.setup.js +30 -0
- package/eslint.config.mjs +0 -22
- package/jest.config.ts +0 -10
- package/project.json +0 -38
- package/src/lib/constant.ts +0 -2
- package/src/lib/dto/create-template-layout.dto.ts +0 -65
- package/src/lib/dto/create-template.dto.ts +0 -80
- package/src/lib/dto/render-content-template-layout.dto.ts +0 -32
- package/src/lib/dto/render-content-template.dto.ts +0 -37
- package/src/lib/dto/render-template-layout.dto.ts +0 -55
- package/src/lib/dto/render-template.dto.ts +0 -74
- package/src/lib/dto/template-filter.dto.ts +0 -52
- package/src/lib/dto/template-layout-filter.dto.ts +0 -51
- package/src/lib/engines/language/html.engine.ts +0 -49
- package/src/lib/engines/language/markdown.engine.ts +0 -37
- package/src/lib/engines/language/mjml.engine.ts +0 -44
- package/src/lib/engines/language/text.engine.ts +0 -15
- package/src/lib/engines/template/ejs.engine.ts +0 -33
- package/src/lib/engines/template/handlebars.engine.ts +0 -35
- package/src/lib/engines/template/pug.engine.ts +0 -43
- package/src/lib/entities/template-layout.entity.ts +0 -99
- package/src/lib/entities/template.entity.ts +0 -105
- package/src/lib/interfaces/template.types.ts +0 -25
- package/src/lib/nest-dynamic-templates.module.ts +0 -143
- package/src/lib/services/template-engine.registry.ts +0 -109
- package/src/test/nunjucks.service.spec.ts +0 -157
- package/src/test/pug.service.spec-temp +0 -254
- package/src/test/template-layout.service.spec.ts +0 -422
- package/src/test/template.service.spec.ts +0 -862
- package/src/test/test-database.config.ts +0 -24
- package/src/test/test-database.d.ts +0 -6
- package/src/test/test.setup.ts +0 -34
- package/src/types/ioredis.d.ts +0 -6
- package/src/types/mjml.d.ts +0 -5
- package/tsconfig.json +0 -17
- package/tsconfig.lib.json +0 -14
- package/tsconfig.spec.json +0 -15
|
@@ -1,70 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@Injectable()
|
|
23
|
-
export class TemplateService {
|
|
24
|
-
constructor(
|
|
25
|
-
@InjectRepository(NestDynamicTemplate)
|
|
26
|
-
private readonly templateRepository: Repository<NestDynamicTemplate>,
|
|
27
|
-
private readonly engineRegistry: TemplateEngineRegistryService,
|
|
28
|
-
private readonly templateLayoutService: TemplateLayoutService,
|
|
29
|
-
) { }
|
|
30
|
-
|
|
31
|
-
async render(renderDto: RenderTemplateDto): Promise<RenderTemplateOutputDTO> {
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
7
|
+
const typeorm_2 = require("typeorm");
|
|
8
|
+
const template_entity_1 = require("../entities/template.entity");
|
|
9
|
+
const template_types_1 = require("../interfaces/template.types");
|
|
10
|
+
const template_layout_service_1 = require("./template-layout.service");
|
|
11
|
+
const template_engine_registry_1 = require("./template-engine.registry");
|
|
12
|
+
const lodash_1 = require("lodash");
|
|
13
|
+
const template_errors_1 = require("../errors/template.errors");
|
|
14
|
+
let TemplateService = class TemplateService {
|
|
15
|
+
constructor(templateRepository, engineRegistry, templateLayoutService) {
|
|
16
|
+
this.templateRepository = templateRepository;
|
|
17
|
+
this.engineRegistry = engineRegistry;
|
|
18
|
+
this.templateLayoutService = templateLayoutService;
|
|
19
|
+
}
|
|
20
|
+
async render(renderDto) {
|
|
32
21
|
const { name, scope, scopeId, locale, context } = renderDto;
|
|
33
|
-
|
|
34
22
|
try {
|
|
35
23
|
// Find template with fallback
|
|
36
24
|
if (!name) {
|
|
37
|
-
throw new BadRequestException('Template name is required');
|
|
25
|
+
throw new common_1.BadRequestException('Template name is required');
|
|
38
26
|
}
|
|
39
27
|
const template = await this.findTemplate(name, scope || 'system', scopeId, locale);
|
|
40
28
|
if (!template) {
|
|
41
|
-
throw new NotFoundException(`Template not found: ${name} in scope ${scope || 'system'}`);
|
|
29
|
+
throw new common_1.NotFoundException(`Template not found: ${name} in scope ${scope || 'system'}`);
|
|
42
30
|
}
|
|
43
|
-
|
|
44
31
|
let content = template.content;
|
|
45
32
|
let subject = template.subject;
|
|
46
|
-
|
|
47
33
|
// Render subject by template engine
|
|
48
34
|
if (template.subject && template.engine) {
|
|
49
35
|
try {
|
|
50
36
|
const subjectEngine = this.engineRegistry.getTemplateEngine(template.engine);
|
|
51
|
-
subject = await subjectEngine.render(template.subject,
|
|
52
|
-
}
|
|
53
|
-
|
|
37
|
+
subject = await subjectEngine.render(template.subject, context || {});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new template_errors_1.TemplateEngineError(template.engine, error);
|
|
54
41
|
}
|
|
55
42
|
}
|
|
56
|
-
|
|
57
43
|
// Render content by template engine
|
|
58
44
|
if (template.engine) {
|
|
59
45
|
try {
|
|
60
|
-
content = await this.renderEngine(template.engine, content,
|
|
61
|
-
}
|
|
62
|
-
|
|
46
|
+
content = await this.renderEngine(template.engine, content, context || {});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw new template_errors_1.TemplateEngineError(template.engine, error);
|
|
63
50
|
}
|
|
64
51
|
}
|
|
65
|
-
|
|
66
52
|
// If template has layout, apply it
|
|
67
|
-
let layout
|
|
53
|
+
let layout;
|
|
68
54
|
if (template.templateLayoutName) {
|
|
69
55
|
try {
|
|
70
56
|
layout = await this.templateLayoutService.render({
|
|
@@ -78,70 +64,66 @@ export class TemplateService {
|
|
|
78
64
|
}
|
|
79
65
|
});
|
|
80
66
|
content = layout.content;
|
|
81
|
-
}
|
|
82
|
-
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new template_errors_1.TemplateLayoutError(template.templateLayoutName, error);
|
|
83
70
|
}
|
|
84
71
|
}
|
|
85
|
-
|
|
86
72
|
// If template has language format, process with language engine
|
|
87
73
|
if (!layout && template.language) {
|
|
88
74
|
try {
|
|
89
|
-
content = await this.renderLanguage(template.language, content,
|
|
90
|
-
}
|
|
91
|
-
|
|
75
|
+
content = await this.renderLanguage(template.language, content, context || {});
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw new template_errors_1.TemplateLanguageError(template.language, error);
|
|
92
79
|
}
|
|
93
80
|
}
|
|
94
|
-
|
|
95
81
|
return {
|
|
96
82
|
subject: subject || '',
|
|
97
83
|
content
|
|
98
84
|
};
|
|
99
|
-
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
100
87
|
// Re-throw known template errors
|
|
101
|
-
if (error instanceof TemplateEngineError ||
|
|
102
|
-
error instanceof TemplateLanguageError ||
|
|
103
|
-
error instanceof TemplateLayoutError ||
|
|
104
|
-
error instanceof NotFoundException) {
|
|
88
|
+
if (error instanceof template_errors_1.TemplateEngineError ||
|
|
89
|
+
error instanceof template_errors_1.TemplateLanguageError ||
|
|
90
|
+
error instanceof template_errors_1.TemplateLayoutError ||
|
|
91
|
+
error instanceof common_1.NotFoundException) {
|
|
105
92
|
throw error;
|
|
106
93
|
}
|
|
107
|
-
|
|
108
94
|
// Wrap unknown errors
|
|
109
|
-
throw new TemplateRenderError('template rendering', error
|
|
95
|
+
throw new template_errors_1.TemplateRenderError('template rendering', error, name);
|
|
110
96
|
}
|
|
111
97
|
}
|
|
112
|
-
|
|
113
|
-
async renderContent(input: RenderContentTemplateDto): Promise<string> {
|
|
98
|
+
async renderContent(input) {
|
|
114
99
|
const { content, language, engine, context, templateLayoutId } = input;
|
|
115
|
-
|
|
116
100
|
try {
|
|
117
101
|
if (!content) {
|
|
118
|
-
throw new BadRequestException('Content is required for rendering');
|
|
102
|
+
throw new common_1.BadRequestException('Content is required for rendering');
|
|
119
103
|
}
|
|
120
|
-
|
|
121
104
|
let renderContent = content;
|
|
122
|
-
|
|
123
105
|
// Step 1: Render template variables first
|
|
124
106
|
try {
|
|
125
|
-
renderContent = await this.renderEngine(engine || TemplateEngineEnum.NUNJUCKS, renderContent,
|
|
126
|
-
}
|
|
127
|
-
|
|
107
|
+
renderContent = await this.renderEngine(engine || template_types_1.TemplateEngineEnum.NUNJUCKS, renderContent, context || {});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw new template_errors_1.TemplateEngineError(engine || template_types_1.TemplateEngineEnum.NUNJUCKS, error);
|
|
128
111
|
}
|
|
129
|
-
|
|
130
112
|
// Step 2: Handle MJML with layouts intelligently
|
|
131
|
-
let templateLayout
|
|
113
|
+
let templateLayout = null;
|
|
132
114
|
if (templateLayoutId) {
|
|
133
115
|
try {
|
|
134
116
|
templateLayout = await this.templateLayoutService.getTemplateLayoutById(templateLayoutId);
|
|
135
117
|
if (!templateLayout) {
|
|
136
|
-
throw new NotFoundException(`Template layout not found with ID: ${templateLayoutId}`);
|
|
118
|
+
throw new common_1.NotFoundException(`Template layout not found with ID: ${templateLayoutId}`);
|
|
137
119
|
}
|
|
138
|
-
}
|
|
139
|
-
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
if (error instanceof common_1.NotFoundException) {
|
|
140
123
|
throw error;
|
|
141
124
|
}
|
|
142
|
-
throw new TemplateContentError('template layout retrieval', error
|
|
125
|
+
throw new template_errors_1.TemplateContentError('template layout retrieval', error);
|
|
143
126
|
}
|
|
144
|
-
|
|
145
127
|
if (templateLayout) {
|
|
146
128
|
try {
|
|
147
129
|
// Step 3: Render the layout content
|
|
@@ -149,179 +131,151 @@ export class TemplateService {
|
|
|
149
131
|
content: templateLayout.content,
|
|
150
132
|
language: language,
|
|
151
133
|
engine: engine,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
134
|
+
context: {
|
|
135
|
+
...(context || {}),
|
|
136
|
+
content: renderContent
|
|
137
|
+
}
|
|
156
138
|
});
|
|
157
|
-
}
|
|
158
|
-
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
throw new template_errors_1.TemplateLayoutError(templateLayout.name, error);
|
|
159
142
|
}
|
|
160
143
|
}
|
|
161
144
|
}
|
|
162
|
-
|
|
163
145
|
// Step 4: Render the content with the language engine
|
|
164
146
|
if ((!templateLayoutId || !templateLayout) && language) {
|
|
165
147
|
try {
|
|
166
|
-
renderContent = await this.renderLanguage(language, renderContent,
|
|
167
|
-
}
|
|
168
|
-
|
|
148
|
+
renderContent = await this.renderLanguage(language, renderContent, context || {});
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
throw new template_errors_1.TemplateLanguageError(language, error);
|
|
169
152
|
}
|
|
170
153
|
}
|
|
171
|
-
|
|
172
154
|
return renderContent;
|
|
173
|
-
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
174
157
|
// Re-throw known template errors
|
|
175
|
-
if (error instanceof TemplateEngineError ||
|
|
176
|
-
error instanceof TemplateLanguageError ||
|
|
177
|
-
error instanceof TemplateLayoutError ||
|
|
178
|
-
error instanceof TemplateContentError ||
|
|
179
|
-
error instanceof NotFoundException ||
|
|
180
|
-
error instanceof BadRequestException) {
|
|
158
|
+
if (error instanceof template_errors_1.TemplateEngineError ||
|
|
159
|
+
error instanceof template_errors_1.TemplateLanguageError ||
|
|
160
|
+
error instanceof template_errors_1.TemplateLayoutError ||
|
|
161
|
+
error instanceof template_errors_1.TemplateContentError ||
|
|
162
|
+
error instanceof common_1.NotFoundException ||
|
|
163
|
+
error instanceof common_1.BadRequestException) {
|
|
181
164
|
throw error;
|
|
182
165
|
}
|
|
183
|
-
|
|
184
166
|
// Wrap unknown errors
|
|
185
|
-
throw new TemplateRenderError('content rendering', error
|
|
167
|
+
throw new template_errors_1.TemplateRenderError('content rendering', error);
|
|
186
168
|
}
|
|
187
169
|
}
|
|
188
|
-
|
|
189
|
-
async renderLanguage(language: TemplateLanguageEnum, content: string, context: Record<string, any>): Promise<string> {
|
|
170
|
+
async renderLanguage(language, content, context) {
|
|
190
171
|
try {
|
|
191
172
|
if (!content) {
|
|
192
|
-
throw new BadRequestException('Content is required for language rendering');
|
|
173
|
+
throw new common_1.BadRequestException('Content is required for language rendering');
|
|
193
174
|
}
|
|
194
|
-
|
|
195
175
|
const languageEngine = this.engineRegistry.getLanguageEngine(language);
|
|
196
176
|
if (!languageEngine) {
|
|
197
|
-
throw new BadRequestException(`Language engine not found for: ${language}`);
|
|
177
|
+
throw new common_1.BadRequestException(`Language engine not found for: ${language}`);
|
|
198
178
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (error instanceof BadRequestException) {
|
|
179
|
+
return await languageEngine.render(content, context || {});
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (error instanceof common_1.BadRequestException) {
|
|
203
183
|
throw error;
|
|
204
184
|
}
|
|
205
|
-
throw new TemplateLanguageError(language, error
|
|
185
|
+
throw new template_errors_1.TemplateLanguageError(language, error);
|
|
206
186
|
}
|
|
207
187
|
}
|
|
208
|
-
|
|
209
|
-
async renderEngine(engine: TemplateEngineEnum, content: string, context: Record<string, any>): Promise<string> {
|
|
188
|
+
async renderEngine(engine, content, context) {
|
|
210
189
|
try {
|
|
211
190
|
if (!content) {
|
|
212
|
-
throw new BadRequestException('Content is required for engine rendering');
|
|
191
|
+
throw new common_1.BadRequestException('Content is required for engine rendering');
|
|
213
192
|
}
|
|
214
|
-
|
|
215
193
|
const templateEngine = this.engineRegistry.getTemplateEngine(engine);
|
|
216
194
|
if (!templateEngine) {
|
|
217
|
-
throw new BadRequestException(`Template engine not found for: ${engine}`);
|
|
195
|
+
throw new common_1.BadRequestException(`Template engine not found for: ${engine}`);
|
|
218
196
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (error instanceof BadRequestException) {
|
|
197
|
+
return await templateEngine.render(content, context || {});
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
if (error instanceof common_1.BadRequestException) {
|
|
223
201
|
throw error;
|
|
224
202
|
}
|
|
225
|
-
throw new TemplateEngineError(engine, error
|
|
203
|
+
throw new template_errors_1.TemplateEngineError(engine, error);
|
|
226
204
|
}
|
|
227
205
|
}
|
|
228
|
-
|
|
229
206
|
/**
|
|
230
207
|
* Get all templates, with scoped templates taking precedence over system templates
|
|
231
208
|
*/
|
|
232
|
-
async getTemplates(filter
|
|
233
|
-
const {
|
|
234
|
-
scope,
|
|
235
|
-
scopeId,
|
|
236
|
-
type,
|
|
237
|
-
locale,
|
|
238
|
-
excludeNames = [],
|
|
239
|
-
} = filter;
|
|
240
|
-
|
|
241
|
-
|
|
209
|
+
async getTemplates(filter = {}) {
|
|
210
|
+
const { scope, scopeId, type, locale, excludeNames = [], } = filter;
|
|
242
211
|
// Build the where clause
|
|
243
|
-
const where
|
|
244
|
-
if (type)
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
|
|
212
|
+
const where = {};
|
|
213
|
+
if (type)
|
|
214
|
+
where.type = type;
|
|
215
|
+
if (locale)
|
|
216
|
+
where.locale = locale;
|
|
217
|
+
if (excludeNames.length > 0)
|
|
218
|
+
where.name = (0, typeorm_2.Not)((0, typeorm_2.In)(excludeNames));
|
|
248
219
|
const systemTemplates = await this.templateRepository.find({
|
|
249
220
|
where: {
|
|
250
221
|
...where,
|
|
251
222
|
scope: 'system',
|
|
252
|
-
scopeId: IsNull(),
|
|
223
|
+
scopeId: (0, typeorm_2.IsNull)(),
|
|
253
224
|
},
|
|
254
225
|
});
|
|
255
|
-
|
|
256
226
|
if (scope === 'system') {
|
|
257
227
|
return systemTemplates;
|
|
258
228
|
}
|
|
259
|
-
|
|
260
229
|
// First get all templates matching the filters
|
|
261
230
|
const templates = await this.templateRepository.find({
|
|
262
231
|
where: {
|
|
263
232
|
...where,
|
|
264
|
-
scope: Equal(scope),
|
|
265
|
-
scopeId: scopeId
|
|
233
|
+
scope: (0, typeorm_2.Equal)(scope),
|
|
234
|
+
scopeId: scopeId,
|
|
266
235
|
},
|
|
267
236
|
order: {
|
|
268
237
|
createdAt: 'DESC',
|
|
269
238
|
},
|
|
270
239
|
});
|
|
271
|
-
|
|
272
240
|
// Create a map to store unique templates by name+type
|
|
273
|
-
const templateMap = new Map
|
|
274
|
-
|
|
241
|
+
const templateMap = new Map();
|
|
275
242
|
for (const template of systemTemplates) {
|
|
276
243
|
const key = `${template.type}/${template.name}/${template.locale}`;
|
|
277
244
|
templateMap.set(key, template);
|
|
278
245
|
}
|
|
279
|
-
|
|
280
246
|
for (const template of templates) {
|
|
281
247
|
const key = `${template.type}/${template.name}/${template.locale}`;
|
|
282
248
|
templateMap.set(key, template);
|
|
283
249
|
}
|
|
284
|
-
|
|
285
250
|
// Convert map values back to array
|
|
286
251
|
return Array.from(templateMap.values());
|
|
287
252
|
}
|
|
288
|
-
|
|
289
|
-
async getTemplateById(id: string): Promise<NestDynamicTemplate | null> {
|
|
253
|
+
async getTemplateById(id) {
|
|
290
254
|
return this.templateRepository.findOne({
|
|
291
255
|
where: { id },
|
|
292
256
|
});
|
|
293
257
|
}
|
|
294
|
-
|
|
295
|
-
async findTemplate(
|
|
296
|
-
name: string,
|
|
297
|
-
scope?: string,
|
|
298
|
-
scopeId?: string,
|
|
299
|
-
locale?: string
|
|
300
|
-
): Promise<NestDynamicTemplate | null> {
|
|
258
|
+
async findTemplate(name, scope, scopeId, locale) {
|
|
301
259
|
// Try to find template in the following order:
|
|
302
260
|
// 1. Scoped template with locale
|
|
303
261
|
// 2. Scoped template without locale
|
|
304
262
|
// 3. System template with locale
|
|
305
263
|
// 4. System template without locale
|
|
306
|
-
|
|
307
264
|
const locales = (locale ? [locale, 'en'] : ['en']).filter(Boolean);
|
|
308
|
-
|
|
309
265
|
// First try to find in the specified scope
|
|
310
266
|
for (const currentLocale of locales) {
|
|
311
267
|
const template = await this.templateRepository.findOne({
|
|
312
268
|
where: {
|
|
313
269
|
name,
|
|
314
270
|
scope,
|
|
315
|
-
scopeId: scope === 'system' ? IsNull() : Equal(scopeId),
|
|
271
|
+
scopeId: scope === 'system' ? (0, typeorm_2.IsNull)() : (0, typeorm_2.Equal)(scopeId),
|
|
316
272
|
locale: currentLocale,
|
|
317
273
|
}
|
|
318
274
|
});
|
|
319
|
-
|
|
320
275
|
if (template) {
|
|
321
276
|
return template;
|
|
322
277
|
}
|
|
323
278
|
}
|
|
324
|
-
|
|
325
279
|
// If not found and not already in system scope, try system scope
|
|
326
280
|
if (scope !== 'system') {
|
|
327
281
|
for (const currentLocale of locales) {
|
|
@@ -329,79 +283,68 @@ export class TemplateService {
|
|
|
329
283
|
where: {
|
|
330
284
|
name,
|
|
331
285
|
scope: 'system',
|
|
332
|
-
scopeId: IsNull(),
|
|
286
|
+
scopeId: (0, typeorm_2.IsNull)(),
|
|
333
287
|
locale: currentLocale,
|
|
334
288
|
}
|
|
335
289
|
});
|
|
336
|
-
|
|
337
290
|
if (template) {
|
|
338
291
|
return template;
|
|
339
292
|
}
|
|
340
293
|
}
|
|
341
294
|
}
|
|
342
|
-
|
|
343
295
|
return null;
|
|
344
296
|
}
|
|
345
|
-
|
|
346
297
|
/**
|
|
347
298
|
* Create a system template. Only system templates can be created directly.
|
|
348
299
|
*/
|
|
349
|
-
async createTemplate(data
|
|
300
|
+
async createTemplate(data) {
|
|
350
301
|
// Ensure this is a system template
|
|
351
302
|
if (data.scope !== 'system') {
|
|
352
|
-
throw new ForbiddenException('Only system templates can be created directly');
|
|
303
|
+
throw new common_1.ForbiddenException('Only system templates can be created directly');
|
|
353
304
|
}
|
|
354
|
-
|
|
355
305
|
// Check if template already exists
|
|
356
306
|
const existingTemplate = await this.templateRepository.findOne({
|
|
357
307
|
where: {
|
|
358
308
|
name: data.name,
|
|
359
309
|
scope: 'system',
|
|
360
|
-
scopeId: IsNull(),
|
|
310
|
+
scopeId: (0, typeorm_2.IsNull)(),
|
|
361
311
|
locale: data.locale,
|
|
362
312
|
},
|
|
363
313
|
});
|
|
364
|
-
|
|
365
314
|
if (existingTemplate) {
|
|
366
|
-
throw new ConflictException(`System template already exists`);
|
|
315
|
+
throw new common_1.ConflictException(`System template already exists`);
|
|
367
316
|
}
|
|
368
|
-
|
|
369
317
|
const template = this.templateRepository.create({
|
|
370
318
|
...data,
|
|
371
319
|
scopeId: undefined, // Ensure system templates have no scopeId
|
|
372
320
|
});
|
|
373
|
-
|
|
374
321
|
return this.templateRepository.save(template);
|
|
375
322
|
}
|
|
376
|
-
|
|
377
|
-
async overwriteSystemTemplate(templateId: string, updates: Partial<CreateTemplateDto>): Promise<NestDynamicTemplate> {
|
|
323
|
+
async overwriteSystemTemplate(templateId, updates) {
|
|
378
324
|
let template = await this.templateRepository.findOne({
|
|
379
325
|
where: { id: templateId },
|
|
380
326
|
});
|
|
381
|
-
|
|
382
327
|
if (!template) {
|
|
383
|
-
throw new NotFoundException(`Template not found: ${templateId}`);
|
|
328
|
+
throw new common_1.NotFoundException(`Template not found: ${templateId}`);
|
|
384
329
|
}
|
|
385
|
-
|
|
386
330
|
if (template.scope === 'system') {
|
|
387
331
|
if (!updates.scope) {
|
|
388
|
-
throw new BadRequestException('Scope is required when overwriting system template');
|
|
332
|
+
throw new common_1.BadRequestException('Scope is required when overwriting system template');
|
|
389
333
|
}
|
|
390
|
-
|
|
391
334
|
// Check if template already exists in target scope
|
|
392
335
|
const existingTemplate = await this.templateRepository.findOne({
|
|
393
336
|
where: {
|
|
394
337
|
name: template.name,
|
|
395
338
|
locale: template.locale,
|
|
396
339
|
scope: updates.scope,
|
|
397
|
-
scopeId: updates.scopeId
|
|
340
|
+
scopeId: updates.scopeId,
|
|
398
341
|
},
|
|
399
342
|
});
|
|
400
|
-
|
|
401
343
|
if (existingTemplate) {
|
|
402
344
|
// Update existing template in target scope
|
|
403
345
|
template = existingTemplate;
|
|
404
|
-
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
405
348
|
// Create new template in target scope
|
|
406
349
|
const newTemplate = this.templateRepository.create({
|
|
407
350
|
...template,
|
|
@@ -414,63 +357,58 @@ export class TemplateService {
|
|
|
414
357
|
template = newTemplate;
|
|
415
358
|
}
|
|
416
359
|
}
|
|
417
|
-
updates = omit(updates, ['name', 'id', 'createdAt', 'updatedAt']);
|
|
418
|
-
|
|
360
|
+
updates = (0, lodash_1.omit)(updates, ['name', 'id', 'createdAt', 'updatedAt']);
|
|
419
361
|
template = this.templateRepository.merge(template, updates);
|
|
420
362
|
await this.templateRepository.save(template);
|
|
421
363
|
return template;
|
|
422
364
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
365
|
/**
|
|
426
366
|
* Update a template
|
|
427
367
|
*/
|
|
428
|
-
async updateTemplate(
|
|
429
|
-
id: string,
|
|
430
|
-
updates: Partial<CreateTemplateDto>,
|
|
431
|
-
canUpdateSystemTemplate: boolean = false,
|
|
432
|
-
): Promise<NestDynamicTemplate> {
|
|
368
|
+
async updateTemplate(id, updates, canUpdateSystemTemplate = false) {
|
|
433
369
|
// Find the template
|
|
434
370
|
let template = await this.templateRepository.findOne({
|
|
435
371
|
where: { id },
|
|
436
372
|
});
|
|
437
|
-
|
|
438
373
|
if (!template) {
|
|
439
|
-
throw new NotFoundException(`Template not found: ${id}`);
|
|
374
|
+
throw new common_1.NotFoundException(`Template not found: ${id}`);
|
|
440
375
|
}
|
|
441
|
-
|
|
442
376
|
// If it's a system template and we can't update it, try to overwrite it
|
|
443
377
|
if (template.scope === 'system' && !canUpdateSystemTemplate) {
|
|
444
378
|
if (updates.scope) {
|
|
445
379
|
// Otherwise, allow overwriting to custom scope
|
|
446
380
|
return this.overwriteSystemTemplate(id, updates);
|
|
447
|
-
}
|
|
448
|
-
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
throw new common_1.ForbiddenException('Cannot update system templates');
|
|
449
384
|
}
|
|
450
385
|
}
|
|
451
|
-
|
|
452
386
|
// For regular updates
|
|
453
387
|
template = this.templateRepository.merge(template, updates);
|
|
454
388
|
return this.templateRepository.save(template);
|
|
455
389
|
}
|
|
456
|
-
|
|
457
390
|
/**
|
|
458
391
|
* Delete a scoped template
|
|
459
392
|
*/
|
|
460
|
-
async deleteTemplate(id
|
|
393
|
+
async deleteTemplate(id, canDeleteSystemTemplate = false) {
|
|
461
394
|
const template = await this.templateRepository.findOne({
|
|
462
395
|
where: { id },
|
|
463
396
|
});
|
|
464
|
-
|
|
465
397
|
if (!template) {
|
|
466
398
|
throw new Error(`Template not found: ${id}`);
|
|
467
399
|
}
|
|
468
|
-
|
|
469
400
|
// Prevent deleting system templates
|
|
470
401
|
if (template.scope === 'system' && !canDeleteSystemTemplate) {
|
|
471
|
-
throw new ForbiddenException('Cannot delete system templates');
|
|
402
|
+
throw new common_1.ForbiddenException('Cannot delete system templates');
|
|
472
403
|
}
|
|
473
|
-
|
|
474
404
|
await this.templateRepository.remove(template);
|
|
475
405
|
}
|
|
476
|
-
}
|
|
406
|
+
};
|
|
407
|
+
exports.TemplateService = TemplateService;
|
|
408
|
+
exports.TemplateService = TemplateService = tslib_1.__decorate([
|
|
409
|
+
(0, common_1.Injectable)(),
|
|
410
|
+
tslib_1.__param(0, (0, typeorm_1.InjectRepository)(template_entity_1.NestDynamicTemplate)),
|
|
411
|
+
tslib_1.__metadata("design:paramtypes", [typeorm_2.Repository,
|
|
412
|
+
template_engine_registry_1.TemplateEngineRegistryService,
|
|
413
|
+
template_layout_service_1.TemplateLayoutService])
|
|
414
|
+
], TemplateService);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-dynamic-templates/src/test/helpers.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;uBACH,IAAI,UAAU,MAAM;6BAoBd,MAAM,YAAY,MAAM;CASpD,CAAA"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.engineFilters = void 0;
|
|
4
|
+
exports.engineFilters = {
|
|
5
|
+
formatDate: (date, format) => {
|
|
3
6
|
const year = date.getFullYear();
|
|
4
7
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
5
8
|
const day = String(date.getDate()).padStart(2, '0');
|
|
6
|
-
|
|
7
9
|
switch (format) {
|
|
8
10
|
case 'YYYY-MM-DD':
|
|
9
11
|
return `${year}-${month}-${day}`;
|
|
@@ -19,7 +21,7 @@ export const engineFilters = {
|
|
|
19
21
|
return `${year}-${month}-${day}`;
|
|
20
22
|
}
|
|
21
23
|
},
|
|
22
|
-
formatCurrency: (amount
|
|
24
|
+
formatCurrency: (amount, currency) => {
|
|
23
25
|
const formatter = new Intl.NumberFormat('en-US', {
|
|
24
26
|
style: 'currency',
|
|
25
27
|
currency: currency,
|
|
@@ -28,4 +30,4 @@ export const engineFilters = {
|
|
|
28
30
|
});
|
|
29
31
|
return formatter.format(amount);
|
|
30
32
|
}
|
|
31
|
-
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
|
2
|
+
import { RedisModuleOptions } from '@nestjs-modules/ioredis';
|
|
3
|
+
export declare const testDatabaseConfig: TypeOrmModuleOptions;
|
|
4
|
+
export declare const testRedisConfig: RedisModuleOptions;
|
|
5
|
+
//# sourceMappingURL=test-database.config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-database.config.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-dynamic-templates/src/test/test-database.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAI7D,eAAO,MAAM,kBAAkB,EAAE,oBAOhC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,kBAS7B,CAAC"}
|