@venizia/ignis-docs 0.2.0 → 0.2.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +22 -11
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +6 -2
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +182 -93
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +107 -322
  26. package/content/extensions/components/authentication/api.md +454 -603
  27. package/content/extensions/components/authentication/errors.md +121 -498
  28. package/content/extensions/components/authentication/index.md +88 -801
  29. package/content/extensions/components/authentication/usage.md +207 -956
  30. package/content/extensions/components/authorization/api.md +736 -656
  31. package/content/extensions/components/authorization/errors.md +168 -206
  32. package/content/extensions/components/authorization/index.md +82 -797
  33. package/content/extensions/components/authorization/usage.md +194 -527
  34. package/content/extensions/components/health-check.md +71 -243
  35. package/content/extensions/components/mail/api.md +504 -287
  36. package/content/extensions/components/mail/errors.md +73 -61
  37. package/content/extensions/components/mail/index.md +96 -467
  38. package/content/extensions/components/mail/usage.md +130 -172
  39. package/content/extensions/components/request-tracker.md +66 -173
  40. package/content/extensions/components/socket-io/api.md +195 -13
  41. package/content/extensions/components/socket-io/errors.md +3 -3
  42. package/content/extensions/components/socket-io/index.md +50 -337
  43. package/content/extensions/components/socket-io/usage.md +143 -26
  44. package/content/extensions/components/static-asset/api.md +410 -142
  45. package/content/extensions/components/static-asset/errors.md +110 -53
  46. package/content/extensions/components/static-asset/index.md +79 -608
  47. package/content/extensions/components/static-asset/usage.md +180 -300
  48. package/content/extensions/components/websocket/api.md +275 -399
  49. package/content/extensions/components/websocket/errors.md +47 -56
  50. package/content/extensions/components/websocket/index.md +74 -407
  51. package/content/extensions/components/websocket/usage.md +110 -341
  52. package/content/extensions/helpers/cron/index.md +51 -160
  53. package/content/extensions/helpers/crypto/index.md +62 -483
  54. package/content/extensions/helpers/crypto/reference.md +456 -0
  55. package/content/extensions/helpers/env/index.md +60 -178
  56. package/content/extensions/helpers/error/index.md +221 -207
  57. package/content/extensions/helpers/inversion/index.md +65 -556
  58. package/content/extensions/helpers/inversion/reference.md +522 -0
  59. package/content/extensions/helpers/kafka/admin.md +20 -1
  60. package/content/extensions/helpers/kafka/compile-binary.md +41 -35
  61. package/content/extensions/helpers/kafka/consumer.md +54 -20
  62. package/content/extensions/helpers/kafka/examples.md +21 -16
  63. package/content/extensions/helpers/kafka/index.md +80 -610
  64. package/content/extensions/helpers/kafka/producer.md +134 -5
  65. package/content/extensions/helpers/kafka/schema-registry.md +45 -70
  66. package/content/extensions/helpers/logger/hf-logger.md +193 -0
  67. package/content/extensions/helpers/logger/index.md +64 -563
  68. package/content/extensions/helpers/logger/pino.md +85 -0
  69. package/content/extensions/helpers/logger/reference.md +746 -0
  70. package/content/extensions/helpers/network/api.md +241 -195
  71. package/content/extensions/helpers/network/index.md +72 -530
  72. package/content/extensions/helpers/queue/index.md +72 -900
  73. package/content/extensions/helpers/queue/reference.md +467 -0
  74. package/content/extensions/helpers/redis/index.md +73 -645
  75. package/content/extensions/helpers/redis/reference.md +727 -0
  76. package/content/extensions/helpers/secrets/index.md +66 -0
  77. package/content/extensions/helpers/socket-io/api.md +305 -203
  78. package/content/extensions/helpers/socket-io/index.md +66 -432
  79. package/content/extensions/helpers/storage/api.md +564 -462
  80. package/content/extensions/helpers/storage/index.md +77 -573
  81. package/content/extensions/helpers/types/index.md +66 -499
  82. package/content/extensions/helpers/types/reference.md +650 -0
  83. package/content/extensions/helpers/uid/index.md +58 -227
  84. package/content/extensions/helpers/websocket/api.md +329 -216
  85. package/content/extensions/helpers/websocket/index.md +65 -503
  86. package/content/extensions/helpers/worker-thread/index.md +58 -396
  87. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  88. package/content/guides/core-concepts/persistent/models.md +1 -1
  89. package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
  90. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  91. package/content/guides/core-concepts/secrets-vault.md +177 -0
  92. package/content/guides/core-concepts/services.md +1 -1
  93. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  94. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  95. package/content/guides/tutorials/ecommerce-api.md +3 -8
  96. package/content/references/base/application.md +1 -1
  97. package/content/references/base/connectors.md +79 -136
  98. package/content/references/base/datasources-reference.md +599 -0
  99. package/content/references/base/datasources.md +84 -444
  100. package/content/references/base/dependency-injection.md +17 -39
  101. package/content/references/base/filter-system/application-usage.md +69 -121
  102. package/content/references/base/filter-system/array-operators.md +12 -0
  103. package/content/references/base/filter-system/comparison-operators.md +12 -0
  104. package/content/references/base/filter-system/default-filter.md +136 -348
  105. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  106. package/content/references/base/filter-system/index.md +106 -257
  107. package/content/references/base/filter-system/json-filtering.md +12 -2
  108. package/content/references/base/filter-system/list-operators.md +16 -2
  109. package/content/references/base/filter-system/logical-operators.md +13 -0
  110. package/content/references/base/filter-system/null-operators.md +13 -0
  111. package/content/references/base/filter-system/pattern-matching.md +12 -0
  112. package/content/references/base/filter-system/quick-reference.md +11 -2
  113. package/content/references/base/filter-system/range-operators.md +12 -0
  114. package/content/references/base/filter-system/tips.md +70 -133
  115. package/content/references/base/filter-system/use-cases.md +156 -233
  116. package/content/references/base/middlewares.md +35 -21
  117. package/content/references/base/models-reference.md +886 -0
  118. package/content/references/base/models.md +80 -1452
  119. package/content/references/base/repositories/advanced.md +156 -192
  120. package/content/references/base/repositories/index.md +77 -650
  121. package/content/references/base/repositories/mixins.md +22 -18
  122. package/content/references/base/repositories/relations.md +123 -171
  123. package/content/references/base/repositories/soft-deletable.md +58 -56
  124. package/content/references/base/secrets.md +263 -0
  125. package/content/references/base/services.md +2 -2
  126. package/content/references/configuration/environment-variables.md +48 -4
  127. package/content/references/configuration/index.md +49 -31
  128. package/content/references/quick-reference.md +3 -16
  129. package/content/references/utilities/crypto.md +35 -76
  130. package/content/references/utilities/date.md +33 -73
  131. package/content/references/utilities/index.md +1 -1
  132. package/content/references/utilities/jsx-reference.md +298 -0
  133. package/content/references/utilities/jsx.md +82 -525
  134. package/content/references/utilities/module.md +29 -62
  135. package/content/references/utilities/parse.md +34 -64
  136. package/content/references/utilities/performance.md +33 -58
  137. package/content/references/utilities/promise.md +28 -62
  138. package/content/references/utilities/request.md +57 -218
  139. package/content/references/utilities/schema.md +43 -137
  140. package/content/references/utilities/statuses-reference.md +361 -0
  141. package/content/references/utilities/statuses.md +63 -667
  142. package/package.json +8 -8
@@ -1,534 +1,163 @@
1
- # Mail -- Setup & Configuration
2
-
3
- > Flexible email sending system with support for multiple transports (Nodemailer, Mailgun, custom), template-based rendering with mustache-style variable syntax, and queue-based processing via Direct, Internal Queue, or BullMQ executors.
4
-
5
- ## Quick Reference
6
-
7
- | Item | Value |
8
- |------|-------|
9
- | **Package** | `@venizia/ignis` |
10
- | **Class** | `MailComponent` |
11
- | **Runtimes** | Both |
12
-
13
- ### Key Components
14
-
15
- | Component | Purpose |
16
- | --------- | ------- |
17
- | **MailComponent** | Main component registering mail services, transporters, and executors |
18
- | **MailService** | Core service for sending emails, batch emails, and template-based emails |
19
- | **TemplateEngineService** | Simple template engine with <code v-pre>{{variable}}</code> syntax |
20
- | **NodemailerTransportHelper** | Nodemailer-based email transport implementation |
21
- | **MailgunTransportHelper** | Mailgun API-based email transport implementation |
22
- | **DirectMailExecutorHelper** | Execute email sending immediately without queue |
23
- | **InternalQueueMailExecutorHelper** | Queue emails using in-memory queue |
24
- | **BullMQMailExecutorHelper** | Queue emails using BullMQ for distributed processing |
25
- | **MailTransportProvider** | Factory provider that creates transport instances based on configuration |
26
- | **MailQueueExecutorProvider** | Factory provider that creates queue executor instances based on configuration |
27
- | **NumericCodeGenerator** | Generates cryptographically random numeric verification codes |
28
- | **RandomTokenGenerator** | Generates cryptographically random base64url tokens |
29
- | **DefaultVerificationDataGenerator** | Composes code + token generators into full verification data objects |
30
-
31
- ### Transport Providers
32
-
33
- | Provider | Value | When to Use |
34
- | -------- | ----- | ----------- |
35
- | **Nodemailer** | `MailProviders.NODEMAILER` | SMTP-based email sending (Gmail, SendGrid, etc.) |
36
- | **Mailgun** | `MailProviders.MAILGUN` | Mailgun API for transactional emails |
37
- | **Custom** | `MailProviders.CUSTOM` | Custom transport implementation |
38
-
39
- ### Queue Executor Types
40
-
41
- | Type | Value | When to Use |
42
- | ---- | ----- | ----------- |
43
- | **Direct** | `'direct'` | No queue, send immediately |
44
- | **Internal Queue** | `'internal-queue'` | In-memory queue for simple use cases |
45
- | **BullMQ** | `'bullmq'` | Redis-backed queue for distributed systems |
46
-
47
- #### Import Paths
48
- ```typescript
49
- import {
50
- MailComponent,
51
- MailKeys,
52
- MailProviders,
53
- MailErrorCodes,
54
- MailDefaults,
55
- MailQueueExecutorTypes,
56
- BullMQExecutorModes,
57
- MailService,
58
- TemplateEngineService,
59
- NumericCodeGenerator,
60
- RandomTokenGenerator,
61
- DefaultVerificationDataGenerator,
62
- MailTransportProvider,
63
- MailQueueExecutorProvider,
64
- } from '@venizia/ignis/mail';
65
-
66
- import type {
67
- TMailOptions,
68
- IBaseMailOptions,
69
- INodemailerMailOptions,
70
- IMailgunMailOptions,
71
- ICustomMailOptions,
72
- IGenericMailOptions,
73
- IMailService,
74
- IMailTemplateEngine,
75
- IMailMessage,
76
- IMailSendResult,
77
- IMailTransport,
78
- IMailAttachment,
79
- IMailQueueExecutor,
80
- IMailQueueExecutorConfig,
81
- IMailQueueOptions,
82
- IMailQueueResult,
83
- IMailProcessorResult,
84
- ITemplate,
85
- IVerificationCodeGenerator,
86
- IVerificationTokenGenerator,
87
- IVerificationDataGenerator,
88
- IVerificationData,
89
- IVerificationGenerationOptions,
90
- TMailProvider,
91
- TNodemailerConfig,
92
- TMailgunConfig,
93
- } from '@venizia/ignis/mail';
94
- ```
1
+ ---
2
+ title: Mail Component
3
+ description: Send email through pluggable transports (Nodemailer, Mailgun, custom) with templates, batch sending, and a pluggable queue executor
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Mail Component
95
8
 
96
- ## Setup
9
+ `MailComponent` wires a pluggable email transport (Nodemailer, Mailgun, or your own) into `MailService`, adding template rendering, batch sending, and an independent queue executor for verification-code/token flows.
97
10
 
98
- The recommended approach is to create a wrapper component that binds the mail options and queue executor config, then registers `MailComponent` internally.
11
+ ## In one example
99
12
 
100
- ### Step 1: Bind Configuration
13
+ Bind `MailKeys.MAIL_OPTIONS`, register `MailComponent`, then inject `IMailService` anywhere to send:
101
14
 
102
15
  ```typescript
103
- // src/components/mail/component.ts
104
- import {
105
- BaseApplication,
106
- BaseComponent,
107
- Binding,
108
- CoreBindings,
109
- inject,
110
- } from '@venizia/ignis';
111
- import { applicationEnvironment, toBoolean } from '@venizia/ignis-helpers';
16
+ import { BaseApplication, ValueOrPromise } from '@venizia/ignis';
112
17
  import { MailComponent, MailKeys, MailProviders } from '@venizia/ignis/mail';
113
18
 
114
- export class NodemailerComponent extends BaseComponent {
115
- constructor(
116
- @inject({ key: CoreBindings.APPLICATION_INSTANCE })
117
- protected application: BaseApplication,
118
- ) {
119
- super({
120
- scope: NodemailerComponent.name,
121
- initDefault: { enable: true, container: application },
122
- bindings: {
123
- // Configure mail transport options
124
- [MailKeys.MAIL_OPTIONS]: Binding.bind({
125
- key: MailKeys.MAIL_OPTIONS,
126
- }).toValue({
127
- provider: MailProviders.NODEMAILER,
128
- from: 'noreply@example.com',
129
- fromName: 'Example App',
130
- config: {
131
- host: applicationEnvironment.get<string>('APP_ENV_MAIL_HOST') ?? 'smtp.gmail.com',
132
- port: +(applicationEnvironment.get<number>('APP_ENV_MAIL_PORT') ?? 465),
133
- secure: toBoolean(applicationEnvironment.get<boolean>('APP_ENV_MAIL_SECURE') ?? true),
134
- auth: {
135
- type: 'oauth2',
136
- user: applicationEnvironment.get<string>('APP_ENV_MAIL_USER'),
137
- clientId: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_ID'),
138
- clientSecret: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_SECRET'),
139
- refreshToken: applicationEnvironment.get<string>('APP_ENV_MAIL_REFRESH_TOKEN'),
140
- },
141
- },
142
- }),
143
- // Configure queue executor
144
- [MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG]: Binding.bind({
145
- key: MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG,
146
- }).toValue({
147
- type: 'internal-queue',
148
- internalQueue: {
149
- identifier: 'mail-internal-queue',
150
- },
151
- }),
19
+ export class Application extends BaseApplication {
20
+ preConfigure(): ValueOrPromise<void> {
21
+ // MAIL_OPTIONS is the only binding MailComponent requires
22
+ this.bind({ key: MailKeys.MAIL_OPTIONS }).toValue({
23
+ provider: MailProviders.NODEMAILER,
24
+ from: 'noreply@example.com',
25
+ config: {
26
+ host: 'smtp.gmail.com',
27
+ port: 465,
28
+ secure: true,
29
+ auth: { user: process.env.APP_ENV_MAIL_USER, pass: process.env.APP_ENV_MAIL_PASS },
152
30
  },
153
31
  });
154
- }
155
-
156
- override async binding(): Promise<void> {
157
- this.logger.info('[binding] Binding mail component...');
158
32
 
159
- // Register the core MailComponent
160
- this.application.component(MailComponent);
161
-
162
- this.logger.info('[binding] Mail component initialized successfully');
33
+ this.component(MailComponent);
163
34
  }
164
35
  }
165
36
  ```
166
37
 
167
- ### Step 2: Register Component
168
-
169
38
  ```typescript
170
- // src/application.ts
171
- import { BaseApplication, ValueOrPromise } from '@venizia/ignis';
172
- import { NodemailerComponent } from './components/mail/component';
39
+ import { BaseService, inject } from '@venizia/ignis';
40
+ import { MailKeys, type IMailService } from '@venizia/ignis/mail';
173
41
 
174
- export class Application extends BaseApplication {
175
- preConfigure(): ValueOrPromise<void> {
176
- // Register the mail component
177
- this.component(NodemailerComponent);
42
+ export class UserService extends BaseService {
43
+ constructor(@inject({ key: MailKeys.MAIL_SERVICE }) private mailService: IMailService) {
44
+ super({ scope: UserService.name });
45
+ }
178
46
 
179
- // ... other components
47
+ async sendWelcomeEmail(email: string) {
48
+ return this.mailService.send({ to: email, subject: 'Welcome!', html: '<h1>Welcome!</h1>' });
180
49
  }
181
50
  }
182
51
  ```
183
52
 
184
- ## Configuration
53
+ `MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG` is optional -- omit it and `MailComponent` binds a `direct` executor (no queue) by default.
185
54
 
186
- ### Transport Options
55
+ ## How it works
187
56
 
188
- The `TMailOptions` configuration determines which email transport provider is used and how it's configured. It is a discriminated union of four variants.
57
+ - **One required binding.** `MailComponent.binding()` throws `Mail options not configured` if `MailKeys.MAIL_OPTIONS` is not bound before registration. Every other binding -- queue executor config, verification generators -- is optional with a working default.
58
+ - **Transport is a discriminated union.** `TMailOptions.provider` selects `NodemailerTransportHelper`, `MailgunTransportHelper`, or a `custom` object you supply that implements `IMailTransport` (`send()` + `verify()`). `MailTransportProvider` is the factory that switches on it and throws for an unsupported provider string.
59
+ - **`MailService` is the one sending entry point.** `send()`, `sendBatch()`, `sendTemplate()`, and `verify()` all validate first, then call the transport directly and synchronously, then normalize failures into `MailErrorCodes`. A validation error (400) passes through unchanged; only a throwing transport gets wrapped as `SEND_FAILED` (500) -- the built-in Nodemailer and Mailgun transports never throw, they return `{ success: false, error }` instead.
60
+ - **The queue executor is a separate subsystem, not a mail queue.** `IMailQueueExecutor` (`direct` / `internal-queue` / `bullmq`) only exposes `enqueueVerificationEmail()` and `setProcessor()` -- it never touches `MailService`. You must call `setProcessor()` with your own function (typically one that calls `mailService.send()` internally) before `enqueueVerificationEmail()` does anything.
61
+ - **Templates are a simple substitution engine.** `TemplateEngineService` stores templates in an in-memory `Map` and replaces <code v-pre>{{variable}}</code> placeholders (dot-notation for nested values). A missing value is logged and left as the literal placeholder text, not blanked out.
62
+ - **Startup logging never leaks credentials.** `MailComponent` logs only `mailOptions.provider` and `queueExecutorConfig.type` -- never the SMTP password, OAuth2 secret, API key, or Redis password nested inside them.
189
63
 
190
- **Nodemailer SMTP example:**
64
+ ## Common tasks
191
65
 
192
- ```typescript
193
- {
194
- provider: MailProviders.NODEMAILER,
195
- from: 'noreply@example.com',
196
- fromName: 'Example App',
197
- config: {
198
- host: 'smtp.gmail.com',
199
- port: 465,
200
- secure: true,
201
- auth: {
202
- user: 'your-email@gmail.com',
203
- pass: 'your-app-password',
204
- },
205
- },
206
- }
207
- ```
66
+ ### Send an email
208
67
 
209
- **Simple SMTP Authentication (e.g., Gmail with app password):**
68
+ Inject `IMailService` via `MailKeys.MAIL_SERVICE` and call `send()`.
210
69
 
211
70
  ```typescript
212
- // Simple SMTP Authentication (e.g., Gmail with app password)
213
- this.bind<TMailOptions>({ key: MailKeys.MAIL_OPTIONS }).toValue({
214
- provider: 'nodemailer',
215
- from: 'noreply@example.com',
216
- fromName: 'My App',
217
- config: {
218
- host: 'smtp.gmail.com',
219
- port: 465,
220
- secure: true,
221
- auth: {
222
- user: process.env.APP_ENV_MAIL_USER,
223
- pass: process.env.APP_ENV_MAIL_PASS,
224
- },
225
- },
71
+ const result = await this.mailService.send({
72
+ to: 'user@example.com',
73
+ subject: 'Welcome!',
74
+ html: '<h1>Welcome!</h1>',
75
+ text: 'Welcome!',
226
76
  });
227
77
  ```
228
78
 
229
- **Mailgun example:**
79
+ ### Send a batch of emails
230
80
 
231
- ```typescript
232
- {
233
- provider: MailProviders.MAILGUN,
234
- from: 'noreply@example.com',
235
- fromName: 'Example App',
236
- config: {
237
- apiKey: process.env.MAILGUN_API_KEY,
238
- domain: 'mg.example.com',
239
- host: 'api.eu.mailgun.net', // Optional: EU region
240
- },
241
- }
242
- ```
243
-
244
- **Generic provider example:**
245
-
246
- The `IGenericMailOptions` variant allows any arbitrary provider string with a `Record<string, AnyType>` config. This is the catch-all for providers not covered by the named variants:
81
+ `sendBatch()` runs each message through `send()` with bounded concurrency (default `5`).
247
82
 
248
83
  ```typescript
249
- {
250
- provider: 'sendgrid',
251
- from: 'noreply@example.com',
252
- config: {
253
- apiKey: process.env.SENDGRID_API_KEY,
254
- // Any key-value pairs accepted
255
- },
256
- }
84
+ const results = await this.mailService.sendBatch(messages, { concurrency: 5 });
257
85
  ```
258
86
 
259
- > [!WARNING]
260
- > The `IGenericMailOptions` variant will fall through to the `default` case in `MailTransportProvider` and throw `Unsupported mail provider: <provider>` unless the transport provider is replaced with a custom one that handles the provider string. This variant exists for extensibility -- you must bind a custom `MailTransportProvider` that knows how to handle your provider string.
87
+ ### Send a registered template
261
88
 
262
- **OAuth2 with environment variables:**
89
+ Register a template on `IMailTemplateEngine`, then send it through `IMailService`.
263
90
 
264
91
  ```typescript
265
- {
266
- provider: MailProviders.NODEMAILER,
267
- from: applicationEnvironment.get<string>('APP_ENV_MAIL_FROM') ?? 'noreply@example.com',
268
- fromName: applicationEnvironment.get<string>('APP_ENV_MAIL_FROM_NAME') ?? 'Example App',
269
- config: {
270
- host: applicationEnvironment.get<string>('APP_ENV_MAIL_HOST') ?? 'smtp.gmail.com',
271
- port: +(applicationEnvironment.get<number>('APP_ENV_MAIL_PORT') ?? 465),
272
- secure: toBoolean(applicationEnvironment.get<boolean>('APP_ENV_MAIL_SECURE') ?? true),
273
- auth: {
274
- type: 'oauth2',
275
- user: applicationEnvironment.get<string>('APP_ENV_MAIL_USER'),
276
- clientId: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_ID'),
277
- clientSecret: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_SECRET'),
278
- refreshToken: applicationEnvironment.get<string>('APP_ENV_MAIL_REFRESH_TOKEN'),
279
- },
280
- },
281
- }
282
- ```
283
-
284
- **Example `.env` file for Nodemailer with OAuth2:**
285
-
286
- ```
287
- APP_ENV_MAIL_HOST=smtp.gmail.com
288
- APP_ENV_MAIL_PORT=465
289
- APP_ENV_MAIL_SECURE=true
290
- APP_ENV_MAIL_USER=your-email@gmail.com
291
- APP_ENV_MAIL_CLIENT_ID=your-oauth2-client-id
292
- APP_ENV_MAIL_CLIENT_SECRET=your-oauth2-client-secret
293
- APP_ENV_MAIL_REFRESH_TOKEN=your-oauth2-refresh-token
294
- ```
295
-
296
- > [!TIP]
297
- > For Gmail OAuth2, follow [Google's OAuth2 setup guide](https://developers.google.com/gmail/api/auth/web-server) to obtain client ID, secret, and refresh token.
298
-
299
- ### Queue Executor Options
300
-
301
- The `IMailQueueExecutorConfig` configuration determines how emails are queued and processed.
302
-
303
- **Direct execution (no queue):**
92
+ this.templateEngine.registerTemplate({
93
+ name: 'welcome-email',
94
+ content: '<h1>Welcome {{userName}}!</h1>',
95
+ options: { subject: 'Welcome to {{appName}}' },
96
+ });
304
97
 
305
- ```typescript
306
- {
307
- type: 'direct',
308
- }
98
+ await this.mailService.sendTemplate({
99
+ templateName: 'welcome-email',
100
+ data: { userName: 'Jane', appName: 'My App' },
101
+ recipients: 'user@example.com',
102
+ });
309
103
  ```
310
104
 
311
- **Internal queue (in-memory):**
312
-
313
- ```typescript
314
- {
315
- type: 'internal-queue',
316
- internalQueue: {
317
- identifier: 'mail-internal-queue',
318
- },
319
- }
320
- ```
105
+ ### Switch to Mailgun
321
106
 
322
- **BullMQ (Redis-backed):**
107
+ `config` must carry `username`, `key`, and `domain` -- the transport validates them eagerly, on construction.
323
108
 
324
109
  ```typescript
325
110
  {
326
- type: 'bullmq',
327
- bullmq: {
328
- redis: {
329
- host: 'localhost',
330
- port: 6379,
331
- password: 'your-redis-password',
332
- },
333
- queue: {
334
- identifier: 'mail-queue',
335
- name: 'mail-queue',
336
- },
337
- mode: 'both', // 'queue-only', 'worker-only', or 'both'
338
- },
111
+ provider: MailProviders.MAILGUN,
112
+ from: 'noreply@example.com',
113
+ config: { username: 'api', key: process.env.MAILGUN_API_KEY, domain: 'mg.example.com' },
339
114
  }
340
115
  ```
341
116
 
342
- > [!NOTE]
343
- > - **`'queue-only'`** -- Only enqueues jobs, does not process them (useful for web servers that offload to workers)
344
- > - **`'worker-only'`** -- Only processes jobs, does not enqueue (useful for dedicated worker processes)
345
- > - **`'both'`** -- Both enqueues and processes jobs (simplest setup for single-instance apps)
346
-
347
- > [!NOTE]
348
- > Choose the right queue executor for your environment:
349
- > - **`direct`** -- Development or low-volume applications. No queueing overhead.
350
- > - **`internal-queue`** -- Single-instance applications with moderate volume. In-memory queue with retry support.
351
- > - **`bullmq`** -- Distributed systems or high-volume applications. Redis-backed with configurable concurrency, priority, and backoff.
117
+ ### Queue verification emails
352
118
 
353
- #### BullMQ Dynamic Worker Management
354
-
355
- The `BullMQMailExecutorHelper` supports dynamic worker scaling at runtime. Workers can be added and removed without restarting the application:
119
+ Get the queue executor instance, register a processor, then enqueue.
356
120
 
357
121
  ```typescript
358
- const executor = this.application.get<BullMQMailExecutorHelper>({
122
+ const executor = this.application.get<IMailQueueExecutor>({
359
123
  key: MailKeys.MAIL_QUEUE_EXECUTOR_INSTANCE,
360
124
  });
361
125
 
362
- // Add a new worker with custom concurrency
363
- executor.addWorker({
364
- workerIdentifier: 'mail-queue-worker-extra',
365
- concurrency: 10,
366
- lockDuration: 60000, // 60 seconds
126
+ executor.setProcessor(async email => {
127
+ await this.mailService.send({ to: email, subject: 'Verify', html: '...' });
128
+ return { success: true, message: 'Sent', expiresInMinutes: 10 };
367
129
  });
368
130
 
369
- // Check current worker count
370
- const count = executor.getWorkerCount(); // e.g. 2
371
-
372
- // Check current mode
373
- const mode = executor.getMode(); // e.g. 'both'
374
-
375
- // Remove a specific worker by index
376
- await executor.removeWorker(1);
377
-
378
- // Remove all workers
379
- await executor.clearWorkers();
131
+ await executor.enqueueVerificationEmail('user@example.com');
380
132
  ```
381
133
 
382
- The `setProcessor()` method on BullMQ also accepts an optional second argument for worker configuration:
134
+ ### Generate a verification code and token
383
135
 
384
- ```typescript
385
- await executor.setProcessor(
386
- async (email: string) => {
387
- // your processing logic
388
- return { success: true, message: 'Sent', expiresInMinutes: 10 };
389
- },
390
- {
391
- numberOfWorkers: 3, // Spawn 3 workers (default: 1)
392
- concurrencyPerWorker: 10, // Each worker handles 10 concurrent jobs (default: 5)
393
- lockDuration: 60000, // Job lock duration in ms (default: 30000)
394
- },
395
- );
396
- ```
397
-
398
- #### Full Transport Options Interface
399
-
400
- The `TMailOptions` union type has four variants. All extend `IBaseMailOptions`:
136
+ `MAIL_VERIFICATION_DATA_GENERATOR` composes a numeric code and a base64url token in one call.
401
137
 
402
138
  ```typescript
403
- interface IBaseMailOptions {
404
- from?: string;
405
- fromName?: string;
406
- }
407
-
408
- interface INodemailerMailOptions extends IBaseMailOptions {
409
- provider: 'nodemailer';
410
- config: TNodemailerConfig; // SMTPTransport | SMTPTransport.Options | string
411
- }
412
-
413
- interface IMailgunMailOptions extends IBaseMailOptions {
414
- provider: 'mailgun';
415
- config: TMailgunConfig; // { domain: string; [key: string]: any }
416
- }
417
-
418
- interface ICustomMailOptions extends IBaseMailOptions {
419
- provider: 'custom';
420
- config: IMailTransport; // Must implement send() and verify()
421
- }
422
-
423
- interface IGenericMailOptions extends IBaseMailOptions {
424
- provider: string;
425
- config: Record<string, AnyType>;
426
- }
427
-
428
- type TMailOptions =
429
- | INodemailerMailOptions
430
- | IMailgunMailOptions
431
- | ICustomMailOptions
432
- | IGenericMailOptions;
139
+ const data = this.verificationGenerator.generateVerificationData({
140
+ codeLength: 6,
141
+ tokenBytes: 32,
142
+ codeExpiryMinutes: 10,
143
+ tokenExpiryHours: 24,
144
+ });
433
145
  ```
434
146
 
435
- #### Full Queue Executor Config Interface
436
- ```typescript
437
- interface IMailQueueExecutorConfig {
438
- type: TConstValue<typeof MailQueueExecutorTypes>; // 'direct' | 'internal-queue' | 'bullmq'
439
- internalQueue?: {
440
- identifier: string;
441
- };
442
- bullmq?: {
443
- redis: IRedisHelperOptions;
444
- queue: {
445
- identifier: string;
446
- name: string;
447
- };
448
- mode: TConstValue<typeof BullMQExecutorModes>; // REQUIRED: 'queue-only' | 'worker-only' | 'both'
449
- };
450
- }
451
- ```
147
+ ## See also
452
148
 
453
- > [!IMPORTANT]
454
- > The `bullmq.mode` field is **required** when `type` is `'bullmq'`. There is no default value -- you must explicitly choose `'queue-only'`, `'worker-only'`, or `'both'`.
455
-
456
- #### Nodemailer Transport Capabilities
457
- - Basic SMTP authentication (`user`/`pass`)
458
- - OAuth2 authentication (client ID, secret, refresh token)
459
- - TLS/SSL connections
460
- - Custom SMTP headers
461
- - Connection pooling
462
- - Attachment handling (file path, buffer, stream)
463
- - HTML and plain text content
464
- - SMTP connection verification via `verify()` method
465
- - Peer dependency validation via `validateModule()` (requires `nodemailer` to be installed)
466
-
467
- #### Mailgun Transport Capabilities
468
- - US and EU regional endpoints
469
- - API key authentication
470
- - HTML and plain text emails
471
- - Inline attachments with CID
472
- - Custom headers (auto-prefixed with `h:`)
473
- - Batch sending via Mailgun's API
474
- - Test mode verification via `verify()` method (uses `o:testmode` flag)
475
- - Peer dependency validation via `validateModule()` (requires `mailgun.js` to be installed)
476
-
477
- ### Constants
478
-
479
- | Constant | Value | Description |
480
- |----------|-------|-------------|
481
- | `MailDefaults.BATCH_CONCURRENCY` | `5` | Default concurrent sends in batch |
482
- | `MailQueueExecutorTypes.DIRECT` | `'direct'` | Immediate execution |
483
- | `MailQueueExecutorTypes.INTERNAL_QUEUE` | `'internal-queue'` | In-memory queue |
484
- | `MailQueueExecutorTypes.BULLMQ` | `'bullmq'` | Redis-backed queue |
485
- | `BullMQExecutorModes.QUEUE_ONLY` | `'queue-only'` | Producer only (enqueue) |
486
- | `BullMQExecutorModes.WORKER_ONLY` | `'worker-only'` | Consumer only (process) |
487
- | `BullMQExecutorModes.BOTH` | `'both'` | Full duplex (produce + consume) |
488
-
489
- #### MailErrorCodes
490
-
491
- | Constant | Value | Description |
492
- |----------|-------|-------------|
493
- | `MailErrorCodes.INVALID_CONFIGURATION` | `'MAIL_INVALID_CONFIGURATION'` | Invalid or missing configuration (transport, template engine, subject, body) |
494
- | `MailErrorCodes.SEND_FAILED` | `'MAIL_SEND_FAILED'` | Single email send failed |
495
- | `MailErrorCodes.VERIFICATION_FAILED` | `'MAIL_VERIFICATION_FAILED'` | Transport connection verification failed |
496
- | `MailErrorCodes.INVALID_RECIPIENT` | `'MAIL_INVALID_RECIPIENT'` | Missing or empty recipient address |
497
- | `MailErrorCodes.BATCH_SEND_FAILED` | `'MAIL_BATCH_SEND_FAILED'` | Batch email operation failed |
498
- | `MailErrorCodes.TEMPLATE_NOT_FOUND` | `'TEMPLATE_NOT_FOUND'` | Template name not found in registry |
499
-
500
- #### MailQueueExecutorTypes Validation
501
-
502
- Both `MailQueueExecutorTypes` and `BullMQExecutorModes` include a `SCHEME_SET` / `MODE_SET` and an `isValid()` static method for runtime validation:
149
+ - [Usage & Examples](./usage) -- sending, templates, queue executors, and verification generators
150
+ - [API Reference](./api) -- architecture, binding keys, interfaces, and internals
151
+ - [Error Reference](./errors) -- error codes and troubleshooting
152
+ - [Components Overview](/guides/core-concepts/components) -- component system basics
153
+ - [Queue Helper](/extensions/helpers/queue/) -- the in-memory/BullMQ primitives the queue executors are built on
154
+ - [Redis Helper](/extensions/helpers/redis/) -- `RedisSingleHelper`, required by the BullMQ queue executor
503
155
 
504
- ```typescript
505
- MailQueueExecutorTypes.isValid('bullmq'); // true
506
- MailQueueExecutorTypes.isValid('unknown'); // false
507
- BullMQExecutorModes.isValid('both'); // true
508
- BullMQExecutorModes.isValid('invalid'); // false
509
- ```
156
+ **Files:**
510
157
 
511
- ## Binding Keys
512
-
513
- | Key | Constant | Type | Required | Default |
514
- |-----|----------|------|----------|---------|
515
- | `@app/components/mail/options` | `MailKeys.MAIL_OPTIONS` | `TMailOptions` | Yes | -- |
516
- | `@app/components/mail/queue/executor-config` | `MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG` | `IMailQueueExecutorConfig` | Yes | -- |
517
- | `@app/components/mail/service` | `MailKeys.MAIL_SERVICE` | `IMailService` | No | `MailService` (singleton) |
518
- | `@app/components/mail/services/template-engine` | `MailKeys.MAIL_TEMPLATE_ENGINE` | `IMailTemplateEngine` | No | `TemplateEngineService` (singleton) |
519
- | `@app/components/mail/transport-provider` | `MailKeys.MAIL_TRANSPORT_PROVIDER` | `TGetMailTransportFn` | No | `MailTransportProvider` (singleton) |
520
- | `@app/components/mail/transport-instance` | `MailKeys.MAIL_TRANSPORT_INSTANCE` | `IMailTransport` | No | Created by component |
521
- | `@app/components/mail/queue-executor-provider` | `MailKeys.MAIL_QUEUE_EXECUTOR_PROVIDER` | `TGetMailQueueExecutorFn` | No | `MailQueueExecutorProvider` (singleton) |
522
- | `@app/components/mail/queue-executor-instance` | `MailKeys.MAIL_QUEUE_EXECUTOR_INSTANCE` | `IMailQueueExecutor` | No | Created by component |
523
- | `@app/components/mail/verification/code-generator` | `MailKeys.MAIL_VERIFICATION_CODE_GENERATOR` | `IVerificationCodeGenerator` | No | `NumericCodeGenerator` |
524
- | `@app/components/mail/verification/token-generator` | `MailKeys.MAIL_VERIFICATION_TOKEN_GENERATOR` | `IVerificationTokenGenerator` | No | `RandomTokenGenerator` |
525
- | `@app/components/mail/verification/data-generator` | `MailKeys.MAIL_VERIFICATION_DATA_GENERATOR` | `IVerificationDataGenerator` | No | `DefaultVerificationDataGenerator` |
526
-
527
- > [!IMPORTANT]
528
- > Both `MailKeys.MAIL_OPTIONS` and `MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG` must be bound before registering `MailComponent`. The component throws an error if `MAIL_OPTIONS` is not found.
529
-
530
- ## See Also
531
-
532
- - [Usage & Examples](./usage) -- Sending emails, templates, queue executors, and verification
533
- - [API Reference](./api) -- Architecture, interfaces, and internals
534
- - [Error Reference](./errors) -- Error codes and troubleshooting
158
+ - [`packages/core/src/components/mail/component.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/mail/component.ts) -- `MailComponent`
159
+ - [`packages/core/src/components/mail/services/mail.service.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/mail/services/mail.service.ts) -- `MailService`
160
+ - [`packages/core/src/components/mail/services/template.service.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/mail/services/template.service.ts) -- `TemplateEngineService`
161
+ - [`packages/core/src/components/mail/services/generator.service.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/mail/services/generator.service.ts) -- verification generators
162
+ - [`packages/core/src/components/mail/common/keys.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/mail/common/keys.ts) -- `MailKeys`
163
+ - [`packages/core/src/components/mail/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/mail/common/types.ts) -- `TMailOptions`, `IMailMessage`, and every mail interface