@breadstone/archipel-platform-mailing 0.0.34 → 0.0.36

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 (32) hide show
  1. package/package.json +5 -5
  2. package/src/MailModule.d.ts +29 -8
  3. package/src/MailModule.js +35 -80
  4. package/src/delivering/strategies/logger/LogDeliveryStrategy.js +9 -3
  5. package/src/delivering/strategies/mailgun/MailgunDeliveryStrategy.js +9 -3
  6. package/src/delivering/strategies/postmark/PostmarkDeliveryStrategy.js +10 -3
  7. package/src/delivering/strategies/resend/ResendDeliveryStrategy.js +10 -3
  8. package/src/delivering/strategies/sendgrid/SendGridDeliveryStrategy.js +9 -3
  9. package/src/delivering/strategies/smtp/SmtpDeliveryStrategy.js +10 -3
  10. package/src/env.d.ts +0 -4
  11. package/src/env.js +3 -13
  12. package/src/events/IMailEvents.d.ts +12 -1
  13. package/src/events/listeners/MailEventSubscriber.js +2 -1
  14. package/src/index.d.ts +2 -0
  15. package/src/index.js +2 -0
  16. package/src/models/IMailTemplateVariants.d.ts +10 -0
  17. package/src/models/IMailTemplateVariants.js +3 -0
  18. package/src/models/MailTemplateFormat.d.ts +6 -0
  19. package/src/models/MailTemplateFormat.js +3 -0
  20. package/src/services/MailService.d.ts +7 -3
  21. package/src/services/MailService.js +13 -6
  22. package/src/templating/MailTemplateEngine.d.ts +10 -1
  23. package/src/templating/MailTemplateEngine.js +16 -6
  24. package/src/templating/strategies/abstracts/TemplateFetchStrategyBase.d.ts +2 -4
  25. package/src/templating/strategies/blob/BlobTemplateFetchStrategy.d.ts +1 -1
  26. package/src/templating/strategies/blob/BlobTemplateFetchStrategy.js +9 -3
  27. package/src/templating/strategies/database/DatabaseTemplateFetchStrategy.d.ts +1 -1
  28. package/src/templating/strategies/database/DatabaseTemplateFetchStrategy.js +3 -0
  29. package/src/templating/strategies/file/FileTemplateFetchStrategy.d.ts +6 -8
  30. package/src/templating/strategies/file/FileTemplateFetchStrategy.js +9 -14
  31. package/src/tokens/MailTokens.d.ts +1 -11
  32. package/src/tokens/MailTokens.js +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@breadstone/archipel-platform-mailing",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "description": "Email delivery with strategy-based transport and template engines for NestJS applications.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -134,10 +134,10 @@
134
134
  "README.md"
135
135
  ],
136
136
  "dependencies": {
137
- "@breadstone/archipel-platform-blob-storage": "0.0.34",
138
- "@breadstone/archipel-platform-configuration": "0.0.34",
139
- "@breadstone/archipel-platform-core": "0.0.34",
140
- "@breadstone/archipel-platform-resources": "0.0.34",
137
+ "@breadstone/archipel-platform-blob-storage": "0.0.36",
138
+ "@breadstone/archipel-platform-configuration": "0.0.36",
139
+ "@breadstone/archipel-platform-core": "0.0.36",
140
+ "@breadstone/archipel-platform-resources": "0.0.36",
141
141
  "tslib": "2.8.1"
142
142
  },
143
143
  "peerDependencies": {
@@ -1,29 +1,50 @@
1
1
  import type { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
2
- import { type DynamicModule, type Provider } from '@nestjs/common';
2
+ import { type DynamicModule, type Provider, type Type } from '@nestjs/common';
3
+ import type { DeliveryStrategyBase } from './delivering/strategies/abstracts/DeliveryStrategyBase';
3
4
  import type { IMailTemplateRepository } from './ports/IMailTemplateRepository';
5
+ import type { TemplateFetchStrategyBase } from './templating/strategies/abstracts/TemplateFetchStrategyBase';
4
6
  /**
5
7
  * Options for configuring the {@link MailModule}.
6
8
  *
7
9
  * @public
8
10
  */
9
11
  export interface IMailModuleOptions {
12
+ /**
13
+ * Concrete implementation of the {@link DeliveryStrategyBase} port.
14
+ * For example, `SmtpDeliveryStrategy`, `PostmarkDeliveryStrategy`, or `LogDeliveryStrategy`.
15
+ */
16
+ readonly deliveryStrategy: Type<DeliveryStrategyBase>;
17
+ /**
18
+ * Concrete implementation of the {@link TemplateFetchStrategyBase} port.
19
+ * For example, `FileTemplateFetchStrategy`, `BlobTemplateFetchStrategy`, or `DatabaseTemplateFetchStrategy`.
20
+ */
21
+ readonly templateFetchStrategy: Type<TemplateFetchStrategyBase>;
10
22
  /**
11
23
  * Whether to register the module globally.
12
24
  * Defaults to `true`.
13
25
  */
14
26
  readonly isGlobal?: boolean;
15
27
  /**
16
- * Additional or overriding configuration entries.
17
- * Merged with the platform default entries.
28
+ * Provider-specific configuration entries to register with the config module.
18
29
  */
19
30
  readonly configEntries?: ReadonlyArray<Omit<IConfigRegistryEntry, 'module'>>;
31
+ /**
32
+ * Template names to load when using the `FileTemplateFetchStrategy`.
33
+ * Each name corresponds to a resource file (e.g. `'AuthRegister'` loads
34
+ * `AuthRegister.html` and `AuthRegister.txt`).
35
+ *
36
+ * Defaults to an empty array (no templates loaded).
37
+ */
38
+ readonly templateNames?: ReadonlyArray<string>;
20
39
  /**
21
40
  * Provider for the `IMailTemplateRepository` port.
22
- * Required when `MAIL_TEMPLATE_STRATEGY` is set to `'database'`.
41
+ * Required when using `DatabaseTemplateFetchStrategy`.
23
42
  *
24
43
  * Example:
25
44
  * ```typescript
26
45
  * MailModule.register({
46
+ * deliveryStrategy: SmtpDeliveryStrategy,
47
+ * templateFetchStrategy: DatabaseTemplateFetchStrategy,
27
48
  * templateRepositoryProvider: {
28
49
  * provide: MAIL_TEMPLATE_REPOSITORY_TOKEN,
29
50
  * useClass: PrismaMailTemplateRepository,
@@ -36,19 +57,19 @@ export interface IMailModuleOptions {
36
57
  /**
37
58
  * Represents the mail module.
38
59
  *
39
- * Delivery and template strategies are resolved at runtime based on
40
- * configuration keys `MAIL_DELIVERY_STRATEGY` and `MAIL_TEMPLATE_STRATEGY`.
60
+ * Delivery and template strategies are selected at compile time via
61
+ * `IMailModuleOptions`. NestJS DI resolves the concrete classes.
41
62
  *
42
63
  * @public
43
64
  */
44
65
  export declare class MailModule {
45
66
  /**
46
- * Registers the mail module with optional configuration.
67
+ * Registers the mail module with the specified configuration.
47
68
  *
48
69
  * @param options - Module registration options.
49
70
  * @returns A configured `DynamicModule`.
50
71
  *
51
72
  * @public
52
73
  */
53
- static register(options?: IMailModuleOptions): DynamicModule;
74
+ static register(options: IMailModuleOptions): DynamicModule;
54
75
  }
package/src/MailModule.js CHANGED
@@ -7,7 +7,6 @@ const tslib_1 = require("tslib");
7
7
  const archipel_platform_blob_storage_1 = require("@breadstone/archipel-platform-blob-storage");
8
8
  const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
9
9
  const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
10
- const archipel_platform_resources_1 = require("@breadstone/archipel-platform-resources");
11
10
  const common_1 = require("@nestjs/common");
12
11
  const env_1 = require("./env");
13
12
  const MailEventSubscriber_1 = require("./events/listeners/MailEventSubscriber");
@@ -19,14 +18,15 @@ const MailTokens_1 = require("./tokens/MailTokens");
19
18
  /**
20
19
  * Represents the mail module.
21
20
  *
22
- * Delivery and template strategies are resolved at runtime based on
23
- * configuration keys `MAIL_DELIVERY_STRATEGY` and `MAIL_TEMPLATE_STRATEGY`.
21
+ * Delivery and template strategies are selected at compile time via
22
+ * `IMailModuleOptions`. NestJS DI resolves the concrete classes.
24
23
  *
25
24
  * @public
26
25
  */
27
26
  let MailModule = MailModule_1 = class MailModule {
27
+ // #region Methods
28
28
  /**
29
- * Registers the mail module with optional configuration.
29
+ * Registers the mail module with the specified configuration.
30
30
  *
31
31
  * @param options - Module registration options.
32
32
  * @returns A configured `DynamicModule`.
@@ -34,87 +34,42 @@ let MailModule = MailModule_1 = class MailModule {
34
34
  * @public
35
35
  */
36
36
  static register(options) {
37
- const isGlobal = options?.isGlobal ?? true;
38
- const configEntries = options?.configEntries ?? env_1.PLATFORM_MAILING_CONFIG_ENTRIES;
39
- const additionalProviders = [];
40
- if (options?.templateRepositoryProvider) {
41
- additionalProviders.push(options.templateRepositoryProvider);
37
+ const isGlobal = options.isGlobal ?? true;
38
+ const configEntries = options.configEntries ?? env_1.PLATFORM_MAILING_CONFIG_ENTRIES;
39
+ const providers = [
40
+ {
41
+ provide: MailTokens_1.MAIL_TEMPLATE_FETCH_STRATEGY_TOKEN,
42
+ useClass: options.templateFetchStrategy,
43
+ },
44
+ {
45
+ provide: MailTokens_1.MAIL_DELIVERY_STRATEGY_TOKEN,
46
+ useClass: options.deliveryStrategy,
47
+ },
48
+ {
49
+ provide: MailTokens_1.MAIL_TEMPLATE_NAMES_TOKEN,
50
+ useValue: options.templateNames ?? [],
51
+ },
52
+ archipel_platform_core_1.ContentTemplateEngine,
53
+ MailService_1.MailService,
54
+ MailTemplateEngine_1.MailTemplateEngine,
55
+ MailVerificationService_1.MailVerificationService,
56
+ SmtpConnectionVerifier_1.SmtpConnectionVerifier,
57
+ MailEventSubscriber_1.MailEventSubscriber,
58
+ ];
59
+ const exports = [
60
+ MailService_1.MailService,
61
+ MailVerificationService_1.MailVerificationService,
62
+ SmtpConnectionVerifier_1.SmtpConnectionVerifier,
63
+ ];
64
+ if (options.templateRepositoryProvider) {
65
+ providers.push(options.templateRepositoryProvider);
42
66
  }
43
67
  return {
44
68
  module: MailModule_1,
45
69
  global: isGlobal,
46
70
  imports: [archipel_platform_configuration_1.ConfigModule.register('platform-mailing', configEntries), archipel_platform_blob_storage_1.BlobModule, archipel_platform_core_1.EventModule],
47
- providers: [
48
- ...additionalProviders,
49
- {
50
- provide: MailTokens_1.MAIL_TEMPLATE_FETCH_STRATEGY_TOKEN,
51
- useFactory: async (configService, blobService, resourceManager, ...extra) => {
52
- const templateStrategy = configService.get(env_1.MAIL_TEMPLATE_STRATEGY.key);
53
- if (templateStrategy === 'file') {
54
- const { FileTemplateFetchStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./templating/strategies/file/FileTemplateFetchStrategy')));
55
- return new FileTemplateFetchStrategy(resourceManager);
56
- }
57
- if (templateStrategy === 'blob') {
58
- const { BlobTemplateFetchStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./templating/strategies/blob/BlobTemplateFetchStrategy')));
59
- return new BlobTemplateFetchStrategy(blobService);
60
- }
61
- if (templateStrategy === 'database') {
62
- const repository = extra[0];
63
- if (!repository) {
64
- throw new Error("Template strategy 'database' requires a templateRepositoryProvider in MailModule.register() options.");
65
- }
66
- const { DatabaseTemplateFetchStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./templating/strategies/database/DatabaseTemplateFetchStrategy')));
67
- return new DatabaseTemplateFetchStrategy(repository);
68
- }
69
- throw new Error(`Unknown template strategy: ${templateStrategy}`);
70
- },
71
- inject: [
72
- archipel_platform_configuration_1.ConfigService,
73
- archipel_platform_blob_storage_1.BlobService,
74
- archipel_platform_resources_1.ResourceManager,
75
- ...(options?.templateRepositoryProvider ? [MailTokens_1.MAIL_TEMPLATE_REPOSITORY_TOKEN] : []),
76
- ],
77
- },
78
- {
79
- provide: MailTokens_1.MAIL_DELIVERY_STRATEGY_TOKEN,
80
- useFactory: async (configService) => {
81
- const deliveryStrategy = configService.get(env_1.MAIL_DELIVERY_STRATEGY.key);
82
- if (deliveryStrategy === 'log') {
83
- const { LogDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./delivering/strategies/logger/LogDeliveryStrategy')));
84
- return new LogDeliveryStrategy();
85
- }
86
- if (deliveryStrategy === 'smtp') {
87
- const { SmtpDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./delivering/strategies/smtp/SmtpDeliveryStrategy')));
88
- return new SmtpDeliveryStrategy(configService);
89
- }
90
- if (deliveryStrategy === 'postmark') {
91
- const { PostmarkDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./delivering/strategies/postmark/PostmarkDeliveryStrategy')));
92
- return new PostmarkDeliveryStrategy(configService);
93
- }
94
- if (deliveryStrategy === 'resend') {
95
- const { ResendDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./delivering/strategies/resend/ResendDeliveryStrategy')));
96
- return new ResendDeliveryStrategy(configService);
97
- }
98
- if (deliveryStrategy === 'sendgrid') {
99
- const { SendGridDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./delivering/strategies/sendgrid/SendGridDeliveryStrategy')));
100
- return new SendGridDeliveryStrategy(configService);
101
- }
102
- if (deliveryStrategy === 'mailgun') {
103
- const { MailgunDeliveryStrategy } = await Promise.resolve().then(() => tslib_1.__importStar(require('./delivering/strategies/mailgun/MailgunDeliveryStrategy')));
104
- return new MailgunDeliveryStrategy(configService);
105
- }
106
- throw new Error(`Unknown delivery strategy: ${deliveryStrategy}`);
107
- },
108
- inject: [archipel_platform_configuration_1.ConfigService],
109
- },
110
- archipel_platform_core_1.ContentTemplateEngine,
111
- MailService_1.MailService,
112
- MailTemplateEngine_1.MailTemplateEngine,
113
- MailVerificationService_1.MailVerificationService,
114
- SmtpConnectionVerifier_1.SmtpConnectionVerifier,
115
- MailEventSubscriber_1.MailEventSubscriber,
116
- ],
117
- exports: [MailService_1.MailService, MailVerificationService_1.MailVerificationService, SmtpConnectionVerifier_1.SmtpConnectionVerifier],
71
+ providers,
72
+ exports,
118
73
  };
119
74
  }
120
75
  };
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var LogDeliveryStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.LogDeliveryStrategy = void 0;
6
+ const tslib_1 = require("tslib");
5
7
  const common_1 = require("@nestjs/common");
6
8
  const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
7
9
  // #endregion
@@ -10,7 +12,7 @@ const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
10
12
  *
11
13
  * @public
12
14
  */
13
- class LogDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
15
+ let LogDeliveryStrategy = LogDeliveryStrategy_1 = class LogDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
14
16
  // #endregion
15
17
  // #region Ctor
16
18
  /**
@@ -21,7 +23,7 @@ class LogDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
21
23
  constructor() {
22
24
  super();
23
25
  // #region Fields
24
- this._logger = new common_1.Logger(LogDeliveryStrategy.name);
26
+ this._logger = new common_1.Logger(LogDeliveryStrategy_1.name);
25
27
  }
26
28
  // #endregion
27
29
  // #region Methods
@@ -35,6 +37,10 @@ class LogDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
35
37
  })}`);
36
38
  return Promise.resolve();
37
39
  }
38
- }
40
+ };
39
41
  exports.LogDeliveryStrategy = LogDeliveryStrategy;
42
+ exports.LogDeliveryStrategy = LogDeliveryStrategy = LogDeliveryStrategy_1 = tslib_1.__decorate([
43
+ (0, common_1.Injectable)(),
44
+ tslib_1.__metadata("design:paramtypes", [])
45
+ ], LogDeliveryStrategy);
40
46
  //# sourceMappingURL=LogDeliveryStrategy.js.map
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var MailgunDeliveryStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.MailgunDeliveryStrategy = void 0;
5
6
  const tslib_1 = require("tslib");
7
+ const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
6
8
  const common_1 = require("@nestjs/common");
7
9
  const form_data_1 = tslib_1.__importDefault(require("form-data"));
8
10
  const mailgun_js_1 = tslib_1.__importDefault(require("mailgun.js"));
@@ -15,7 +17,7 @@ const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
15
17
  *
16
18
  * @public
17
19
  */
18
- class MailgunDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
20
+ let MailgunDeliveryStrategy = MailgunDeliveryStrategy_1 = class MailgunDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
19
21
  // #endregion
20
22
  // #region Ctor
21
23
  /**
@@ -26,7 +28,7 @@ class MailgunDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBas
26
28
  constructor(configService) {
27
29
  super();
28
30
  // #region Fields
29
- this._logger = new common_1.Logger(MailgunDeliveryStrategy.name);
31
+ this._logger = new common_1.Logger(MailgunDeliveryStrategy_1.name);
30
32
  const mailgun = new mailgun_js_1.default(form_data_1.default);
31
33
  this._mailgunClient = mailgun.client({
32
34
  username: 'api',
@@ -65,6 +67,10 @@ class MailgunDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBas
65
67
  throw new MailDeliveryError_1.MailDeliveryError('mailgun', 'Failed to send email via Mailgun', error);
66
68
  }
67
69
  }
68
- }
70
+ };
69
71
  exports.MailgunDeliveryStrategy = MailgunDeliveryStrategy;
72
+ exports.MailgunDeliveryStrategy = MailgunDeliveryStrategy = MailgunDeliveryStrategy_1 = tslib_1.__decorate([
73
+ (0, common_1.Injectable)(),
74
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
75
+ ], MailgunDeliveryStrategy);
70
76
  //# sourceMappingURL=MailgunDeliveryStrategy.js.map
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var PostmarkDeliveryStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.PostmarkDeliveryStrategy = void 0;
6
+ const tslib_1 = require("tslib");
7
+ const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
5
8
  const common_1 = require("@nestjs/common");
6
9
  const postmark_1 = require("postmark");
7
10
  const env_1 = require("../../../env");
@@ -13,7 +16,7 @@ const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
13
16
  *
14
17
  * @public
15
18
  */
16
- class PostmarkDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
19
+ let PostmarkDeliveryStrategy = PostmarkDeliveryStrategy_1 = class PostmarkDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
17
20
  // #endregion
18
21
  // #region Ctor
19
22
  /**
@@ -24,7 +27,7 @@ class PostmarkDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBa
24
27
  constructor(configService) {
25
28
  super();
26
29
  // #region Fields
27
- this._logger = new common_1.Logger(PostmarkDeliveryStrategy.name);
30
+ this._logger = new common_1.Logger(PostmarkDeliveryStrategy_1.name);
28
31
  this._postmarkClient = new postmark_1.ServerClient(configService.get(env_1.MAIL_POSTMARK_API_KEY.key));
29
32
  }
30
33
  // #endregion
@@ -58,6 +61,10 @@ class PostmarkDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBa
58
61
  throw new MailDeliveryError_1.MailDeliveryError('postmark', 'Failed to send email via Postmark', error);
59
62
  }
60
63
  }
61
- }
64
+ };
62
65
  exports.PostmarkDeliveryStrategy = PostmarkDeliveryStrategy;
66
+ exports.PostmarkDeliveryStrategy = PostmarkDeliveryStrategy = PostmarkDeliveryStrategy_1 = tslib_1.__decorate([
67
+ (0, common_1.Injectable)(),
68
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
69
+ ], PostmarkDeliveryStrategy);
63
70
  //# sourceMappingURL=PostmarkDeliveryStrategy.js.map
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var ResendDeliveryStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.ResendDeliveryStrategy = void 0;
6
+ const tslib_1 = require("tslib");
7
+ const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
5
8
  const common_1 = require("@nestjs/common");
6
9
  const resend_1 = require("resend");
7
10
  const env_1 = require("../../../env");
@@ -13,7 +16,7 @@ const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
13
16
  *
14
17
  * @public
15
18
  */
16
- class ResendDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
19
+ let ResendDeliveryStrategy = ResendDeliveryStrategy_1 = class ResendDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
17
20
  // #endregion
18
21
  // #region Ctor
19
22
  /**
@@ -24,7 +27,7 @@ class ResendDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase
24
27
  constructor(configService) {
25
28
  super();
26
29
  // #region Fields
27
- this._logger = new common_1.Logger(ResendDeliveryStrategy.name);
30
+ this._logger = new common_1.Logger(ResendDeliveryStrategy_1.name);
28
31
  this._resendClient = new resend_1.Resend(configService.get(env_1.MAIL_RESEND_API_KEY.key));
29
32
  }
30
33
  // #endregion
@@ -58,6 +61,10 @@ class ResendDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase
58
61
  throw new MailDeliveryError_1.MailDeliveryError('resend', 'Failed to send email via Resend', error);
59
62
  }
60
63
  }
61
- }
64
+ };
62
65
  exports.ResendDeliveryStrategy = ResendDeliveryStrategy;
66
+ exports.ResendDeliveryStrategy = ResendDeliveryStrategy = ResendDeliveryStrategy_1 = tslib_1.__decorate([
67
+ (0, common_1.Injectable)(),
68
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
69
+ ], ResendDeliveryStrategy);
63
70
  //# sourceMappingURL=ResendDeliveryStrategy.js.map
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var SendGridDeliveryStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.SendGridDeliveryStrategy = void 0;
5
6
  const tslib_1 = require("tslib");
7
+ const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
6
8
  const common_1 = require("@nestjs/common");
7
9
  const mail_1 = tslib_1.__importDefault(require("@sendgrid/mail"));
8
10
  const env_1 = require("../../../env");
@@ -14,7 +16,7 @@ const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
14
16
  *
15
17
  * @public
16
18
  */
17
- class SendGridDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
19
+ let SendGridDeliveryStrategy = SendGridDeliveryStrategy_1 = class SendGridDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
18
20
  // #endregion
19
21
  // #region Ctor
20
22
  /**
@@ -25,7 +27,7 @@ class SendGridDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBa
25
27
  constructor(configService) {
26
28
  super();
27
29
  // #region Fields
28
- this._logger = new common_1.Logger(SendGridDeliveryStrategy.name);
30
+ this._logger = new common_1.Logger(SendGridDeliveryStrategy_1.name);
29
31
  mail_1.default.setApiKey(configService.get(env_1.MAIL_SENDGRID_API_KEY.key));
30
32
  }
31
33
  // #endregion
@@ -59,6 +61,10 @@ class SendGridDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBa
59
61
  throw new MailDeliveryError_1.MailDeliveryError('sendgrid', 'Failed to send email via SendGrid', error);
60
62
  }
61
63
  }
62
- }
64
+ };
63
65
  exports.SendGridDeliveryStrategy = SendGridDeliveryStrategy;
66
+ exports.SendGridDeliveryStrategy = SendGridDeliveryStrategy = SendGridDeliveryStrategy_1 = tslib_1.__decorate([
67
+ (0, common_1.Injectable)(),
68
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
69
+ ], SendGridDeliveryStrategy);
64
70
  //# sourceMappingURL=SendGridDeliveryStrategy.js.map
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var SmtpDeliveryStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.SmtpDeliveryStrategy = void 0;
6
+ const tslib_1 = require("tslib");
7
+ const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
5
8
  const common_1 = require("@nestjs/common");
6
9
  const nodemailer_1 = require("nodemailer");
7
10
  const env_1 = require("../../../env");
@@ -13,7 +16,7 @@ const DeliveryStrategyBase_1 = require("../abstracts/DeliveryStrategyBase");
13
16
  *
14
17
  * @public
15
18
  */
16
- class SmtpDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
19
+ let SmtpDeliveryStrategy = SmtpDeliveryStrategy_1 = class SmtpDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
17
20
  // #endregion
18
21
  // #region Ctor
19
22
  /**
@@ -24,7 +27,7 @@ class SmtpDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
24
27
  constructor(configService) {
25
28
  super();
26
29
  // #region Fields
27
- this._logger = new common_1.Logger(SmtpDeliveryStrategy.name);
30
+ this._logger = new common_1.Logger(SmtpDeliveryStrategy_1.name);
28
31
  const options = {
29
32
  host: configService.tryGet(env_1.MAIL_SMTP_HOST.key, 'localhost'),
30
33
  port: configService.tryGet(env_1.MAIL_SMTP_PORT.key, 587),
@@ -67,6 +70,10 @@ class SmtpDeliveryStrategy extends DeliveryStrategyBase_1.DeliveryStrategyBase {
67
70
  throw new MailDeliveryError_1.MailDeliveryError('smtp', 'Failed to send email via SMTP', error);
68
71
  }
69
72
  }
70
- }
73
+ };
71
74
  exports.SmtpDeliveryStrategy = SmtpDeliveryStrategy;
75
+ exports.SmtpDeliveryStrategy = SmtpDeliveryStrategy = SmtpDeliveryStrategy_1 = tslib_1.__decorate([
76
+ (0, common_1.Injectable)(),
77
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_configuration_1.ConfigService])
78
+ ], SmtpDeliveryStrategy);
72
79
  //# sourceMappingURL=SmtpDeliveryStrategy.js.map
package/src/env.d.ts CHANGED
@@ -1,8 +1,4 @@
1
1
  import { IConfigRegistryEntry } from '@breadstone/archipel-platform-configuration';
2
- /** Which template-fetch strategy to use (e.g. `file`, `blob`). */
3
- export declare const MAIL_TEMPLATE_STRATEGY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
4
- /** Which delivery strategy to use (e.g. `smtp`, `postmark`, `resend`, `sendgrid`, `mailgun`, `log`). */
5
- export declare const MAIL_DELIVERY_STRATEGY: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
6
2
  /** Sender e-mail address shown in the `From` header. */
7
3
  export declare const MAIL_SENDER_EMAIL: import("@breadstone/archipel-platform-configuration").IConfigKey<string>;
8
4
  /** Template engine format identifier (e.g. `handlebars`). */
package/src/env.js CHANGED
@@ -1,16 +1,12 @@
1
1
  "use strict";
2
2
  // #region Imports
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.PLATFORM_MAILING_CONFIG_ENTRIES = exports.MAIL_PORT = exports.MAIL_USER = exports.MAIL_HOST = exports.MAIL_SMTP_PASSWORD = exports.MAIL_SMTP_USER = exports.MAIL_SMTP_SECURE = exports.MAIL_SMTP_PORT = exports.MAIL_SMTP_HOST = exports.MAIL_MAILGUN_DOMAIN = exports.MAIL_MAILGUN_API_KEY = exports.MAIL_SENDGRID_API_KEY = exports.MAIL_RESEND_API_KEY = exports.MAIL_POSTMARK_API_KEY = exports.MAIL_TEMPLATE_ENGINE_FORMAT = exports.MAIL_SENDER_EMAIL = exports.MAIL_DELIVERY_STRATEGY = exports.MAIL_TEMPLATE_STRATEGY = void 0;
4
+ exports.PLATFORM_MAILING_CONFIG_ENTRIES = exports.MAIL_PORT = exports.MAIL_USER = exports.MAIL_HOST = exports.MAIL_SMTP_PASSWORD = exports.MAIL_SMTP_USER = exports.MAIL_SMTP_SECURE = exports.MAIL_SMTP_PORT = exports.MAIL_SMTP_HOST = exports.MAIL_MAILGUN_DOMAIN = exports.MAIL_MAILGUN_API_KEY = exports.MAIL_SENDGRID_API_KEY = exports.MAIL_RESEND_API_KEY = exports.MAIL_POSTMARK_API_KEY = exports.MAIL_TEMPLATE_ENGINE_FORMAT = exports.MAIL_SENDER_EMAIL = void 0;
5
5
  const archipel_platform_configuration_1 = require("@breadstone/archipel-platform-configuration");
6
6
  // #endregion
7
7
  // ──────────────────────────────────────────────────────────────
8
- // Delivery & Template Strategy
8
+ // Core
9
9
  // ──────────────────────────────────────────────────────────────
10
- /** Which template-fetch strategy to use (e.g. `file`, `blob`). */
11
- exports.MAIL_TEMPLATE_STRATEGY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_TEMPLATE_STRATEGY');
12
- /** Which delivery strategy to use (e.g. `smtp`, `postmark`, `resend`, `sendgrid`, `mailgun`, `log`). */
13
- exports.MAIL_DELIVERY_STRATEGY = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_DELIVERY_STRATEGY');
14
10
  /** Sender e-mail address shown in the `From` header. */
15
11
  exports.MAIL_SENDER_EMAIL = (0, archipel_platform_configuration_1.createConfigKey)('MAIL_SENDER_EMAIL');
16
12
  /** Template engine format identifier (e.g. `handlebars`). */
@@ -64,13 +60,7 @@ exports.MAIL_PORT = (0, archipel_platform_configuration_1.createConfigKey)('MAIL
64
60
  // ──────────────────────────────────────────────────────────────
65
61
  /** All configuration entries required by `platform-mailing`. */
66
62
  exports.PLATFORM_MAILING_CONFIG_ENTRIES = [
67
- // Strategy
68
- { key: exports.MAIL_TEMPLATE_STRATEGY, required: true, description: 'Template-fetch strategy (file, blob, database).' },
69
- {
70
- key: exports.MAIL_DELIVERY_STRATEGY,
71
- required: true,
72
- description: 'Delivery strategy (smtp, postmark, resend, sendgrid, mailgun, log).',
73
- },
63
+ // Core
74
64
  { key: exports.MAIL_SENDER_EMAIL, required: true, description: 'Sender e-mail address for the From header.' },
75
65
  { key: exports.MAIL_TEMPLATE_ENGINE_FORMAT, required: true, description: 'Template engine format identifier.' },
76
66
  // Postmark
@@ -2,14 +2,25 @@ import { IEventMap } from '@breadstone/archipel-platform-core';
2
2
  /**
3
3
  * Represents the contract of events emitted by the mail domain.
4
4
  *
5
+ * Publishers only need to specify `recipientEmail`, `templateName`, and `templateParams`.
6
+ * The subject is resolved from the stored template (industry-standard behavior).
7
+ * An explicit `subject` can be provided as an override.
8
+ *
5
9
  * @public
6
10
  */
7
11
  export interface IMailEvents extends IEventMap {
8
12
  sendMail: {
13
+ /** Recipient email address. */
9
14
  recipientEmail: string;
10
- subject: string;
15
+ /** Template key to resolve (e.g. `'AuthRegister'`). */
11
16
  templateName: string;
17
+ /** Placeholder values to interpolate into subject and body. */
12
18
  templateParams: Record<string, string | number | boolean | Date | undefined | null>;
19
+ /** Optional locale for template resolution (e.g. `'de'`, `'en'`). */
20
+ locale?: string;
21
+ /** Optional subject override. When omitted, resolved from the template. */
22
+ subject?: string;
23
+ /** Optional sender email override. When omitted, uses the configured default. */
13
24
  senderEmail?: string;
14
25
  };
15
26
  }
@@ -29,7 +29,8 @@ let MailEventSubscriber = MailEventSubscriber_1 = class MailEventSubscriber {
29
29
  this._mailService = mailService;
30
30
  this._subscription = eventHub.observe(MailEventKeys_1.SEND_MAIL_EVENT_KEY).subscribe({
31
31
  next: (payload) => {
32
- this._logger.debug(`Received mail event for recipient ${(0, archipel_platform_core_1.maskSensitive)(payload.recipientEmail)} with subject "${(0, archipel_platform_core_1.maskSensitive)(payload.subject)}"`);
32
+ this._logger.debug(`Received mail event for recipient ${(0, archipel_platform_core_1.maskSensitive)(payload.recipientEmail)} ` +
33
+ `with template "${payload.templateName}"${payload.subject ? ` (subject override: "${(0, archipel_platform_core_1.maskSensitive)(payload.subject)}")` : ''}`);
33
34
  void this.handle(payload);
34
35
  },
35
36
  error: (err) => {
package/src/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export * from './events';
5
5
  export * from './MailModule';
6
6
  export * from './models/IMailAttachment';
7
7
  export * from './models/IMailTemplate';
8
+ export * from './models/IMailTemplateVariants';
9
+ export * from './models/MailTemplateFormat';
8
10
  export * from './ports/IMailTemplateRepository';
9
11
  export * from './services/MailService';
10
12
  export * from './services/MailVerificationService';
package/src/index.js CHANGED
@@ -8,6 +8,8 @@ tslib_1.__exportStar(require("./events"), exports);
8
8
  tslib_1.__exportStar(require("./MailModule"), exports);
9
9
  tslib_1.__exportStar(require("./models/IMailAttachment"), exports);
10
10
  tslib_1.__exportStar(require("./models/IMailTemplate"), exports);
11
+ tslib_1.__exportStar(require("./models/IMailTemplateVariants"), exports);
12
+ tslib_1.__exportStar(require("./models/MailTemplateFormat"), exports);
11
13
  tslib_1.__exportStar(require("./ports/IMailTemplateRepository"), exports);
12
14
  tslib_1.__exportStar(require("./services/MailService"), exports);
13
15
  tslib_1.__exportStar(require("./services/MailVerificationService"), exports);
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Represents the in-memory structure for a single template (multiple formats).
3
+ *
4
+ * @public
5
+ */
6
+ export interface IMailTemplateVariants {
7
+ subject?: string;
8
+ html?: string;
9
+ txt?: string;
10
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=IMailTemplateVariants.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Union type of all supported template formats.
3
+ *
4
+ * @public
5
+ */
6
+ export type MailTemplateFormat = 'html' | 'txt';
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=MailTemplateFormat.js.map
@@ -37,17 +37,21 @@ export declare class MailService {
37
37
  * Sends an email using a predefined template (HTML or text).
38
38
  * Automatically uses the template format (either 'html' or 'txt') based on the environment variable.
39
39
  *
40
+ * When no `subject` is provided in `mailOptions`, the subject is resolved from the
41
+ * stored template and interpolated with the given `templateParams` (industry-standard
42
+ * behavior matching Mailchimp/SendGrid/Postmark).
43
+ *
40
44
  * @public
41
45
  * @param mailOptions.from - Sender's email address (optional, defaults to config)
42
46
  * @param mailOptions.to - Recipient's email address
43
- * @param mailOptions.subject - Subject of the email
47
+ * @param mailOptions.subject - Subject of the email (optional — resolved from template if omitted)
44
48
  * @param templateOptions.templateName - Name of the template to be used
45
- * @param templateOptions.params - Parameters to inject into the template
49
+ * @param templateOptions.templateParams - Parameters to inject into the template
46
50
  */
47
51
  sendTemplate(mailOptions: {
48
52
  from?: string;
49
53
  to: string;
50
- subject: string;
54
+ subject?: string;
51
55
  }, templateOptions: {
52
56
  templateName: string;
53
57
  templateParams: Record<string, string | number | boolean | Date | undefined | null>;
@@ -62,17 +62,26 @@ let MailService = class MailService {
62
62
  * Sends an email using a predefined template (HTML or text).
63
63
  * Automatically uses the template format (either 'html' or 'txt') based on the environment variable.
64
64
  *
65
+ * When no `subject` is provided in `mailOptions`, the subject is resolved from the
66
+ * stored template and interpolated with the given `templateParams` (industry-standard
67
+ * behavior matching Mailchimp/SendGrid/Postmark).
68
+ *
65
69
  * @public
66
70
  * @param mailOptions.from - Sender's email address (optional, defaults to config)
67
71
  * @param mailOptions.to - Recipient's email address
68
- * @param mailOptions.subject - Subject of the email
72
+ * @param mailOptions.subject - Subject of the email (optional — resolved from template if omitted)
69
73
  * @param templateOptions.templateName - Name of the template to be used
70
- * @param templateOptions.params - Parameters to inject into the template
74
+ * @param templateOptions.templateParams - Parameters to inject into the template
71
75
  */
72
76
  async sendTemplate(mailOptions, templateOptions) {
73
77
  const content = this._mailTemplateEngine.compileTemplate(templateOptions.templateName, templateOptions.templateParams, this._mailTemplateFormat);
74
78
  const isHtml = this._mailTemplateFormat === 'html';
75
- await this.send(mailOptions, content, isHtml);
79
+ const subject = mailOptions.subject ?? this._mailTemplateEngine.resolveSubject(templateOptions.templateName, templateOptions.templateParams);
80
+ if (!subject) {
81
+ throw new Error(`No subject provided and template '${templateOptions.templateName}' has no stored subject. ` +
82
+ 'Either pass a subject in mailOptions or ensure the template includes a subject.');
83
+ }
84
+ await this.send({ from: mailOptions.from, to: mailOptions.to, subject }, content, isHtml);
76
85
  }
77
86
  /**
78
87
  * Performs a minimal email address validation. Not exhaustive but filters obvious mistakes.
@@ -97,9 +106,7 @@ let MailService = class MailService {
97
106
  if (!IMailAttachment_1.ALLOWED_ATTACHMENT_MIME_TYPES.includes(attachment.contentType)) {
98
107
  throw new Error(`Unsupported attachment MIME type: '${attachment.contentType}'`);
99
108
  }
100
- const size = typeof attachment.content === 'string'
101
- ? Buffer.byteLength(attachment.content, 'utf-8')
102
- : attachment.content.length;
109
+ const size = typeof attachment.content === 'string' ? Buffer.byteLength(attachment.content, 'utf-8') : attachment.content.length;
103
110
  if (size > IMailAttachment_1.MAX_ATTACHMENT_SIZE_BYTES) {
104
111
  throw new Error(`Attachment '${attachment.filename}' exceeds maximum size of ${IMailAttachment_1.MAX_ATTACHMENT_SIZE_BYTES} bytes`);
105
112
  }
@@ -1,6 +1,6 @@
1
1
  import { ContentTemplateEngine } from '@breadstone/archipel-platform-core';
2
2
  import { OnModuleInit } from '@nestjs/common';
3
- import { MailTemplateFormat } from '../tokens/MailTokens';
3
+ import type { MailTemplateFormat } from '../models/MailTemplateFormat';
4
4
  import { TemplateFetchStrategyBase } from './strategies/abstracts/TemplateFetchStrategyBase';
5
5
  /**
6
6
  * The `MailTemplateEngine` class.
@@ -35,6 +35,15 @@ export declare class MailTemplateEngine implements OnModuleInit {
35
35
  * @returns The compiled template as a string.
36
36
  */
37
37
  compileTemplate(templateKey: string, params: Record<string, unknown>, format: MailTemplateFormat): string;
38
+ /**
39
+ * Resolves and interpolates the subject line from a stored template.
40
+ *
41
+ * @public
42
+ * @param templateKey The key of the template.
43
+ * @param params The parameters to insert into the subject.
44
+ * @returns The compiled subject string, or `undefined` if no subject is stored.
45
+ */
46
+ resolveSubject(templateKey: string, params: Record<string, unknown>): string | undefined;
38
47
  private escapeHtmlParams;
39
48
  private escapeHtml;
40
49
  }
@@ -66,6 +66,21 @@ let MailTemplateEngine = class MailTemplateEngine {
66
66
  throw error;
67
67
  }
68
68
  }
69
+ /**
70
+ * Resolves and interpolates the subject line from a stored template.
71
+ *
72
+ * @public
73
+ * @param templateKey The key of the template.
74
+ * @param params The parameters to insert into the subject.
75
+ * @returns The compiled subject string, or `undefined` if no subject is stored.
76
+ */
77
+ resolveSubject(templateKey, params) {
78
+ const templateVariants = this._templates[templateKey];
79
+ if (!templateVariants?.subject) {
80
+ return undefined;
81
+ }
82
+ return this._contentTemplateEngine.compileTemplate(templateVariants.subject, params);
83
+ }
69
84
  escapeHtmlParams(params) {
70
85
  const escaped = {};
71
86
  for (const [key, value] of Object.entries(params)) {
@@ -74,12 +89,7 @@ let MailTemplateEngine = class MailTemplateEngine {
74
89
  return escaped;
75
90
  }
76
91
  escapeHtml(text) {
77
- return text
78
- .replace(/&/g, '&amp;')
79
- .replace(/</g, '&lt;')
80
- .replace(/>/g, '&gt;')
81
- .replace(/"/g, '&quot;')
82
- .replace(/'/g, '&#39;');
92
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
83
93
  }
84
94
  };
85
95
  exports.MailTemplateEngine = MailTemplateEngine;
@@ -1,3 +1,4 @@
1
+ import type { IMailTemplateVariants } from '../../../models/IMailTemplateVariants';
1
2
  /**
2
3
  * Represents the base class for template fetch strategies.
3
4
  *
@@ -17,8 +18,5 @@ export declare abstract class TemplateFetchStrategyBase {
17
18
  * @public
18
19
  * @abstract
19
20
  */
20
- abstract load(): Promise<Record<string, {
21
- html?: string;
22
- txt?: string;
23
- }>>;
21
+ abstract load(): Promise<Record<string, IMailTemplateVariants>>;
24
22
  }
@@ -1,5 +1,5 @@
1
1
  import { BlobService } from '@breadstone/archipel-platform-blob-storage';
2
- import { IMailTemplateVariants } from '../../../tokens/MailTokens';
2
+ import type { IMailTemplateVariants } from '../../../models/IMailTemplateVariants';
3
3
  import { TemplateFetchStrategyBase } from '../abstracts/TemplateFetchStrategyBase';
4
4
  /**
5
5
  * The `BlobTemplateFetchStrategy` class.
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  // #region Imports
3
+ var BlobTemplateFetchStrategy_1;
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
5
  exports.BlobTemplateFetchStrategy = void 0;
6
+ const tslib_1 = require("tslib");
5
7
  const archipel_platform_blob_storage_1 = require("@breadstone/archipel-platform-blob-storage");
6
8
  const common_1 = require("@nestjs/common");
7
9
  const node_path_1 = require("node:path");
@@ -12,7 +14,7 @@ const TemplateFetchStrategyBase_1 = require("../abstracts/TemplateFetchStrategyB
12
14
  *
13
15
  * @public
14
16
  */
15
- class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetchStrategyBase {
17
+ let BlobTemplateFetchStrategy = BlobTemplateFetchStrategy_1 = class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetchStrategyBase {
16
18
  // #endregion
17
19
  // #region Ctor
18
20
  /**
@@ -22,7 +24,7 @@ class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetc
22
24
  */
23
25
  constructor(blobService) {
24
26
  super();
25
- this._logger = new common_1.Logger(BlobTemplateFetchStrategy.name);
27
+ this._logger = new common_1.Logger(BlobTemplateFetchStrategy_1.name);
26
28
  this._blobService = blobService;
27
29
  }
28
30
  // #endregion
@@ -51,6 +53,10 @@ class BlobTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetc
51
53
  this._logger.log('Templates loaded from blob storage');
52
54
  return templates;
53
55
  }
54
- }
56
+ };
55
57
  exports.BlobTemplateFetchStrategy = BlobTemplateFetchStrategy;
58
+ exports.BlobTemplateFetchStrategy = BlobTemplateFetchStrategy = BlobTemplateFetchStrategy_1 = tslib_1.__decorate([
59
+ (0, common_1.Injectable)(),
60
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_blob_storage_1.BlobService])
61
+ ], BlobTemplateFetchStrategy);
56
62
  //# sourceMappingURL=BlobTemplateFetchStrategy.js.map
@@ -1,5 +1,5 @@
1
+ import type { IMailTemplateVariants } from '../../../models/IMailTemplateVariants';
1
2
  import type { IMailTemplateRepository } from '../../../ports/IMailTemplateRepository';
2
- import type { IMailTemplateVariants } from '../../../tokens/MailTokens';
3
3
  import { TemplateFetchStrategyBase } from '../abstracts/TemplateFetchStrategyBase';
4
4
  /**
5
5
  * Template fetch strategy that loads templates from a database via the
@@ -44,6 +44,9 @@ let DatabaseTemplateFetchStrategy = DatabaseTemplateFetchStrategy_1 = class Data
44
44
  templates[key] = {};
45
45
  }
46
46
  // Only set if not already filled (first match wins — default locale preferred)
47
+ if (template.subject && !templates[key].subject) {
48
+ templates[key].subject = template.subject;
49
+ }
47
50
  if (template.htmlBody && !templates[key].html) {
48
51
  templates[key].html = template.htmlBody;
49
52
  }
@@ -1,25 +1,23 @@
1
1
  import { ResourceManager } from '@breadstone/archipel-platform-resources';
2
- import { IMailTemplateVariants } from '../../../tokens/MailTokens';
2
+ import type { IMailTemplateVariants } from '../../../models/IMailTemplateVariants';
3
3
  import { TemplateFetchStrategyBase } from '../abstracts/TemplateFetchStrategyBase';
4
4
  /**
5
5
  * The `FileTemplateFetchStrategy` class.
6
6
  *
7
+ * Loads mail templates from the file system via `ResourceManager`.
8
+ * Template names are injected via `MAIL_TEMPLATE_NAMES_TOKEN` — defaults to an empty array.
9
+ *
7
10
  * @public
8
11
  */
9
12
  export declare class FileTemplateFetchStrategy extends TemplateFetchStrategyBase {
10
13
  private readonly _resourceManager;
14
+ private readonly _templateNames;
11
15
  private readonly _logger;
12
- constructor(resourceManager: ResourceManager);
16
+ constructor(resourceManager: ResourceManager, templateNames: ReadonlyArray<string>);
13
17
  /**
14
18
  * Loads mail templates from the file system.
15
19
  *
16
20
  * @public
17
21
  */
18
22
  load(): Promise<Record<string, IMailTemplateVariants>>;
19
- /**
20
- * Returns the list of known template names.
21
- *
22
- * @private
23
- */
24
- private getTemplateNames;
25
23
  }
@@ -6,20 +6,25 @@ exports.FileTemplateFetchStrategy = void 0;
6
6
  const tslib_1 = require("tslib");
7
7
  const archipel_platform_resources_1 = require("@breadstone/archipel-platform-resources");
8
8
  const common_1 = require("@nestjs/common");
9
+ const MailTokens_1 = require("../../../tokens/MailTokens");
9
10
  const TemplateFetchStrategyBase_1 = require("../abstracts/TemplateFetchStrategyBase");
10
11
  // #endregion
11
12
  /**
12
13
  * The `FileTemplateFetchStrategy` class.
13
14
  *
15
+ * Loads mail templates from the file system via `ResourceManager`.
16
+ * Template names are injected via `MAIL_TEMPLATE_NAMES_TOKEN` — defaults to an empty array.
17
+ *
14
18
  * @public
15
19
  */
16
20
  let FileTemplateFetchStrategy = FileTemplateFetchStrategy_1 = class FileTemplateFetchStrategy extends TemplateFetchStrategyBase_1.TemplateFetchStrategyBase {
17
21
  // #endregion
18
22
  // #region Ctor
19
- constructor(resourceManager) {
23
+ constructor(resourceManager, templateNames) {
20
24
  super();
21
25
  this._logger = new common_1.Logger(FileTemplateFetchStrategy_1.name);
22
26
  this._resourceManager = resourceManager;
27
+ this._templateNames = templateNames;
23
28
  }
24
29
  // #endregion
25
30
  // #region Methods
@@ -30,9 +35,8 @@ let FileTemplateFetchStrategy = FileTemplateFetchStrategy_1 = class FileTemplate
30
35
  */
31
36
  async load() {
32
37
  const templates = {};
33
- const templateNames = this.getTemplateNames();
34
38
  let templateCount = 0;
35
- for (const templateName of templateNames) {
39
+ for (const templateName of this._templateNames) {
36
40
  if (!templates[templateName]) {
37
41
  templates[templateName] = {};
38
42
  }
@@ -52,20 +56,11 @@ let FileTemplateFetchStrategy = FileTemplateFetchStrategy_1 = class FileTemplate
52
56
  this._logger.log(`${templateCount} Templates loaded from file system`);
53
57
  return templates;
54
58
  }
55
- // #endregion
56
- // #region Private Methods
57
- /**
58
- * Returns the list of known template names.
59
- *
60
- * @private
61
- */
62
- getTemplateNames() {
63
- return ['AppointmentInvitation', 'AppointmentUpdate', 'AuthForgotPassword', 'AuthRegister', 'AuthVerify'];
64
- }
65
59
  };
66
60
  exports.FileTemplateFetchStrategy = FileTemplateFetchStrategy;
67
61
  exports.FileTemplateFetchStrategy = FileTemplateFetchStrategy = FileTemplateFetchStrategy_1 = tslib_1.__decorate([
68
62
  (0, common_1.Injectable)(),
69
- tslib_1.__metadata("design:paramtypes", [archipel_platform_resources_1.ResourceManager])
63
+ tslib_1.__param(1, (0, common_1.Inject)(MailTokens_1.MAIL_TEMPLATE_NAMES_TOKEN)),
64
+ tslib_1.__metadata("design:paramtypes", [archipel_platform_resources_1.ResourceManager, Array])
70
65
  ], FileTemplateFetchStrategy);
71
66
  //# sourceMappingURL=FileTemplateFetchStrategy.js.map
@@ -6,14 +6,4 @@
6
6
  export declare const MAIL_TEMPLATE_FETCH_STRATEGY_TOKEN: unique symbol;
7
7
  export declare const MAIL_DELIVERY_STRATEGY_TOKEN: unique symbol;
8
8
  export declare const MAIL_TEMPLATE_REPOSITORY_TOKEN: unique symbol;
9
- /**
10
- * Union type of all supported template formats.
11
- */
12
- export type MailTemplateFormat = 'html' | 'txt';
13
- /**
14
- * Represents the in-memory structure for a single template (multiple formats).
15
- */
16
- export interface IMailTemplateVariants {
17
- html?: string;
18
- txt?: string;
19
- }
9
+ export declare const MAIL_TEMPLATE_NAMES_TOKEN: unique symbol;
@@ -7,8 +7,9 @@
7
7
  */
8
8
  // #endregion
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.MAIL_TEMPLATE_REPOSITORY_TOKEN = exports.MAIL_DELIVERY_STRATEGY_TOKEN = exports.MAIL_TEMPLATE_FETCH_STRATEGY_TOKEN = void 0;
10
+ exports.MAIL_TEMPLATE_NAMES_TOKEN = exports.MAIL_TEMPLATE_REPOSITORY_TOKEN = exports.MAIL_DELIVERY_STRATEGY_TOKEN = exports.MAIL_TEMPLATE_FETCH_STRATEGY_TOKEN = void 0;
11
11
  exports.MAIL_TEMPLATE_FETCH_STRATEGY_TOKEN = Symbol('MailTemplateFetchStrategy');
12
12
  exports.MAIL_DELIVERY_STRATEGY_TOKEN = Symbol('MailDeliveryStrategy');
13
13
  exports.MAIL_TEMPLATE_REPOSITORY_TOKEN = Symbol('MailTemplateRepository');
14
+ exports.MAIL_TEMPLATE_NAMES_TOKEN = Symbol('MailTemplateNames');
14
15
  //# sourceMappingURL=MailTokens.js.map