@venizia/ignis-docs 0.2.0 → 0.2.1-1

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 (174) 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 +24 -13
  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 +27 -3
  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 +8 -4
  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 +247 -153
  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 +109 -323
  26. package/content/extensions/components/authentication/api.md +489 -602
  27. package/content/extensions/components/authentication/errors.md +135 -498
  28. package/content/extensions/components/authentication/index.md +89 -801
  29. package/content/extensions/components/authentication/usage.md +231 -955
  30. package/content/extensions/components/authorization/api.md +991 -644
  31. package/content/extensions/components/authorization/errors.md +204 -208
  32. package/content/extensions/components/authorization/getting-started.md +227 -0
  33. package/content/extensions/components/authorization/index.md +88 -795
  34. package/content/extensions/components/authorization/usage.md +219 -528
  35. package/content/extensions/components/health-check.md +77 -243
  36. package/content/extensions/components/index.md +24 -90
  37. package/content/extensions/components/mail/api.md +553 -285
  38. package/content/extensions/components/mail/errors.md +76 -62
  39. package/content/extensions/components/mail/index.md +111 -463
  40. package/content/extensions/components/mail/usage.md +139 -173
  41. package/content/extensions/components/request-tracker.md +70 -173
  42. package/content/extensions/components/socket-io/api.md +462 -785
  43. package/content/extensions/components/socket-io/errors.md +49 -51
  44. package/content/extensions/components/socket-io/index.md +69 -372
  45. package/content/extensions/components/socket-io/usage.md +212 -105
  46. package/content/extensions/components/static-asset/api.md +461 -141
  47. package/content/extensions/components/static-asset/errors.md +121 -53
  48. package/content/extensions/components/static-asset/index.md +84 -606
  49. package/content/extensions/components/static-asset/usage.md +184 -299
  50. package/content/extensions/components/template/index.md +3 -3
  51. package/content/extensions/components/websocket/api.md +311 -404
  52. package/content/extensions/components/websocket/errors.md +47 -56
  53. package/content/extensions/components/websocket/index.md +75 -407
  54. package/content/extensions/components/websocket/usage.md +120 -338
  55. package/content/extensions/helpers/cron/index.md +52 -160
  56. package/content/extensions/helpers/crypto/index.md +67 -480
  57. package/content/extensions/helpers/crypto/reference.md +528 -0
  58. package/content/extensions/helpers/env/index.md +64 -178
  59. package/content/extensions/helpers/error/index.md +286 -196
  60. package/content/extensions/helpers/index.md +61 -47
  61. package/content/extensions/helpers/inversion/index.md +76 -550
  62. package/content/extensions/helpers/inversion/reference.md +530 -0
  63. package/content/extensions/helpers/kafka/admin.md +23 -3
  64. package/content/extensions/helpers/kafka/compile-binary.md +83 -52
  65. package/content/extensions/helpers/kafka/consumer.md +65 -28
  66. package/content/extensions/helpers/kafka/examples.md +46 -253
  67. package/content/extensions/helpers/kafka/index.md +55 -617
  68. package/content/extensions/helpers/kafka/producer.md +156 -22
  69. package/content/extensions/helpers/kafka/schema-registry.md +59 -79
  70. package/content/extensions/helpers/logger/hf-logger.md +220 -0
  71. package/content/extensions/helpers/logger/index.md +78 -552
  72. package/content/extensions/helpers/logger/pino.md +105 -0
  73. package/content/extensions/helpers/logger/reference.md +937 -0
  74. package/content/extensions/helpers/network/api.md +276 -195
  75. package/content/extensions/helpers/network/index.md +87 -524
  76. package/content/extensions/helpers/queue/index.md +80 -897
  77. package/content/extensions/helpers/queue/reference.md +494 -0
  78. package/content/extensions/helpers/redis/index.md +86 -640
  79. package/content/extensions/helpers/redis/reference.md +784 -0
  80. package/content/extensions/helpers/secrets/index.md +136 -0
  81. package/content/extensions/helpers/socket-io/api.md +325 -204
  82. package/content/extensions/helpers/socket-io/index.md +79 -429
  83. package/content/extensions/helpers/storage/api.md +584 -464
  84. package/content/extensions/helpers/storage/index.md +80 -573
  85. package/content/extensions/helpers/types/index.md +75 -495
  86. package/content/extensions/helpers/types/reference.md +689 -0
  87. package/content/extensions/helpers/uid/index.md +176 -189
  88. package/content/extensions/helpers/websocket/api.md +366 -214
  89. package/content/extensions/helpers/websocket/index.md +68 -503
  90. package/content/extensions/helpers/worker-thread/index.md +62 -396
  91. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  92. package/content/extensions/index.md +38 -39
  93. package/content/extensions/src-details/mcp-server.md +96 -548
  94. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  95. package/content/guides/core-concepts/persistent/index.md +5 -1
  96. package/content/guides/core-concepts/persistent/models.md +1 -1
  97. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  98. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  99. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  100. package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
  101. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  102. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  103. package/content/guides/core-concepts/secrets-vault.md +177 -0
  104. package/content/guides/core-concepts/services.md +1 -1
  105. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  106. package/content/guides/get-started/philosophy.md +135 -670
  107. package/content/guides/get-started/setup.md +53 -74
  108. package/content/guides/migrations/redis-helpers-migration.md +5 -4
  109. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  110. package/content/guides/migrations/unified-connectors-migration.md +8 -7
  111. package/content/guides/tutorials/ecommerce-api.md +3 -8
  112. package/content/guides/tutorials/realtime-chat.md +1 -1
  113. package/content/references/base/application.md +64 -22
  114. package/content/references/base/components.md +3 -3
  115. package/content/references/base/connectors.md +79 -136
  116. package/content/references/base/controllers.md +12 -12
  117. package/content/references/base/datasources-reference.md +600 -0
  118. package/content/references/base/datasources.md +84 -444
  119. package/content/references/base/dependency-injection.md +25 -46
  120. package/content/references/base/filter-system/application-usage.md +95 -123
  121. package/content/references/base/filter-system/array-operators.md +33 -43
  122. package/content/references/base/filter-system/comparison-operators.md +55 -63
  123. package/content/references/base/filter-system/default-filter.md +144 -350
  124. package/content/references/base/filter-system/fields-order-pagination.md +116 -148
  125. package/content/references/base/filter-system/index.md +114 -253
  126. package/content/references/base/filter-system/json-filtering.md +52 -181
  127. package/content/references/base/filter-system/list-operators.md +28 -44
  128. package/content/references/base/filter-system/logical-operators.md +69 -114
  129. package/content/references/base/filter-system/null-operators.md +41 -98
  130. package/content/references/base/filter-system/pattern-matching.md +48 -51
  131. package/content/references/base/filter-system/quick-reference.md +93 -196
  132. package/content/references/base/filter-system/range-operators.md +22 -38
  133. package/content/references/base/filter-system/tips.md +70 -133
  134. package/content/references/base/filter-system/use-cases.md +173 -232
  135. package/content/references/base/grpc-controllers.md +53 -17
  136. package/content/references/base/index.md +5 -3
  137. package/content/references/base/middlewares.md +43 -28
  138. package/content/references/base/models-reference.md +886 -0
  139. package/content/references/base/models.md +81 -1452
  140. package/content/references/base/providers.md +8 -8
  141. package/content/references/base/repositories/advanced.md +281 -419
  142. package/content/references/base/repositories/index.md +84 -644
  143. package/content/references/base/repositories/mixins.md +25 -21
  144. package/content/references/base/repositories/relations.md +194 -375
  145. package/content/references/base/repositories/soft-deletable.md +67 -55
  146. package/content/references/base/secrets.md +267 -0
  147. package/content/references/base/services.md +8 -6
  148. package/content/references/configuration/environment-variables.md +73 -21
  149. package/content/references/configuration/index.md +51 -31
  150. package/content/references/index.md +1 -1
  151. package/content/references/quick-reference.md +3 -16
  152. package/content/references/utilities/crypto.md +35 -76
  153. package/content/references/utilities/date.md +33 -73
  154. package/content/references/utilities/duration.md +85 -0
  155. package/content/references/utilities/index.md +6 -2
  156. package/content/references/utilities/jsx-reference.md +298 -0
  157. package/content/references/utilities/jsx.md +82 -525
  158. package/content/references/utilities/module.md +81 -61
  159. package/content/references/utilities/parse.md +34 -64
  160. package/content/references/utilities/performance.md +33 -58
  161. package/content/references/utilities/promise.md +28 -62
  162. package/content/references/utilities/request.md +58 -218
  163. package/content/references/utilities/retry.md +139 -0
  164. package/content/references/utilities/schema.md +43 -137
  165. package/content/references/utilities/statuses-reference.md +361 -0
  166. package/content/references/utilities/statuses.md +63 -667
  167. package/dist/mcp-server/index.js +0 -0
  168. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  169. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  171. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  172. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  173. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  174. package/package.json +24 -23
@@ -1,534 +1,182 @@
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`. It adds 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 is optional, with a working default: queue executor config, verification generators, and more.
189
58
 
190
- **Nodemailer SMTP example:**
59
+ - **Transport is a discriminated union.** `TMailOptions.provider` picks the transport class:
191
60
 
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
- ```
61
+ | `provider` | Class |
62
+ |---|---|
63
+ | `nodemailer` | `NodemailerTransportHelper` |
64
+ | `mailgun` | `MailgunTransportHelper` |
65
+ | `custom` | Your own object, implementing `IMailTransport` (`send()` + `verify()`) |
208
66
 
209
- **Simple SMTP Authentication (e.g., Gmail with app password):**
67
+ `MailTransportProvider` is the factory that switches on the provider. It throws for an unsupported provider string.
210
68
 
211
- ```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
- },
226
- });
227
- ```
69
+ - **`MailService` is the one sending entry point.** `send()`, `sendBatch()`, `sendTemplate()`, and `verify()` all validate first, then call the transport directly, then normalize failures into `MailErrorCodes`:
228
70
 
229
- **Mailgun example:**
71
+ | Case | Result |
72
+ |---|---|
73
+ | Validation error | Passes through unchanged as `400` |
74
+ | Transport throws | Wrapped as `SEND_FAILED` (`500`) |
75
+ | Nodemailer / Mailgun transport | Never throws - returns `{ success: false, error }` instead |
230
76
 
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
- ```
77
+ - **The queue executor is a separate subsystem, not a mail queue.** `IMailQueueExecutor` (`direct` / `internal-queue` / `bullmq`) exposes only `enqueueVerificationEmail()` and `setProcessor()`, and never touches `MailService`. Call `setProcessor()` before `enqueueVerificationEmail()`, with your own function - typically one wrapping `mailService.send()`.
243
78
 
244
- **Generic provider example:**
79
+ - **Templates are a simple substitution engine.** `TemplateEngineService` stores templates in an in-memory `Map`. It replaces <code v-pre>{{variable}}</code> placeholders, with dot-notation for nested values. A missing value is logged and left as the literal placeholder text, not blanked out.
245
80
 
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
+ - **Startup logging never leaks credentials.** `MailComponent` logs only `mailOptions.provider` and `queueExecutorConfig.type`. It never logs the SMTP password, OAuth2 secret, API key, or Redis password nested inside them.
247
82
 
248
- ```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
- }
257
- ```
83
+ ## Common tasks
258
84
 
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.
85
+ ### Send an email
261
86
 
262
- **OAuth2 with environment variables:**
87
+ Inject `IMailService` via `MailKeys.MAIL_SERVICE` and call `send()`.
263
88
 
264
89
  ```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
90
+ const result = await this.mailService.send({
91
+ to: 'user@example.com',
92
+ subject: 'Welcome!',
93
+ html: '<h1>Welcome!</h1>',
94
+ text: 'Welcome!',
95
+ });
294
96
  ```
295
97
 
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.
98
+ ### Send a batch of emails
302
99
 
303
- **Direct execution (no queue):**
100
+ `sendBatch()` runs each message through `send()` with bounded concurrency (default `5`).
304
101
 
305
102
  ```typescript
306
- {
307
- type: 'direct',
308
- }
103
+ const results = await this.mailService.sendBatch(messages, { concurrency: 5 });
309
104
  ```
310
105
 
311
- **Internal queue (in-memory):**
106
+ ### Send a registered template
107
+
108
+ Register a template on `IMailTemplateEngine`, then send it through `IMailService`.
312
109
 
313
110
  ```typescript
314
- {
315
- type: 'internal-queue',
316
- internalQueue: {
317
- identifier: 'mail-internal-queue',
318
- },
319
- }
111
+ this.templateEngine.registerTemplate({
112
+ name: 'welcome-email',
113
+ content: '<h1>Welcome {{userName}}!</h1>',
114
+ options: { subject: 'Welcome to {{appName}}' },
115
+ });
116
+
117
+ await this.mailService.sendTemplate({
118
+ templateName: 'welcome-email',
119
+ data: { userName: 'Jane', appName: 'My App' },
120
+ recipients: 'user@example.com',
121
+ });
320
122
  ```
321
123
 
322
- **BullMQ (Redis-backed):**
124
+ ### Switch to Mailgun
125
+
126
+ `config` must carry `username`, `key`, and `domain` -- the transport validates them eagerly, on construction.
323
127
 
324
128
  ```typescript
325
129
  {
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
- },
130
+ provider: MailProviders.MAILGUN,
131
+ from: 'noreply@example.com',
132
+ config: { username: 'api', key: process.env.MAILGUN_API_KEY, domain: 'mg.example.com' },
339
133
  }
340
134
  ```
341
135
 
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.
136
+ ### Queue verification emails
352
137
 
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:
138
+ Get the queue executor instance, register a processor, then enqueue.
356
139
 
357
140
  ```typescript
358
- const executor = this.application.get<BullMQMailExecutorHelper>({
141
+ const executor = this.application.get<IMailQueueExecutor>({
359
142
  key: MailKeys.MAIL_QUEUE_EXECUTOR_INSTANCE,
360
143
  });
361
144
 
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
145
+ executor.setProcessor(async email => {
146
+ await this.mailService.send({ to: email, subject: 'Verify', html: '...' });
147
+ return { success: true, message: 'Sent', expiresInMinutes: 10 };
367
148
  });
368
149
 
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();
150
+ await executor.enqueueVerificationEmail('user@example.com');
380
151
  ```
381
152
 
382
- The `setProcessor()` method on BullMQ also accepts an optional second argument for worker configuration:
153
+ ### Generate a verification code and token
383
154
 
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`:
155
+ `MAIL_VERIFICATION_DATA_GENERATOR` composes a numeric code and a base64url token in one call.
401
156
 
402
157
  ```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;
158
+ const data = this.verificationGenerator.generateVerificationData({
159
+ codeLength: 6,
160
+ tokenBytes: 32,
161
+ codeExpiryMinutes: 10,
162
+ tokenExpiryHours: 24,
163
+ });
433
164
  ```
434
165
 
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
- ```
166
+ ## See also
452
167
 
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:
168
+ - [Usage & Examples](./usage) -- sending, templates, queue executors, and verification generators
169
+ - [API Reference](./api) -- architecture, binding keys, interfaces, and internals
170
+ - [Error Reference](./errors) -- error codes and troubleshooting
171
+ - [Components Overview](/guides/core-concepts/components) -- component system basics
172
+ - [Queue Helper](/extensions/helpers/queue/) -- the in-memory/BullMQ primitives the queue executors are built on
173
+ - [Redis Helper](/extensions/helpers/redis/) -- `RedisSingleHelper`, required by the BullMQ queue executor
503
174
 
504
- ```typescript
505
- MailQueueExecutorTypes.isValid('bullmq'); // true
506
- MailQueueExecutorTypes.isValid('unknown'); // false
507
- BullMQExecutorModes.isValid('both'); // true
508
- BullMQExecutorModes.isValid('invalid'); // false
509
- ```
175
+ **Files:**
510
176
 
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
177
+ - [`packages/core-server/src/components/mail/component.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/mail/component.ts) -- `MailComponent`
178
+ - [`packages/core-server/src/components/mail/services/mail.service.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/mail/services/mail.service.ts) -- `MailService`
179
+ - [`packages/core-server/src/components/mail/services/template.service.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/mail/services/template.service.ts) -- `TemplateEngineService`
180
+ - [`packages/core-server/src/components/mail/services/generator.service.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/mail/services/generator.service.ts) -- verification generators
181
+ - [`packages/core-server/src/components/mail/common/keys.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/mail/common/keys.ts) -- `MailKeys`
182
+ - [`packages/core-server/src/components/mail/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/mail/common/types.ts) -- `TMailOptions`, `IMailMessage`, and every mail interface