@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.
Files changed (142) hide show
  1. package/package.json +2 -2
  2. package/src/{index.ts → index.d.ts} +2 -14
  3. package/src/index.d.ts.map +1 -0
  4. package/src/index.js +25 -0
  5. package/src/lib/constant.d.ts +3 -0
  6. package/src/lib/constant.d.ts.map +1 -0
  7. package/src/lib/constant.js +5 -0
  8. package/src/lib/dto/create-template-layout.dto.d.ts +16 -0
  9. package/src/lib/dto/create-template-layout.dto.d.ts.map +1 -0
  10. package/src/lib/dto/create-template-layout.dto.js +86 -0
  11. package/src/lib/dto/create-template.dto.d.ts +18 -0
  12. package/src/lib/dto/create-template.dto.d.ts.map +1 -0
  13. package/src/lib/dto/create-template.dto.js +103 -0
  14. package/src/lib/dto/render-content-template-layout.dto.d.ts +8 -0
  15. package/src/lib/dto/render-content-template-layout.dto.d.ts.map +1 -0
  16. package/src/lib/dto/render-content-template-layout.dto.js +40 -0
  17. package/src/lib/dto/render-content-template.dto.d.ts +9 -0
  18. package/src/lib/dto/render-content-template.dto.d.ts.map +1 -0
  19. package/src/lib/dto/render-content-template.dto.js +46 -0
  20. package/src/lib/dto/render-template-layout.dto.d.ts +11 -0
  21. package/src/lib/dto/render-template-layout.dto.d.ts.map +1 -0
  22. package/src/lib/dto/render-template-layout.dto.js +66 -0
  23. package/src/lib/dto/render-template.dto.d.ts +15 -0
  24. package/src/lib/dto/render-template.dto.d.ts.map +1 -0
  25. package/src/lib/dto/render-template.dto.js +90 -0
  26. package/src/lib/dto/template-filter.dto.d.ts +9 -0
  27. package/src/lib/dto/template-filter.dto.d.ts.map +1 -0
  28. package/src/lib/dto/template-filter.dto.js +61 -0
  29. package/src/lib/dto/template-layout-filter.dto.d.ts +8 -0
  30. package/src/lib/dto/template-layout-filter.dto.d.ts.map +1 -0
  31. package/src/lib/dto/template-layout-filter.dto.js +60 -0
  32. package/src/lib/engines/language/html.engine.d.ts +10 -0
  33. package/src/lib/engines/language/html.engine.d.ts.map +1 -0
  34. package/src/lib/engines/language/html.engine.js +80 -0
  35. package/src/lib/engines/language/{index.ts → index.d.ts} +1 -0
  36. package/src/lib/engines/language/index.d.ts.map +1 -0
  37. package/src/lib/engines/language/index.js +11 -0
  38. package/src/lib/engines/language/markdown.engine.d.ts +10 -0
  39. package/src/lib/engines/language/markdown.engine.d.ts.map +1 -0
  40. package/src/lib/engines/language/markdown.engine.js +39 -0
  41. package/src/lib/engines/language/mjml.engine.d.ts +10 -0
  42. package/src/lib/engines/language/mjml.engine.d.ts.map +1 -0
  43. package/src/lib/engines/language/mjml.engine.js +75 -0
  44. package/src/lib/engines/language/text.engine.d.ts +8 -0
  45. package/src/lib/engines/language/text.engine.d.ts.map +1 -0
  46. package/src/lib/engines/language/text.engine.js +15 -0
  47. package/src/lib/engines/{language-engine.ts → language-engine.d.ts} +2 -7
  48. package/src/lib/engines/language-engine.d.ts.map +1 -0
  49. package/src/lib/engines/language-engine.js +6 -0
  50. package/src/lib/engines/template/ejs.engine.d.ts +11 -0
  51. package/src/lib/engines/template/ejs.engine.d.ts.map +1 -0
  52. package/src/lib/engines/template/ejs.engine.js +65 -0
  53. package/src/lib/engines/template/handlebars.engine.d.ts +11 -0
  54. package/src/lib/engines/template/handlebars.engine.d.ts.map +1 -0
  55. package/src/lib/engines/template/handlebars.engine.js +66 -0
  56. package/src/lib/engines/template/{index.ts → index.d.ts} +1 -0
  57. package/src/lib/engines/template/index.d.ts.map +1 -0
  58. package/src/lib/engines/template/index.js +11 -0
  59. package/src/lib/engines/template/nunjucks.engine.d.ts +17 -0
  60. package/src/lib/engines/template/nunjucks.engine.d.ts.map +1 -0
  61. package/src/lib/engines/template/{nunjucks.engine.ts → nunjucks.engine.js} +24 -30
  62. package/src/lib/engines/template/pug.engine.d.ts +13 -0
  63. package/src/lib/engines/template/pug.engine.d.ts.map +1 -0
  64. package/src/lib/engines/template/pug.engine.js +74 -0
  65. package/src/lib/engines/{template-engine.ts → template-engine.d.ts} +2 -6
  66. package/src/lib/engines/template-engine.d.ts.map +1 -0
  67. package/src/lib/engines/template-engine.js +6 -0
  68. package/src/lib/entities/template-layout.entity.d.ts +21 -0
  69. package/src/lib/entities/template-layout.entity.d.ts.map +1 -0
  70. package/src/lib/entities/template-layout.entity.js +120 -0
  71. package/src/lib/entities/template.entity.d.ts +22 -0
  72. package/src/lib/entities/template.entity.d.ts.map +1 -0
  73. package/src/lib/entities/template.entity.js +127 -0
  74. package/src/lib/errors/template.errors.d.ts +20 -0
  75. package/src/lib/errors/template.errors.d.ts.map +1 -0
  76. package/src/lib/errors/{template.errors.ts → template.errors.js} +22 -20
  77. package/src/lib/interfaces/{module-config.interface.ts → module-config.interface.d.ts} +2 -10
  78. package/src/lib/interfaces/module-config.interface.d.ts.map +1 -0
  79. package/src/lib/interfaces/module-config.interface.js +2 -0
  80. package/src/lib/interfaces/template.types.d.ts +23 -0
  81. package/src/lib/interfaces/template.types.d.ts.map +1 -0
  82. package/src/lib/interfaces/template.types.js +24 -0
  83. package/src/lib/nest-dynamic-templates.module.d.ts +11 -0
  84. package/src/lib/nest-dynamic-templates.module.d.ts.map +1 -0
  85. package/src/lib/nest-dynamic-templates.module.js +131 -0
  86. package/src/lib/services/template-config.service.d.ts +55 -0
  87. package/src/lib/services/template-config.service.d.ts.map +1 -0
  88. package/src/lib/services/{template-config.service.ts → template-config.service.js} +32 -43
  89. package/src/lib/services/template-engine.registry.d.ts +22 -0
  90. package/src/lib/services/template-engine.registry.d.ts.map +1 -0
  91. package/src/lib/services/template-engine.registry.js +93 -0
  92. package/src/lib/services/template-layout.service.d.ts +37 -0
  93. package/src/lib/services/template-layout.service.d.ts.map +1 -0
  94. package/src/lib/services/{template-layout.service.ts → template-layout.service.js} +101 -165
  95. package/src/lib/services/template.service.d.ts +39 -0
  96. package/src/lib/services/template.service.d.ts.map +1 -0
  97. package/src/lib/services/{template.service.ts → template.service.js} +137 -199
  98. package/src/test/helpers.d.ts +5 -0
  99. package/src/test/helpers.d.ts.map +1 -0
  100. package/src/test/{helpers.ts → helpers.js} +7 -5
  101. package/src/test/test-database.config.d.ts +5 -0
  102. package/src/test/test-database.config.d.ts.map +1 -0
  103. package/src/test/test-database.config.js +23 -0
  104. package/src/test/test.setup.d.ts +4 -0
  105. package/src/test/test.setup.d.ts.map +1 -0
  106. package/src/test/test.setup.js +30 -0
  107. package/eslint.config.mjs +0 -22
  108. package/jest.config.ts +0 -10
  109. package/project.json +0 -38
  110. package/src/lib/constant.ts +0 -2
  111. package/src/lib/dto/create-template-layout.dto.ts +0 -65
  112. package/src/lib/dto/create-template.dto.ts +0 -80
  113. package/src/lib/dto/render-content-template-layout.dto.ts +0 -32
  114. package/src/lib/dto/render-content-template.dto.ts +0 -37
  115. package/src/lib/dto/render-template-layout.dto.ts +0 -55
  116. package/src/lib/dto/render-template.dto.ts +0 -74
  117. package/src/lib/dto/template-filter.dto.ts +0 -52
  118. package/src/lib/dto/template-layout-filter.dto.ts +0 -51
  119. package/src/lib/engines/language/html.engine.ts +0 -49
  120. package/src/lib/engines/language/markdown.engine.ts +0 -37
  121. package/src/lib/engines/language/mjml.engine.ts +0 -44
  122. package/src/lib/engines/language/text.engine.ts +0 -15
  123. package/src/lib/engines/template/ejs.engine.ts +0 -33
  124. package/src/lib/engines/template/handlebars.engine.ts +0 -35
  125. package/src/lib/engines/template/pug.engine.ts +0 -43
  126. package/src/lib/entities/template-layout.entity.ts +0 -99
  127. package/src/lib/entities/template.entity.ts +0 -105
  128. package/src/lib/interfaces/template.types.ts +0 -25
  129. package/src/lib/nest-dynamic-templates.module.ts +0 -143
  130. package/src/lib/services/template-engine.registry.ts +0 -109
  131. package/src/test/nunjucks.service.spec.ts +0 -157
  132. package/src/test/pug.service.spec-temp +0 -254
  133. package/src/test/template-layout.service.spec.ts +0 -422
  134. package/src/test/template.service.spec.ts +0 -862
  135. package/src/test/test-database.config.ts +0 -24
  136. package/src/test/test-database.d.ts +0 -6
  137. package/src/test/test.setup.ts +0 -34
  138. package/src/types/ioredis.d.ts +0 -6
  139. package/src/types/mjml.d.ts +0 -5
  140. package/tsconfig.json +0 -17
  141. package/tsconfig.lib.json +0 -14
  142. package/tsconfig.spec.json +0 -15
@@ -1,44 +0,0 @@
1
- import { TemplateLanguageEnum } from '../../interfaces/template.types';
2
- import { LanguageEngine } from '../language-engine';
3
-
4
- export class MjmlEngine extends LanguageEngine {
5
-
6
- static override engineName = TemplateLanguageEnum.MJML;
7
-
8
- private readonly options: any = {};
9
-
10
- constructor(options: any = {}) {
11
- super();
12
- this.options = options;
13
- }
14
-
15
- async render(content: string): Promise<string> {
16
- try {
17
- const mjml2html = (await import('mjml')).default;
18
- const result = mjml2html(content, {
19
- ...this.options,
20
- validationLevel: 'strict',
21
- });
22
-
23
- if (result.errors && result.errors.length > 0) {
24
- throw new Error(`MJML validation errors: ${result.errors.join(', ')}`);
25
- }
26
-
27
- return result.html;
28
- } catch (error: any) {
29
- throw new Error(`MJML rendering error: ${error?.message || 'Unknown error'}`);
30
- }
31
- }
32
-
33
- async validate(content: string): Promise<boolean> {
34
- try {
35
- const mjml2html = (await import('mjml')).default;
36
- const result = mjml2html(content, {
37
- validationLevel: 'strict',
38
- });
39
- return result.errors.length === 0;
40
- } catch (error) {
41
- return false;
42
- }
43
- }
44
- }
@@ -1,15 +0,0 @@
1
- import { TemplateLanguageEnum } from '../../interfaces/template.types';
2
- import { LanguageEngine } from '../language-engine';
3
-
4
- export class TextEngine extends LanguageEngine {
5
-
6
- static override engineName = TemplateLanguageEnum.TEXT;
7
-
8
- async render(content: string): Promise<string> {
9
- return content;
10
- }
11
-
12
- async validate(content: string): Promise<boolean> {
13
- return true;
14
- }
15
- }
@@ -1,33 +0,0 @@
1
- import { TemplateEngine } from '../template-engine';
2
- import { TemplateEngineEnum } from '../../interfaces/template.types';
3
- import { EngineOptions } from '../../interfaces/module-config.interface';
4
- export class EjsEngine extends TemplateEngine {
5
-
6
- static override engineName = TemplateEngineEnum.EJS;
7
-
8
- private options: ejs.Options;
9
-
10
- constructor(options?: EngineOptions<ejs.Options>) {
11
- super();
12
- this.options = options || {};
13
- }
14
-
15
- async render(content: string, data?: Record<string, any>): Promise<string> {
16
- try {
17
- const ejs = await import('ejs');
18
- return ejs.render(content, data, this.options);
19
- } catch (error: any) {
20
- throw new Error(`Failed to render EJS template: ${error?.message || 'Unknown error'}`);
21
- }
22
- }
23
-
24
- async validate(content: string): Promise<boolean> {
25
- try {
26
- const ejs = await import('ejs');
27
- ejs.compile(content, this.options);
28
- return true;
29
- } catch (error) {
30
- return false;
31
- }
32
- }
33
- }
@@ -1,35 +0,0 @@
1
- import { TemplateEngineEnum } from '../../interfaces/template.types';
2
- import { TemplateEngine } from '../template-engine';
3
- import { EngineOptions } from '../../interfaces/module-config.interface';
4
-
5
- export class HandlebarsEngine extends TemplateEngine {
6
-
7
- static override engineName = TemplateEngineEnum.HANDLEBARS;
8
-
9
- private options: Handlebars.ParseOptions;
10
-
11
- constructor(options?: EngineOptions<Handlebars.ParseOptions>) {
12
- super();
13
- this.options = options || {};
14
- }
15
-
16
- async render(content: string, data?: Record<string, any>): Promise<string> {
17
- try {
18
- const Handlebars = await import('handlebars');
19
- const template = Handlebars.compile(content, this.options);
20
- return template(data);
21
- } catch (error: any) {
22
- throw new Error(`Failed to render Handlebars template: ${error?.message || 'Unknown error'}`);
23
- }
24
- }
25
-
26
- async validate(content: string): Promise<boolean> {
27
- try {
28
- const Handlebars = await import('handlebars');
29
- Handlebars.precompile(content, this.options);
30
- return true;
31
- } catch (error) {
32
- return false;
33
- }
34
- }
35
- }
@@ -1,43 +0,0 @@
1
- import type { Options } from 'pug';
2
- import { TemplateEngineEnum } from '../../interfaces/template.types';
3
- import { TemplateEngine } from '../template-engine';
4
- import { CustomEngineOptions, EngineOptions } from '../../interfaces/module-config.interface';
5
-
6
- export class PugEngine extends TemplateEngine {
7
-
8
- static override engineName = TemplateEngineEnum.PUG;
9
-
10
- private options: Options;
11
-
12
- constructor(options?: EngineOptions<Options>, private customOptions?: CustomEngineOptions) {
13
- super();
14
- this.options = options || {};
15
- }
16
-
17
- async render(content: string, data: any): Promise<string> {
18
- try {
19
- const pug = await import('pug');
20
- const template = pug.compile(content, {
21
- ...this.options,
22
- filters: this.customOptions?.filters
23
- });
24
- return template({
25
- ...this.options.filters,
26
- ...data,
27
- ...this.customOptions?.filters
28
- });
29
- } catch (error: any) {
30
- throw new Error(`Failed to render Pug template: ${error?.message || 'Unknown error'}`);
31
- }
32
- }
33
-
34
- async validate(content: string): Promise<boolean> {
35
- try {
36
- const pug = await import('pug');
37
- pug.compile(content, this.options);
38
- return true;
39
- } catch (error) {
40
- return false;
41
- }
42
- }
43
- }
@@ -1,99 +0,0 @@
1
- import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, Index, BaseEntity } from 'typeorm';
2
- import { IsBoolean, IsEnum, IsNotEmpty, IsOptional, IsString, Matches } from 'class-validator';
3
- import { TemplateEngineEnum, TemplateTypeEnum, TemplateLanguageEnum } from '../interfaces/template.types';
4
- import { ApiProperty } from '@nestjs/swagger';
5
-
6
-
7
- @Entity('nest_dynamic_template_layouts')
8
- @Index(['name', 'scope', 'scopeId', 'locale'], { unique: true })
9
- export class NestDynamicTemplateLayout extends BaseEntity {
10
-
11
- @ApiProperty({ type: String, format: 'uuid', readOnly: true })
12
- @PrimaryGeneratedColumn('uuid')
13
- id: string;
14
-
15
- @ApiProperty({ type: String })
16
- @IsString()
17
- @IsNotEmpty()
18
- @Matches(/^[a-z0-9\-_]+$/, { message: 'Invalid template name format' })
19
- @Column()
20
- name: string;
21
-
22
- @ApiProperty({ type: String, nullable: true })
23
- @IsString()
24
- @IsOptional()
25
- @Column({ nullable: true })
26
- displayName?: string;
27
-
28
- @ApiProperty({ type: String, nullable: true })
29
- @IsString()
30
- @IsOptional()
31
- @Column({ type: 'text', nullable: true })
32
- description?: string;
33
-
34
- @ApiProperty({ type: String })
35
- @IsString()
36
- @IsOptional()
37
- @Column({ type: 'text' })
38
- type?: string;
39
-
40
- @ApiProperty({ enum: TemplateEngineEnum, type: String })
41
- @IsEnum(TemplateEngineEnum)
42
- @Column({
43
- type: 'text',
44
- enum: TemplateEngineEnum,
45
- default: TemplateEngineEnum.NUNJUCKS
46
- })
47
- engine: TemplateEngineEnum;
48
-
49
- @ApiProperty({ enum: TemplateLanguageEnum, type: String, nullable: true })
50
- @IsEnum(TemplateLanguageEnum)
51
- @IsOptional()
52
- @Column({ type: 'text' })
53
- language?: TemplateLanguageEnum;
54
-
55
- @ApiProperty({ type: String })
56
- @IsString()
57
- @IsOptional()
58
- @Column('text')
59
- content: string;
60
-
61
- @ApiProperty({ type: String, nullable: true })
62
- @IsString()
63
- @IsOptional()
64
- @Column({ nullable: true })
65
- templateLayoutName?: string;
66
-
67
- @ApiProperty({ type: String, nullable: true })
68
- @IsString()
69
- @Column({ nullable: true, default: 'system' })
70
- scope?: string;
71
-
72
- @ApiProperty({ type: String, nullable: true })
73
- @IsString()
74
- @Column({ nullable: true })
75
- scopeId?: string;
76
-
77
- @ApiProperty({ type: String, nullable: true })
78
- @IsString()
79
- @Column({ nullable: true, default: 'en' })
80
- locale?: string;
81
-
82
- @ApiProperty({ type: Object, nullable: true })
83
- @IsOptional()
84
- @Column('simple-json', { nullable: true })
85
- previewContext?: Record<string, any>;
86
-
87
- @ApiProperty({ type: Boolean })
88
- @IsBoolean()
89
- @Column({ default: true })
90
- isActive: boolean;
91
-
92
- @ApiProperty({ type: Date, readOnly: true })
93
- @CreateDateColumn()
94
- createdAt: Date;
95
-
96
- @ApiProperty({ type: Date, readOnly: true })
97
- @UpdateDateColumn()
98
- updatedAt: Date;
99
- }
@@ -1,105 +0,0 @@
1
- import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, Index, JoinColumn, ManyToOne, RelationId, BaseEntity } from 'typeorm';
2
- import { TemplateTypeEnum, TemplateEngineEnum, TemplateLanguageEnum } from '../interfaces/template.types';
3
- import { IsBoolean, IsEnum, IsNotEmpty, IsOptional, IsString, Matches } from 'class-validator';
4
- import { ApiProperty } from '@nestjs/swagger';
5
-
6
-
7
- @Entity('nest_dynamic_templates')
8
- @Index(['name', 'scope', 'scopeId', 'locale'], { unique: true })
9
- export class NestDynamicTemplate extends BaseEntity {
10
-
11
- @ApiProperty({ type: String, format: 'uuid', readOnly: true })
12
- @PrimaryGeneratedColumn('uuid')
13
- id: string;
14
-
15
- @ApiProperty({ type: String })
16
- @IsString()
17
- @IsNotEmpty()
18
- @Matches(/^[a-z0-9\-_]+$/, { message: 'Invalid template name format' })
19
- @Column()
20
- name: string;
21
-
22
- @ApiProperty({ type: String, nullable: true })
23
- @IsString()
24
- @IsOptional()
25
- @Column({ nullable: true })
26
- displayName?: string;
27
-
28
- @ApiProperty({ type: String, nullable: true })
29
- @IsString()
30
- @IsOptional()
31
- @Column({ type: 'text', nullable: true })
32
- description?: string;
33
-
34
- @ApiProperty({ type: String, nullable: true })
35
- @IsString()
36
- @IsOptional()
37
- @Column({ type: 'text', nullable: true })
38
- type?: string;
39
-
40
- @ApiProperty({ enum: TemplateEngineEnum, type: String })
41
- @IsEnum(TemplateEngineEnum)
42
- @Column({
43
- type: 'text',
44
- enum: TemplateEngineEnum,
45
- default: TemplateEngineEnum.NUNJUCKS
46
- })
47
- engine: TemplateEngineEnum;
48
-
49
- @ApiProperty({ enum: TemplateLanguageEnum, type: String, nullable: true })
50
- @IsEnum(TemplateLanguageEnum)
51
- @IsOptional()
52
- @Column({ type: 'text' })
53
- language?: TemplateLanguageEnum;
54
-
55
- @ApiProperty({ type: String, nullable: true })
56
- @IsString()
57
- @IsOptional()
58
- @Column({ nullable: true })
59
- subject?: string;
60
-
61
- @ApiProperty({ type: String })
62
- @IsString()
63
- @IsOptional()
64
- @Column('text')
65
- content: string;
66
-
67
- @ApiProperty({ type: String, nullable: true })
68
- @IsString()
69
- @IsOptional()
70
- @Column({ nullable: true })
71
- templateLayoutName?: string;
72
-
73
- @ApiProperty({ type: String, nullable: true })
74
- @IsString()
75
- @Column({ nullable: true, default: 'system' })
76
- scope?: string;
77
-
78
- @ApiProperty({ type: String, nullable: true })
79
- @IsString()
80
- @Column({ nullable: true })
81
- scopeId?: string;
82
-
83
- @ApiProperty({ type: String, nullable: true })
84
- @IsString()
85
- @Column({ nullable: true, default: 'en' })
86
- locale?: string;
87
-
88
- @ApiProperty({ type: Object, nullable: true })
89
- @IsOptional()
90
- @Column('simple-json', { nullable: true })
91
- previewContext?: Record<string, any>;
92
-
93
- @ApiProperty({ type: Boolean })
94
- @IsBoolean()
95
- @Column({ default: true })
96
- isActive: boolean;
97
-
98
- @ApiProperty({ type: Date, readOnly: true })
99
- @CreateDateColumn()
100
- createdAt: Date;
101
-
102
- @ApiProperty({ type: Date, readOnly: true })
103
- @UpdateDateColumn()
104
- updatedAt: Date;
105
- }
@@ -1,25 +0,0 @@
1
- export enum TemplateTypeEnum {
2
- EMAIL = 'email',
3
- SMS = 'sms',
4
- PUSH = 'push',
5
- PDF = 'pdf',
6
- }
7
-
8
- export enum TemplateEngineEnum {
9
- NUNJUCKS = 'njk',
10
- HANDLEBARS = 'hbs',
11
- EJS = 'ejs',
12
- PUG = 'pug',
13
- }
14
-
15
- export enum TemplateLanguageEnum {
16
- MJML = 'mjml',
17
- HTML = 'html',
18
- MARKDOWN = 'md',
19
- TEXT = 'txt',
20
- }
21
-
22
- export interface Scope {
23
- scope: string;
24
- id: string;
25
- }
@@ -1,143 +0,0 @@
1
- import { Module, DynamicModule, Provider } from '@nestjs/common';
2
- import { TypeOrmModule } from '@nestjs/typeorm';
3
- import { NestDynamicTemplate } from './entities/template.entity';
4
- import { NestDynamicTemplateLayout } from './entities/template-layout.entity';
5
- import {
6
- NestDynamicTemplatesModuleConfig,
7
- NestDynamicTemplatesModuleAsyncOptions,
8
- NestDynamicTemplatesModuleOptionsFactory
9
- } from './interfaces/module-config.interface';
10
- import deepmerge from 'deepmerge';
11
- import { TemplateEngineRegistryService } from './services/template-engine.registry';
12
- import { TemplateLayoutService } from './services/template-layout.service';
13
- import { TemplateService } from './services/template.service';
14
- import { TemplateConfigService } from './services/template-config.service';
15
- import { NEST_DYNAMIC_TEMPLATES_ASYNC_OPTIONS_PROVIDER } from './constant';
16
- import { TemplateEngineEnum } from './interfaces/template.types';
17
- import { TemplateLanguageEnum } from './interfaces/template.types';
18
-
19
-
20
- const defaultConfig: NestDynamicTemplatesModuleConfig = {
21
- engines: {
22
- template: [TemplateEngineEnum.NUNJUCKS],
23
- language: [TemplateLanguageEnum.HTML, TemplateLanguageEnum.MJML, TemplateLanguageEnum.TEXT]
24
- }
25
- }
26
-
27
- @Module({
28
- imports: [TypeOrmModule.forFeature([NestDynamicTemplate, NestDynamicTemplateLayout])],
29
- providers: [
30
- TemplateConfigService,
31
- TemplateEngineRegistryService,
32
- TemplateLayoutService,
33
- TemplateService,
34
- ],
35
- exports: [
36
- TemplateConfigService,
37
- TemplateService,
38
- TemplateLayoutService,
39
- ],
40
- })
41
- export class NestDynamicTemplatesModule {
42
- static moduleDefaultOptions: Partial<NestDynamicTemplatesModuleConfig> = defaultConfig;
43
-
44
- static forRoot(config: NestDynamicTemplatesModuleConfig = {}): DynamicModule {
45
- const mergedConfig = this.getOptions(config);
46
-
47
- // Set options in static service
48
- TemplateConfigService.setOptions(mergedConfig);
49
-
50
- return {
51
- module: NestDynamicTemplatesModule,
52
- global: mergedConfig.isGlobal,
53
- imports: [
54
- TypeOrmModule.forFeature([NestDynamicTemplate, NestDynamicTemplateLayout]),
55
- ],
56
- providers: [
57
- TemplateConfigService,
58
- TemplateEngineRegistryService,
59
- TemplateLayoutService,
60
- TemplateService,
61
- ],
62
- exports: [
63
- TemplateConfigService,
64
- TemplateService,
65
- TemplateLayoutService,
66
- ],
67
- };
68
- }
69
-
70
- static forRootAsync(options: NestDynamicTemplatesModuleAsyncOptions): DynamicModule {
71
- const asyncProviders = this.createAsyncProviders(options);
72
-
73
- return {
74
- module: NestDynamicTemplatesModule,
75
- global: options.isGlobal,
76
- imports: [
77
- TypeOrmModule.forFeature([NestDynamicTemplate, NestDynamicTemplateLayout]),
78
- ...(options.imports || []),
79
- ],
80
- providers: [
81
- ...asyncProviders,
82
- TemplateConfigService,
83
- TemplateEngineRegistryService,
84
- TemplateLayoutService,
85
- TemplateService,
86
- ],
87
- exports: [
88
- TemplateConfigService,
89
- TemplateService,
90
- TemplateLayoutService,
91
- ],
92
- };
93
- }
94
-
95
- private static createAsyncProviders(options: NestDynamicTemplatesModuleAsyncOptions): Provider[] {
96
- if (options.useExisting || options.useFactory) {
97
- return [this.createAsyncOptionsProvider(options)];
98
- }
99
-
100
- if (options.useClass) {
101
- return [
102
- this.createAsyncOptionsProvider(options),
103
- {
104
- provide: options.useClass,
105
- useClass: options.useClass,
106
- },
107
- ];
108
- }
109
-
110
- return [];
111
- }
112
-
113
- private static createAsyncOptionsProvider(options: NestDynamicTemplatesModuleAsyncOptions): Provider {
114
- if (options.useFactory) {
115
- return {
116
- provide: NEST_DYNAMIC_TEMPLATES_ASYNC_OPTIONS_PROVIDER,
117
- useFactory: async (...args: any[]) => {
118
- const userOptions = options.useFactory ? await options.useFactory(...args) : {};
119
- const mergedOptions = this.getOptions(userOptions);
120
- TemplateConfigService.setOptions(mergedOptions);
121
- return mergedOptions;
122
- },
123
- inject: options.inject || [],
124
- };
125
- }
126
-
127
- return {
128
- provide: NEST_DYNAMIC_TEMPLATES_ASYNC_OPTIONS_PROVIDER,
129
- useFactory: async (optionsFactory: NestDynamicTemplatesModuleOptionsFactory) => {
130
- const userOptions = await optionsFactory.createNestDynamicTemplatesModuleOptions();
131
- const mergedOptions = this.getOptions(userOptions);
132
- TemplateConfigService.setOptions(mergedOptions);
133
- return mergedOptions;
134
- },
135
- inject: [options.useExisting || options.useClass!],
136
- };
137
- }
138
-
139
- private static getOptions(options: NestDynamicTemplatesModuleConfig): NestDynamicTemplatesModuleConfig {
140
- return deepmerge(this.moduleDefaultOptions, options);
141
- }
142
-
143
- }
@@ -1,109 +0,0 @@
1
- import { Injectable } from '@nestjs/common';
2
- import { TemplateEngineEnum, TemplateLanguageEnum } from '../interfaces/template.types';
3
- import { NunjucksEngine } from '../engines/template/nunjucks.engine';
4
- import { MjmlEngine } from '../engines/language/mjml.engine';
5
- import { HtmlEngine } from '../engines/language/html.engine';
6
- import { MarkdownEngine, TextEngine } from '../engines/language';
7
- import { EjsEngine } from '../engines/template/ejs.engine';
8
- import { HandlebarsEngine } from '../engines/template/handlebars.engine';
9
- import { PugEngine } from '../engines/template/pug.engine';
10
- import { TemplateConfigService } from './template-config.service';
11
- import { TemplateEngine } from '../engines/template-engine';
12
- import { LanguageEngine } from '../engines/language-engine';
13
- import { NestDynamicTemplatesModuleConfig } from '../interfaces/module-config.interface';
14
-
15
- type ClassType<T> = new (...args: any[]) => T;
16
-
17
- @Injectable()
18
- export class TemplateEngineRegistryService {
19
- private templateEngines: Map<TemplateEngineEnum, TemplateEngine> = new Map();
20
- private languageEngines: Map<TemplateLanguageEnum, LanguageEngine> = new Map();
21
- private config: NestDynamicTemplatesModuleConfig;
22
-
23
- constructor() {
24
- this.config = TemplateConfigService.getOptions();
25
-
26
- this.registerTemplateEngines([
27
- NunjucksEngine,
28
- HandlebarsEngine,
29
- EjsEngine,
30
- PugEngine
31
- ]);
32
-
33
-
34
- this.registerLanguageEngines([
35
- MjmlEngine,
36
- HtmlEngine,
37
- TextEngine,
38
- MarkdownEngine
39
- ]);
40
- }
41
-
42
- registerTemplateEngines(engineClasses: ClassType<TemplateEngine>[]): void {
43
- engineClasses.forEach(EngineClass => {
44
- const engineName = (EngineClass as any).engineName;
45
- if (!engineName) {
46
- throw new Error(`Engine class ${EngineClass.name} must define static engineName property`);
47
- }
48
- const options = (this.config.enginesOptions?.template as any)?.[engineName];
49
-
50
- const customOptions = {
51
- filters: this.config.enginesOptions?.filters,
52
- globalValues: this.config.enginesOptions?.globalValues
53
- }
54
-
55
- this.registerTemplateEngine(engineName, new EngineClass(options, customOptions));
56
- });
57
- }
58
-
59
- registerTemplateEngine(format: TemplateEngineEnum, engine: TemplateEngine): void {
60
- this.templateEngines.set(format, engine);
61
- }
62
-
63
- registerLanguageEngine(format: TemplateLanguageEnum, engine: LanguageEngine): void {
64
- this.languageEngines.set(format, engine);
65
- }
66
-
67
- getTemplateEngine(format: TemplateEngineEnum): TemplateEngine {
68
- const engine = this.templateEngines.get(format);
69
- if (!engine) {
70
- throw new Error(`Template engine not found for format: ${format}`);
71
- }
72
- return engine;
73
- }
74
-
75
- getLanguageEngine(format: TemplateLanguageEnum): LanguageEngine {
76
- const engine = this.languageEngines.get(format);
77
- if (!engine) {
78
- throw new Error(`Language engine not found for format: ${format}`);
79
- }
80
- return engine;
81
- }
82
-
83
- registerLanguageEngines(engineClasses: ClassType<LanguageEngine>[]): void {
84
- engineClasses.forEach(EngineClass => {
85
- const engineName = (EngineClass as any).engineName;
86
- if (!engineName) {
87
- throw new Error(`Engine class ${EngineClass.name} must define static engineName property`);
88
- }
89
- const options = (this.config.enginesOptions?.language as any)?.[engineName];
90
- this.registerLanguageEngine(engineName, new EngineClass(options));
91
- });
92
- }
93
-
94
- hasTemplateEngine(format: TemplateEngineEnum): boolean {
95
- return this.templateEngines.has(format);
96
- }
97
-
98
- hasLanguageEngine(format: TemplateLanguageEnum): boolean {
99
- return this.languageEngines.has(format);
100
- }
101
-
102
- getSupportedTemplateFormats(): TemplateEngineEnum[] {
103
- return Array.from(this.templateEngines.keys());
104
- }
105
-
106
- getSupportedLanguageFormats(): TemplateLanguageEnum[] {
107
- return Array.from(this.languageEngines.keys());
108
- }
109
- }