@venizia/ignis-docs 0.0.5 → 0.0.6-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 (98) hide show
  1. package/package.json +1 -1
  2. package/wiki/best-practices/architecture-decisions.md +0 -8
  3. package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
  4. package/wiki/best-practices/performance-optimization.md +3 -3
  5. package/wiki/best-practices/security-guidelines.md +2 -2
  6. package/wiki/best-practices/troubleshooting-tips.md +1 -1
  7. package/wiki/guides/core-concepts/components-guide.md +1 -1
  8. package/wiki/guides/core-concepts/components.md +2 -2
  9. package/wiki/guides/core-concepts/dependency-injection.md +1 -1
  10. package/wiki/guides/core-concepts/services.md +1 -1
  11. package/wiki/guides/tutorials/building-a-crud-api.md +1 -1
  12. package/wiki/guides/tutorials/ecommerce-api.md +2 -2
  13. package/wiki/guides/tutorials/realtime-chat.md +6 -6
  14. package/wiki/guides/tutorials/testing.md +1 -1
  15. package/wiki/references/base/bootstrapping.md +0 -2
  16. package/wiki/references/base/components.md +2 -2
  17. package/wiki/references/base/controllers.md +0 -1
  18. package/wiki/references/base/datasources.md +1 -1
  19. package/wiki/references/base/dependency-injection.md +1 -1
  20. package/wiki/references/base/filter-system/quick-reference.md +0 -14
  21. package/wiki/references/base/middlewares.md +0 -8
  22. package/wiki/references/base/providers.md +0 -9
  23. package/wiki/references/base/services.md +0 -1
  24. package/wiki/references/components/authentication/api.md +444 -0
  25. package/wiki/references/components/authentication/errors.md +177 -0
  26. package/wiki/references/components/authentication/index.md +571 -0
  27. package/wiki/references/components/authentication/usage.md +781 -0
  28. package/wiki/references/components/health-check.md +292 -103
  29. package/wiki/references/components/index.md +14 -12
  30. package/wiki/references/components/mail/api.md +505 -0
  31. package/wiki/references/components/mail/errors.md +176 -0
  32. package/wiki/references/components/mail/index.md +535 -0
  33. package/wiki/references/components/mail/usage.md +404 -0
  34. package/wiki/references/components/request-tracker.md +229 -25
  35. package/wiki/references/components/socket-io/api.md +1051 -0
  36. package/wiki/references/components/socket-io/errors.md +119 -0
  37. package/wiki/references/components/socket-io/index.md +410 -0
  38. package/wiki/references/components/socket-io/usage.md +322 -0
  39. package/wiki/references/components/static-asset/api.md +261 -0
  40. package/wiki/references/components/static-asset/errors.md +89 -0
  41. package/wiki/references/components/static-asset/index.md +617 -0
  42. package/wiki/references/components/static-asset/usage.md +364 -0
  43. package/wiki/references/components/swagger.md +390 -110
  44. package/wiki/references/components/template/api-page.md +125 -0
  45. package/wiki/references/components/template/errors-page.md +100 -0
  46. package/wiki/references/components/template/index.md +104 -0
  47. package/wiki/references/components/template/setup-page.md +134 -0
  48. package/wiki/references/components/template/single-page.md +132 -0
  49. package/wiki/references/components/template/usage-page.md +127 -0
  50. package/wiki/references/components/websocket/api.md +508 -0
  51. package/wiki/references/components/websocket/errors.md +123 -0
  52. package/wiki/references/components/websocket/index.md +453 -0
  53. package/wiki/references/components/websocket/usage.md +475 -0
  54. package/wiki/references/helpers/cron/index.md +224 -0
  55. package/wiki/references/helpers/crypto/index.md +537 -0
  56. package/wiki/references/helpers/env/index.md +214 -0
  57. package/wiki/references/helpers/error/index.md +232 -0
  58. package/wiki/references/helpers/index.md +16 -15
  59. package/wiki/references/helpers/inversion/index.md +608 -0
  60. package/wiki/references/helpers/logger/index.md +600 -0
  61. package/wiki/references/helpers/network/api.md +986 -0
  62. package/wiki/references/helpers/network/index.md +620 -0
  63. package/wiki/references/helpers/queue/index.md +589 -0
  64. package/wiki/references/helpers/redis/index.md +495 -0
  65. package/wiki/references/helpers/socket-io/api.md +497 -0
  66. package/wiki/references/helpers/socket-io/index.md +513 -0
  67. package/wiki/references/helpers/storage/api.md +705 -0
  68. package/wiki/references/helpers/storage/index.md +583 -0
  69. package/wiki/references/helpers/template/index.md +66 -0
  70. package/wiki/references/helpers/template/single-page.md +126 -0
  71. package/wiki/references/helpers/testing/index.md +510 -0
  72. package/wiki/references/helpers/types/index.md +512 -0
  73. package/wiki/references/helpers/uid/index.md +272 -0
  74. package/wiki/references/helpers/websocket/api.md +736 -0
  75. package/wiki/references/helpers/websocket/index.md +574 -0
  76. package/wiki/references/helpers/worker-thread/index.md +470 -0
  77. package/wiki/references/quick-reference.md +3 -18
  78. package/wiki/references/utilities/jsx.md +1 -8
  79. package/wiki/references/utilities/statuses.md +0 -7
  80. package/wiki/references/components/authentication.md +0 -476
  81. package/wiki/references/components/mail.md +0 -687
  82. package/wiki/references/components/socket-io.md +0 -562
  83. package/wiki/references/components/static-asset.md +0 -1277
  84. package/wiki/references/helpers/cron.md +0 -108
  85. package/wiki/references/helpers/crypto.md +0 -132
  86. package/wiki/references/helpers/env.md +0 -83
  87. package/wiki/references/helpers/error.md +0 -97
  88. package/wiki/references/helpers/inversion.md +0 -176
  89. package/wiki/references/helpers/logger.md +0 -296
  90. package/wiki/references/helpers/network.md +0 -396
  91. package/wiki/references/helpers/queue.md +0 -150
  92. package/wiki/references/helpers/redis.md +0 -142
  93. package/wiki/references/helpers/socket-io.md +0 -932
  94. package/wiki/references/helpers/storage.md +0 -665
  95. package/wiki/references/helpers/testing.md +0 -133
  96. package/wiki/references/helpers/types.md +0 -167
  97. package/wiki/references/helpers/uid.md +0 -167
  98. package/wiki/references/helpers/worker-thread.md +0 -178
@@ -0,0 +1,535 @@
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
+ ```
95
+
96
+ ## Setup
97
+
98
+ The recommended approach is to create a wrapper component that binds the mail options and queue executor config, then registers `MailComponent` internally.
99
+
100
+ ### Step 1: Bind Configuration
101
+
102
+ ```typescript
103
+ // src/components/mail/component.ts
104
+ import {
105
+ BaseApplication,
106
+ BaseComponent,
107
+ Binding,
108
+ CoreBindings,
109
+ inject,
110
+ applicationEnvironment,
111
+ toBoolean,
112
+ } from '@venizia/ignis';
113
+ import { MailComponent, MailKeys, MailProviders } from '@venizia/ignis/mail';
114
+
115
+ export class NodemailerComponent extends BaseComponent {
116
+ constructor(
117
+ @inject({ key: CoreBindings.APPLICATION_INSTANCE })
118
+ protected application: BaseApplication,
119
+ ) {
120
+ super({
121
+ scope: NodemailerComponent.name,
122
+ initDefault: { enable: true, container: application },
123
+ bindings: {
124
+ // Configure mail transport options
125
+ [MailKeys.MAIL_OPTIONS]: Binding.bind({
126
+ key: MailKeys.MAIL_OPTIONS,
127
+ }).toValue({
128
+ provider: MailProviders.NODEMAILER,
129
+ from: 'noreply@example.com',
130
+ fromName: 'Example App',
131
+ config: {
132
+ host: applicationEnvironment.get<string>('APP_ENV_MAIL_HOST') ?? 'smtp.gmail.com',
133
+ port: +(applicationEnvironment.get<number>('APP_ENV_MAIL_PORT') ?? 465),
134
+ secure: toBoolean(applicationEnvironment.get<boolean>('APP_ENV_MAIL_SECURE') ?? true),
135
+ auth: {
136
+ type: 'oauth2',
137
+ user: applicationEnvironment.get<string>('APP_ENV_MAIL_USER'),
138
+ clientId: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_ID'),
139
+ clientSecret: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_SECRET'),
140
+ refreshToken: applicationEnvironment.get<string>('APP_ENV_MAIL_REFRESH_TOKEN'),
141
+ },
142
+ },
143
+ }),
144
+ // Configure queue executor
145
+ [MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG]: Binding.bind({
146
+ key: MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG,
147
+ }).toValue({
148
+ type: 'internal-queue',
149
+ internalQueue: {
150
+ identifier: 'mail-internal-queue',
151
+ },
152
+ }),
153
+ },
154
+ });
155
+ }
156
+
157
+ override async binding(): Promise<void> {
158
+ this.logger.info('[binding] Binding mail component...');
159
+
160
+ // Register the core MailComponent
161
+ this.application.component(MailComponent);
162
+
163
+ this.logger.info('[binding] Mail component initialized successfully');
164
+ }
165
+ }
166
+ ```
167
+
168
+ ### Step 2: Register Component
169
+
170
+ ```typescript
171
+ // src/application.ts
172
+ import { BaseApplication, ValueOrPromise } from '@venizia/ignis';
173
+ import { NodemailerComponent } from './components/mail/component';
174
+
175
+ export class Application extends BaseApplication {
176
+ preConfigure(): ValueOrPromise<void> {
177
+ // Register the mail component
178
+ this.component(NodemailerComponent);
179
+
180
+ // ... other components
181
+ }
182
+ }
183
+ ```
184
+
185
+ ## Configuration
186
+
187
+ ### Transport Options
188
+
189
+ The `TMailOptions` configuration determines which email transport provider is used and how it's configured. It is a discriminated union of four variants.
190
+
191
+ **Nodemailer SMTP example:**
192
+
193
+ ```typescript
194
+ {
195
+ provider: MailProviders.NODEMAILER,
196
+ from: 'noreply@example.com',
197
+ fromName: 'Example App',
198
+ config: {
199
+ host: 'smtp.gmail.com',
200
+ port: 465,
201
+ secure: true,
202
+ auth: {
203
+ user: 'your-email@gmail.com',
204
+ pass: 'your-app-password',
205
+ },
206
+ },
207
+ }
208
+ ```
209
+
210
+ **Simple SMTP Authentication (e.g., Gmail with app password):**
211
+
212
+ ```typescript
213
+ // Simple SMTP Authentication (e.g., Gmail with app password)
214
+ this.bind<TMailOptions>({ key: MailBindingKeys.MAIL_OPTIONS }).toValue({
215
+ provider: 'nodemailer',
216
+ from: 'noreply@example.com',
217
+ fromName: 'My App',
218
+ config: {
219
+ host: 'smtp.gmail.com',
220
+ port: 465,
221
+ secure: true,
222
+ auth: {
223
+ user: process.env.APP_ENV_MAIL_USER,
224
+ pass: process.env.APP_ENV_MAIL_PASS,
225
+ },
226
+ },
227
+ });
228
+ ```
229
+
230
+ **Mailgun example:**
231
+
232
+ ```typescript
233
+ {
234
+ provider: MailProviders.MAILGUN,
235
+ from: 'noreply@example.com',
236
+ fromName: 'Example App',
237
+ config: {
238
+ apiKey: process.env.MAILGUN_API_KEY,
239
+ domain: 'mg.example.com',
240
+ host: 'api.eu.mailgun.net', // Optional: EU region
241
+ },
242
+ }
243
+ ```
244
+
245
+ **Generic provider example:**
246
+
247
+ 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:
248
+
249
+ ```typescript
250
+ {
251
+ provider: 'sendgrid',
252
+ from: 'noreply@example.com',
253
+ config: {
254
+ apiKey: process.env.SENDGRID_API_KEY,
255
+ // Any key-value pairs accepted
256
+ },
257
+ }
258
+ ```
259
+
260
+ > [!WARNING]
261
+ > 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.
262
+
263
+ **OAuth2 with environment variables:**
264
+
265
+ ```typescript
266
+ {
267
+ provider: MailProviders.NODEMAILER,
268
+ from: applicationEnvironment.get<string>('APP_ENV_MAIL_FROM') ?? 'noreply@example.com',
269
+ fromName: applicationEnvironment.get<string>('APP_ENV_MAIL_FROM_NAME') ?? 'Example App',
270
+ config: {
271
+ host: applicationEnvironment.get<string>('APP_ENV_MAIL_HOST') ?? 'smtp.gmail.com',
272
+ port: +(applicationEnvironment.get<number>('APP_ENV_MAIL_PORT') ?? 465),
273
+ secure: toBoolean(applicationEnvironment.get<boolean>('APP_ENV_MAIL_SECURE') ?? true),
274
+ auth: {
275
+ type: 'oauth2',
276
+ user: applicationEnvironment.get<string>('APP_ENV_MAIL_USER'),
277
+ clientId: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_ID'),
278
+ clientSecret: applicationEnvironment.get<string>('APP_ENV_MAIL_CLIENT_SECRET'),
279
+ refreshToken: applicationEnvironment.get<string>('APP_ENV_MAIL_REFRESH_TOKEN'),
280
+ },
281
+ },
282
+ }
283
+ ```
284
+
285
+ **Example `.env` file for Nodemailer with OAuth2:**
286
+
287
+ ```
288
+ APP_ENV_MAIL_HOST=smtp.gmail.com
289
+ APP_ENV_MAIL_PORT=465
290
+ APP_ENV_MAIL_SECURE=true
291
+ APP_ENV_MAIL_USER=your-email@gmail.com
292
+ APP_ENV_MAIL_CLIENT_ID=your-oauth2-client-id
293
+ APP_ENV_MAIL_CLIENT_SECRET=your-oauth2-client-secret
294
+ APP_ENV_MAIL_REFRESH_TOKEN=your-oauth2-refresh-token
295
+ ```
296
+
297
+ > [!TIP]
298
+ > 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.
299
+
300
+ ### Queue Executor Options
301
+
302
+ The `IMailQueueExecutorConfig` configuration determines how emails are queued and processed.
303
+
304
+ **Direct execution (no queue):**
305
+
306
+ ```typescript
307
+ {
308
+ type: 'direct',
309
+ }
310
+ ```
311
+
312
+ **Internal queue (in-memory):**
313
+
314
+ ```typescript
315
+ {
316
+ type: 'internal-queue',
317
+ internalQueue: {
318
+ identifier: 'mail-internal-queue',
319
+ },
320
+ }
321
+ ```
322
+
323
+ **BullMQ (Redis-backed):**
324
+
325
+ ```typescript
326
+ {
327
+ type: 'bullmq',
328
+ bullmq: {
329
+ redis: {
330
+ host: 'localhost',
331
+ port: 6379,
332
+ password: 'your-redis-password',
333
+ },
334
+ queue: {
335
+ identifier: 'mail-queue',
336
+ name: 'mail-queue',
337
+ },
338
+ mode: 'both', // 'queue-only', 'worker-only', or 'both'
339
+ },
340
+ }
341
+ ```
342
+
343
+ > [!NOTE]
344
+ > - **`'queue-only'`** -- Only enqueues jobs, does not process them (useful for web servers that offload to workers)
345
+ > - **`'worker-only'`** -- Only processes jobs, does not enqueue (useful for dedicated worker processes)
346
+ > - **`'both'`** -- Both enqueues and processes jobs (simplest setup for single-instance apps)
347
+
348
+ > [!NOTE]
349
+ > Choose the right queue executor for your environment:
350
+ > - **`direct`** -- Development or low-volume applications. No queueing overhead.
351
+ > - **`internal-queue`** -- Single-instance applications with moderate volume. In-memory queue with retry support.
352
+ > - **`bullmq`** -- Distributed systems or high-volume applications. Redis-backed with configurable concurrency, priority, and backoff.
353
+
354
+ #### BullMQ Dynamic Worker Management
355
+
356
+ The `BullMQMailExecutorHelper` supports dynamic worker scaling at runtime. Workers can be added and removed without restarting the application:
357
+
358
+ ```typescript
359
+ const executor = this.application.get<BullMQMailExecutorHelper>({
360
+ key: MailKeys.MAIL_QUEUE_EXECUTOR_INSTANCE,
361
+ });
362
+
363
+ // Add a new worker with custom concurrency
364
+ executor.addWorker({
365
+ workerIdentifier: 'mail-queue-worker-extra',
366
+ concurrency: 10,
367
+ lockDuration: 60000, // 60 seconds
368
+ });
369
+
370
+ // Check current worker count
371
+ const count = executor.getWorkerCount(); // e.g. 2
372
+
373
+ // Check current mode
374
+ const mode = executor.getMode(); // e.g. 'both'
375
+
376
+ // Remove a specific worker by index
377
+ await executor.removeWorker(1);
378
+
379
+ // Remove all workers
380
+ await executor.clearWorkers();
381
+ ```
382
+
383
+ The `setProcessor()` method on BullMQ also accepts an optional second argument for worker configuration:
384
+
385
+ ```typescript
386
+ await executor.setProcessor(
387
+ async (email: string) => {
388
+ // your processing logic
389
+ return { success: true, message: 'Sent', expiresInMinutes: 10 };
390
+ },
391
+ {
392
+ numberOfWorkers: 3, // Spawn 3 workers (default: 1)
393
+ concurrencyPerWorker: 10, // Each worker handles 10 concurrent jobs (default: 5)
394
+ lockDuration: 60000, // Job lock duration in ms (default: 30000)
395
+ },
396
+ );
397
+ ```
398
+
399
+ #### Full Transport Options Interface
400
+
401
+ The `TMailOptions` union type has four variants. All extend `IBaseMailOptions`:
402
+
403
+ ```typescript
404
+ interface IBaseMailOptions {
405
+ from?: string;
406
+ fromName?: string;
407
+ }
408
+
409
+ interface INodemailerMailOptions extends IBaseMailOptions {
410
+ provider: 'nodemailer';
411
+ config: TNodemailerConfig; // SMTPTransport | SMTPTransport.Options | string
412
+ }
413
+
414
+ interface IMailgunMailOptions extends IBaseMailOptions {
415
+ provider: 'mailgun';
416
+ config: TMailgunConfig; // { domain: string; [key: string]: any }
417
+ }
418
+
419
+ interface ICustomMailOptions extends IBaseMailOptions {
420
+ provider: 'custom';
421
+ config: IMailTransport; // Must implement send() and verify()
422
+ }
423
+
424
+ interface IGenericMailOptions extends IBaseMailOptions {
425
+ provider: string;
426
+ config: Record<string, AnyType>;
427
+ }
428
+
429
+ type TMailOptions =
430
+ | INodemailerMailOptions
431
+ | IMailgunMailOptions
432
+ | ICustomMailOptions
433
+ | IGenericMailOptions;
434
+ ```
435
+
436
+ #### Full Queue Executor Config Interface
437
+ ```typescript
438
+ interface IMailQueueExecutorConfig {
439
+ type: TConstValue<typeof MailQueueExecutorTypes>; // 'direct' | 'internal-queue' | 'bullmq'
440
+ internalQueue?: {
441
+ identifier: string;
442
+ };
443
+ bullmq?: {
444
+ redis: IRedisHelperOptions;
445
+ queue: {
446
+ identifier: string;
447
+ name: string;
448
+ };
449
+ mode: TConstValue<typeof BullMQExecutorModes>; // REQUIRED: 'queue-only' | 'worker-only' | 'both'
450
+ };
451
+ }
452
+ ```
453
+
454
+ > [!IMPORTANT]
455
+ > 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'`.
456
+
457
+ #### Nodemailer Transport Capabilities
458
+ - Basic SMTP authentication (`user`/`pass`)
459
+ - OAuth2 authentication (client ID, secret, refresh token)
460
+ - TLS/SSL connections
461
+ - Custom SMTP headers
462
+ - Connection pooling
463
+ - Attachment handling (file path, buffer, stream)
464
+ - HTML and plain text content
465
+ - SMTP connection verification via `verify()` method
466
+ - Peer dependency validation via `validateModule()` (requires `nodemailer` to be installed)
467
+
468
+ #### Mailgun Transport Capabilities
469
+ - US and EU regional endpoints
470
+ - API key authentication
471
+ - HTML and plain text emails
472
+ - Inline attachments with CID
473
+ - Custom headers (auto-prefixed with `h:`)
474
+ - Batch sending via Mailgun's API
475
+ - Test mode verification via `verify()` method (uses `o:testmode` flag)
476
+ - Peer dependency validation via `validateModule()` (requires `mailgun.js` to be installed)
477
+
478
+ ### Constants
479
+
480
+ | Constant | Value | Description |
481
+ |----------|-------|-------------|
482
+ | `MailDefaults.BATCH_CONCURRENCY` | `5` | Default concurrent sends in batch |
483
+ | `MailQueueExecutorTypes.DIRECT` | `'direct'` | Immediate execution |
484
+ | `MailQueueExecutorTypes.INTERNAL_QUEUE` | `'internal-queue'` | In-memory queue |
485
+ | `MailQueueExecutorTypes.BULLMQ` | `'bullmq'` | Redis-backed queue |
486
+ | `BullMQExecutorModes.QUEUE_ONLY` | `'queue-only'` | Producer only (enqueue) |
487
+ | `BullMQExecutorModes.WORKER_ONLY` | `'worker-only'` | Consumer only (process) |
488
+ | `BullMQExecutorModes.BOTH` | `'both'` | Full duplex (produce + consume) |
489
+
490
+ #### MailErrorCodes
491
+
492
+ | Constant | Value | Description |
493
+ |----------|-------|-------------|
494
+ | `MailErrorCodes.INVALID_CONFIGURATION` | `'MAIL_INVALID_CONFIGURATION'` | Invalid or missing configuration (transport, template engine, subject, body) |
495
+ | `MailErrorCodes.SEND_FAILED` | `'MAIL_SEND_FAILED'` | Single email send failed |
496
+ | `MailErrorCodes.VERIFICATION_FAILED` | `'MAIL_VERIFICATION_FAILED'` | Transport connection verification failed |
497
+ | `MailErrorCodes.INVALID_RECIPIENT` | `'MAIL_INVALID_RECIPIENT'` | Missing or empty recipient address |
498
+ | `MailErrorCodes.BATCH_SEND_FAILED` | `'MAIL_BATCH_SEND_FAILED'` | Batch email operation failed |
499
+ | `MailErrorCodes.TEMPLATE_NOT_FOUND` | `'TEMPLATE_NOT_FOUND'` | Template name not found in registry |
500
+
501
+ #### MailQueueExecutorTypes Validation
502
+
503
+ Both `MailQueueExecutorTypes` and `BullMQExecutorModes` include a `SCHEME_SET` / `MODE_SET` and an `isValid()` static method for runtime validation:
504
+
505
+ ```typescript
506
+ MailQueueExecutorTypes.isValid('bullmq'); // true
507
+ MailQueueExecutorTypes.isValid('unknown'); // false
508
+ BullMQExecutorModes.isValid('both'); // true
509
+ BullMQExecutorModes.isValid('invalid'); // false
510
+ ```
511
+
512
+ ## Binding Keys
513
+
514
+ | Key | Constant | Type | Required | Default |
515
+ |-----|----------|------|----------|---------|
516
+ | `@app/components/mail/options` | `MailKeys.MAIL_OPTIONS` | `TMailOptions` | Yes | -- |
517
+ | `@app/components/mail/queue/executor-config` | `MailKeys.MAIL_QUEUE_EXECUTOR_CONFIG` | `IMailQueueExecutorConfig` | Yes | -- |
518
+ | `@app/components/mail/service` | `MailKeys.MAIL_SERVICE` | `IMailService` | No | `MailService` (singleton) |
519
+ | `@app/components/mail/services/template-engine` | `MailKeys.MAIL_TEMPLATE_ENGINE` | `IMailTemplateEngine` | No | `TemplateEngineService` (singleton) |
520
+ | `@app/components/mail/transport-provider` | `MailKeys.MAIL_TRANSPORT_PROVIDER` | `TGetMailTransportFn` | No | `MailTransportProvider` (singleton) |
521
+ | `@app/components/mail/transport-instance` | `MailKeys.MAIL_TRANSPORT_INSTANCE` | `IMailTransport` | No | Created by component |
522
+ | `@app/components/mail/queue-executor-provider` | `MailKeys.MAIL_QUEUE_EXECUTOR_PROVIDER` | `TGetMailQueueExecutorFn` | No | `MailQueueExecutorProvider` (singleton) |
523
+ | `@app/components/mail/queue-executor-instance` | `MailKeys.MAIL_QUEUE_EXECUTOR_INSTANCE` | `IMailQueueExecutor` | No | Created by component |
524
+ | `@app/components/mail/verification/code-generator` | `MailKeys.MAIL_VERIFICATION_CODE_GENERATOR` | `IVerificationCodeGenerator` | No | `NumericCodeGenerator` |
525
+ | `@app/components/mail/verification/token-generator` | `MailKeys.MAIL_VERIFICATION_TOKEN_GENERATOR` | `IVerificationTokenGenerator` | No | `RandomTokenGenerator` |
526
+ | `@app/components/mail/verification/data-generator` | `MailKeys.MAIL_VERIFICATION_DATA_GENERATOR` | `IVerificationDataGenerator` | No | `DefaultVerificationDataGenerator` |
527
+
528
+ > [!IMPORTANT]
529
+ > 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.
530
+
531
+ ## See Also
532
+
533
+ - [Usage & Examples](./usage) -- Sending emails, templates, queue executors, and verification
534
+ - [API Reference](./api) -- Architecture, interfaces, and internals
535
+ - [Error Reference](./errors) -- Error codes and troubleshooting