@gravito/signal 3.0.3 → 3.0.4

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 (104) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +89 -60
  3. package/README.zh-TW.md +140 -9
  4. package/dist/MjmlRenderer-IUH663FT.mjs +8 -0
  5. package/dist/ReactMjmlRenderer-C3P5YO5L.mjs +8 -0
  6. package/dist/ReactRenderer-2JFLRVST.mjs +45 -0
  7. package/dist/{ReactRenderer-L5INVYKT.mjs → ReactRenderer-LYEOSYFS.mjs} +9 -8
  8. package/dist/ReactRenderer-V54CUUEI.mjs +45 -0
  9. package/dist/VueMjmlRenderer-4F4CXHDB.mjs +8 -0
  10. package/dist/VueMjmlRenderer-5WZR4CQG.mjs +8 -0
  11. package/dist/VueMjmlRenderer-U5YMWI44.mjs +8 -0
  12. package/dist/VueRenderer-3YBRQXME.mjs +48 -0
  13. package/dist/VueRenderer-46JGXTJ2.mjs +48 -0
  14. package/dist/VueRenderer-5KWD4R3C.mjs +48 -0
  15. package/dist/VueRenderer-C23U4O5E.mjs +48 -0
  16. package/dist/VueRenderer-LEVDFLHP.mjs +31 -0
  17. package/dist/VueRenderer-RNHSCCRI.mjs +48 -0
  18. package/dist/chunk-3WOR3XSL.mjs +82 -0
  19. package/dist/chunk-DBFIVHHG.mjs +79 -0
  20. package/dist/{chunk-6DZX6EAA.mjs → chunk-HEBXNMVQ.mjs} +12 -1
  21. package/dist/chunk-KB7IDDBT.mjs +82 -0
  22. package/dist/chunk-LZL5UUPC.mjs +82 -0
  23. package/dist/chunk-W6LXIJKK.mjs +57 -0
  24. package/dist/chunk-XBIVBJS2.mjs +8 -0
  25. package/dist/index.d.mts +1680 -209
  26. package/dist/index.d.ts +1680 -209
  27. package/dist/index.js +69405 -542
  28. package/dist/index.mjs +993 -110
  29. package/dist/lib-HJTRWKU5.mjs +67788 -0
  30. package/dist/{VueRenderer-Z5PRVBNH.mjs → server-renderer-4IM3P5XZ.mjs} +308 -423
  31. package/dist/server-renderer-7KWFSTPV.mjs +37193 -0
  32. package/dist/{VueRenderer-S65ZARRI.mjs → server-renderer-S5FPSTJ2.mjs} +931 -877
  33. package/dist/server-renderer-X5LUFVWT.mjs +37193 -0
  34. package/doc/OPTIMIZATION_PLAN.md +496 -0
  35. package/package.json +14 -12
  36. package/scripts/check-coverage.ts +64 -0
  37. package/src/Mailable.ts +340 -44
  38. package/src/OrbitSignal.ts +350 -50
  39. package/src/TypedMailable.ts +96 -0
  40. package/src/dev/DevMailbox.ts +89 -33
  41. package/src/dev/DevServer.ts +14 -14
  42. package/src/dev/storage/FileMailboxStorage.ts +66 -0
  43. package/src/dev/storage/MailboxStorage.ts +15 -0
  44. package/src/dev/storage/MemoryMailboxStorage.ts +36 -0
  45. package/src/dev/ui/mailbox.ts +1 -1
  46. package/src/dev/ui/preview.ts +4 -4
  47. package/src/errors.ts +69 -0
  48. package/src/events.ts +72 -0
  49. package/src/index.ts +20 -1
  50. package/src/renderers/HtmlRenderer.ts +20 -18
  51. package/src/renderers/MjmlRenderer.ts +73 -0
  52. package/src/renderers/ReactMjmlRenderer.ts +94 -0
  53. package/src/renderers/ReactRenderer.ts +26 -21
  54. package/src/renderers/Renderer.ts +43 -3
  55. package/src/renderers/TemplateRenderer.ts +48 -15
  56. package/src/renderers/VueMjmlRenderer.ts +99 -0
  57. package/src/renderers/VueRenderer.ts +26 -21
  58. package/src/renderers/mjml-templates.ts +50 -0
  59. package/src/transports/BaseTransport.ts +148 -0
  60. package/src/transports/LogTransport.ts +28 -6
  61. package/src/transports/MemoryTransport.ts +34 -6
  62. package/src/transports/SesTransport.ts +62 -17
  63. package/src/transports/SmtpTransport.ts +123 -27
  64. package/src/transports/Transport.ts +33 -4
  65. package/src/types.ts +172 -3
  66. package/src/utils/html.ts +43 -0
  67. package/src/webhooks/SendGridWebhookDriver.ts +80 -0
  68. package/src/webhooks/SesWebhookDriver.ts +44 -0
  69. package/tests/DevMailbox.test.ts +54 -0
  70. package/tests/FileMailboxStorage.test.ts +56 -0
  71. package/tests/MjmlLayout.test.ts +28 -0
  72. package/tests/MjmlRenderer.test.ts +53 -0
  73. package/tests/OrbitSignalWebhook.test.ts +56 -0
  74. package/tests/ReactMjmlRenderer.test.ts +33 -0
  75. package/tests/SendGridWebhookDriver.test.ts +69 -0
  76. package/tests/SesWebhookDriver.test.ts +46 -0
  77. package/tests/VueMjmlRenderer.test.ts +35 -0
  78. package/tests/dev-server.test.ts +1 -1
  79. package/tests/transports.test.ts +3 -3
  80. package/tsconfig.json +12 -24
  81. package/dist/OrbitMail-2Z7ZTKYA.mjs +0 -7
  82. package/dist/OrbitMail-BGV32HWN.mjs +0 -7
  83. package/dist/OrbitMail-FUYZQSAV.mjs +0 -7
  84. package/dist/OrbitMail-NAPCRK7B.mjs +0 -7
  85. package/dist/OrbitMail-REGJ276B.mjs +0 -7
  86. package/dist/OrbitMail-TCFBJWDT.mjs +0 -7
  87. package/dist/OrbitMail-XZZW6U4N.mjs +0 -7
  88. package/dist/OrbitSignal-IPSA2CDO.mjs +0 -7
  89. package/dist/OrbitSignal-MABW4DDW.mjs +0 -7
  90. package/dist/OrbitSignal-QSW5VQ5M.mjs +0 -7
  91. package/dist/OrbitSignal-R22QHWAA.mjs +0 -7
  92. package/dist/OrbitSignal-ZKKMEC27.mjs +0 -7
  93. package/dist/chunk-3U2CYJO5.mjs +0 -367
  94. package/dist/chunk-3XFC4T6M.mjs +0 -392
  95. package/dist/chunk-456QRYFW.mjs +0 -401
  96. package/dist/chunk-DT3R2TNV.mjs +0 -367
  97. package/dist/chunk-F6MVTUCT.mjs +0 -421
  98. package/dist/chunk-GADWIVC4.mjs +0 -400
  99. package/dist/chunk-HHKFAMSE.mjs +0 -380
  100. package/dist/chunk-NEQCQSZI.mjs +0 -406
  101. package/dist/chunk-OKRNL6PN.mjs +0 -400
  102. package/dist/chunk-ULN3GMY2.mjs +0 -367
  103. package/dist/chunk-XAWO7RSP.mjs +0 -398
  104. package/dist/chunk-YLVDJSED.mjs +0 -431
package/src/Mailable.ts CHANGED
@@ -11,21 +11,53 @@ type ComponentType = any
11
11
  /**
12
12
  * Base class for all mailable messages.
13
13
  *
14
- * Provides a fluent API for building email envelopes and rendering content
15
- * using various engines (raw HTML, Prism templates, React, or Vue).
14
+ * @description
15
+ * Mailable provides a fluent API to build email envelopes and render content
16
+ * using multiple engines: HTML, Prism templates, React, and Vue components.
17
+ *
18
+ * @architecture
19
+ * ```
20
+ * Mailable
21
+ * ├── Envelope (from, to, subject, cc, bcc, attachments)
22
+ * ├── Renderer (HtmlRenderer | TemplateRenderer | ReactRenderer | VueRenderer)
23
+ * └── Queueable (queue support interface)
24
+ * ```
25
+ *
26
+ * @lifecycle
27
+ * 1. Create Mailable subclass
28
+ * 2. Implement build() method to configure envelope and content
29
+ * 3. Call send() to send immediately, or queue() for background processing
30
+ * 4. OrbitSignal calls buildEnvelope() → renderContent() → transport.send()
16
31
  *
17
32
  * @example
18
33
  * ```typescript
19
- * class WelcomeMail extends Mailable {
34
+ * import { Mailable } from '@gravito/signal'
35
+ *
36
+ * class WelcomeEmail extends Mailable {
37
+ * constructor(private user: User) {
38
+ * super()
39
+ * }
40
+ *
20
41
  * build() {
21
- * return this.subject('Welcome!')
22
- * .view('emails.welcome', { name: 'John' });
42
+ * return this
43
+ * .to(this.user.email)
44
+ * .subject('Welcome!')
45
+ * .view('emails/welcome', { name: this.user.name })
23
46
  * }
24
47
  * }
25
48
  *
26
- * await new WelcomeMail().to('john@example.com').send();
49
+ * // Send immediately
50
+ * await mail.send(new WelcomeEmail(user))
51
+ *
52
+ * // Queue for background processing
53
+ * await new WelcomeEmail(user).onQueue('emails').queue()
27
54
  * ```
28
55
  *
56
+ * @see {@link OrbitSignal} Mail service orchestrator
57
+ * @see {@link Renderer} Content rendering interface
58
+ * @see {@link Envelope} Email metadata structure
59
+ * @see {@link Queueable} Queue integration interface
60
+ *
29
61
  * @public
30
62
  * @since 3.0.0
31
63
  */
@@ -41,7 +73,17 @@ export abstract class Mailable implements Queueable {
41
73
  /**
42
74
  * Set the sender address for the email.
43
75
  *
44
- * @param address - Email address or Address object.
76
+ * This defines the "From" field in the email envelope. If not called, the default
77
+ * sender from the mail configuration will be used.
78
+ *
79
+ * @param address - The email address or address object containing name and address.
80
+ * @returns The current mailable instance for chaining.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * mailable.from('admin@example.com')
85
+ * mailable.from({ name: 'Support', address: 'support@example.com' })
86
+ * ```
45
87
  */
46
88
  from(address: string | Address): this {
47
89
  this.envelope.from = typeof address === 'string' ? { address } : address
@@ -51,7 +93,17 @@ export abstract class Mailable implements Queueable {
51
93
  /**
52
94
  * Set the primary recipient(s) for the email.
53
95
  *
54
- * @param address - Single address, address object, or array of either.
96
+ * Configures the "To" field. Supports single or multiple recipients in various formats.
97
+ *
98
+ * @param address - A single email string, an address object, or an array of either.
99
+ * @returns The current mailable instance for chaining.
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * mailable.to('user@example.com')
104
+ * mailable.to(['a@example.com', 'b@example.com'])
105
+ * mailable.to({ name: 'John', address: 'john@example.com' })
106
+ * ```
55
107
  */
56
108
  to(address: string | Address | (string | Address)[]): this {
57
109
  this.envelope.to = this.normalizeAddressArray(address)
@@ -61,7 +113,15 @@ export abstract class Mailable implements Queueable {
61
113
  /**
62
114
  * Set the carbon copy (CC) recipient(s).
63
115
  *
64
- * @param address - Single address, address object, or array of either.
116
+ * Adds recipients to the "Cc" field of the email.
117
+ *
118
+ * @param address - A single email string, an address object, or an array of either.
119
+ * @returns The current mailable instance for chaining.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * mailable.cc('manager@example.com')
124
+ * ```
65
125
  */
66
126
  cc(address: string | Address | (string | Address)[]): this {
67
127
  this.envelope.cc = this.normalizeAddressArray(address)
@@ -71,7 +131,15 @@ export abstract class Mailable implements Queueable {
71
131
  /**
72
132
  * Set the blind carbon copy (BCC) recipient(s).
73
133
  *
74
- * @param address - Single address, address object, or array of either.
134
+ * Adds recipients to the "Bcc" field. These recipients are hidden from others.
135
+ *
136
+ * @param address - A single email string, an address object, or an array of either.
137
+ * @returns The current mailable instance for chaining.
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * mailable.bcc('audit@example.com')
142
+ * ```
75
143
  */
76
144
  bcc(address: string | Address | (string | Address)[]): this {
77
145
  this.envelope.bcc = this.normalizeAddressArray(address)
@@ -81,7 +149,15 @@ export abstract class Mailable implements Queueable {
81
149
  /**
82
150
  * Set the reply-to address.
83
151
  *
84
- * @param address - Email address or Address object.
152
+ * Specifies where replies to this email should be directed.
153
+ *
154
+ * @param address - The email address or address object for replies.
155
+ * @returns The current mailable instance for chaining.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * mailable.replyTo('no-reply@example.com')
160
+ * ```
85
161
  */
86
162
  replyTo(address: string | Address): this {
87
163
  this.envelope.replyTo = typeof address === 'string' ? { address } : address
@@ -91,7 +167,15 @@ export abstract class Mailable implements Queueable {
91
167
  /**
92
168
  * Set the subject line for the email.
93
169
  *
94
- * @param subject - The email subject.
170
+ * Defines the text that appears in the recipient's inbox subject field.
171
+ *
172
+ * @param subject - The subject text.
173
+ * @returns The current mailable instance for chaining.
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * mailable.subject('Your Order Confirmation')
178
+ * ```
95
179
  */
96
180
  subject(subject: string): this {
97
181
  this.envelope.subject = subject
@@ -101,7 +185,15 @@ export abstract class Mailable implements Queueable {
101
185
  /**
102
186
  * Set the email priority.
103
187
  *
104
- * @param level - Priority level ('high', 'normal', or 'low').
188
+ * Hints to the email client how urgent this message is.
189
+ *
190
+ * @param level - The priority level: 'high', 'normal', or 'low'.
191
+ * @returns The current mailable instance for chaining.
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * mailable.emailPriority('high')
196
+ * ```
105
197
  */
106
198
  emailPriority(level: 'high' | 'normal' | 'low'): this {
107
199
  this.envelope.priority = level
@@ -111,7 +203,18 @@ export abstract class Mailable implements Queueable {
111
203
  /**
112
204
  * Attach a file to the email.
113
205
  *
114
- * @param attachment - Attachment configuration object.
206
+ * Adds a file attachment to the message. Can be called multiple times for multiple files.
207
+ *
208
+ * @param attachment - The attachment configuration including path, content, or filename.
209
+ * @returns The current mailable instance for chaining.
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * mailable.attach({
214
+ * filename: 'invoice.pdf',
215
+ * path: './storage/invoices/123.pdf'
216
+ * })
217
+ * ```
115
218
  */
116
219
  attach(attachment: Attachment): this {
117
220
  this.envelope.attachments = this.envelope.attachments || []
@@ -122,9 +225,17 @@ export abstract class Mailable implements Queueable {
122
225
  // ===== Content Methods (Renderer Selection) =====
123
226
 
124
227
  /**
125
- * Set the content using raw HTML string.
228
+ * Set the content using a raw HTML string.
229
+ *
230
+ * Use this for simple emails where a full template engine is not required.
126
231
  *
127
- * @param content - The HTML content string.
232
+ * @param content - The raw HTML content.
233
+ * @returns The current mailable instance for chaining.
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * mailable.html('<h1>Hello</h1><p>Welcome to our platform.</p>')
238
+ * ```
128
239
  */
129
240
  html(content: string): this {
130
241
  this.renderer = new HtmlRenderer(content)
@@ -134,8 +245,17 @@ export abstract class Mailable implements Queueable {
134
245
  /**
135
246
  * Set the content using an OrbitPrism template.
136
247
  *
137
- * @param template - Template name (relative to viewsDir/emails).
138
- * @param data - Optional data to pass to the template.
248
+ * Renders a template file with the provided data. This is the recommended way
249
+ * to build complex, data-driven emails.
250
+ *
251
+ * @param template - The template name or path relative to the configured views directory.
252
+ * @param data - The data object to be injected into the template.
253
+ * @returns The current mailable instance for chaining.
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * mailable.view('emails.welcome', { name: 'Alice' })
258
+ * ```
139
259
  */
140
260
  view(template: string, data?: Record<string, unknown>): this {
141
261
  this.renderer = new TemplateRenderer(template, undefined) // Dir will be injected later if possible, or use default
@@ -145,11 +265,19 @@ export abstract class Mailable implements Queueable {
145
265
 
146
266
  /**
147
267
  * Set the content using a React component.
148
- * Dynamically imports ReactRenderer to avoid hard dependency errors if React is not installed.
149
268
  *
150
- * @param component - The React component to render.
151
- * @param props - Optional props for the component.
152
- * @param deps - Optional dependencies (React, ReactDOMServer) if not globally available.
269
+ * Leverages React's component model for email design. The renderer is loaded
270
+ * dynamically to keep the core package lightweight.
271
+ *
272
+ * @param component - The React component class or function.
273
+ * @param props - The properties to pass to the component.
274
+ * @param deps - Optional React/ReactDOMServer overrides for custom environments.
275
+ * @returns The current mailable instance for chaining.
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * mailable.react(WelcomeEmailComponent, { name: 'Alice' })
280
+ * ```
153
281
  */
154
282
  react<P extends object>(
155
283
  component: ComponentType,
@@ -168,11 +296,19 @@ export abstract class Mailable implements Queueable {
168
296
 
169
297
  /**
170
298
  * Set the content using a Vue component.
171
- * Dynamically imports VueRenderer to avoid hard dependency errors if Vue is not installed.
172
299
  *
173
- * @param component - The Vue component to render.
174
- * @param props - Optional props for the component.
175
- * @param deps - Optional dependencies (Vue, VueServerRenderer) if not globally available.
300
+ * Leverages Vue's component model for email design. The renderer is loaded
301
+ * dynamically to keep the core package lightweight.
302
+ *
303
+ * @param component - The Vue component object.
304
+ * @param props - The properties to pass to the component.
305
+ * @param deps - Optional Vue/VueServerRenderer overrides for custom environments.
306
+ * @returns The current mailable instance for chaining.
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * mailable.vue(WelcomeEmailComponent, { name: 'Alice' })
311
+ * ```
176
312
  */
177
313
  vue<P extends object>(
178
314
  component: ComponentType,
@@ -190,11 +326,91 @@ export abstract class Mailable implements Queueable {
190
326
  return this
191
327
  }
192
328
 
329
+ /**
330
+ * Set the content using an MJML markup string.
331
+ *
332
+ * MJML ensures responsive email compatibility across various clients.
333
+ *
334
+ * @param content - The MJML markup string or inner content.
335
+ * @param options - MJML transformation options.
336
+ * @param options.layout - Optional full MJML layout string. Use '{{content}}' as placeholder.
337
+ * @returns The current mailable instance for chaining.
338
+ *
339
+ * @example
340
+ * ```typescript
341
+ * mailable.mjml('<mj-text>Hello</mj-text>', {
342
+ * layout: '<mjml><mj-body>{{content}}</mj-body></mjml>'
343
+ * })
344
+ * ```
345
+ */
346
+ mjml(content: string, options?: Record<string, any> & { layout?: string }): this {
347
+ const finalContent = options?.layout?.includes('{{content}}')
348
+ ? options.layout.replace('{{content}}', content)
349
+ : content
350
+
351
+ this.rendererResolver = async () => {
352
+ const { MjmlRenderer } = await import('./renderers/MjmlRenderer')
353
+ return new MjmlRenderer(finalContent, options)
354
+ }
355
+ return this
356
+ }
357
+
358
+ /**
359
+ * Set the content using a React component that outputs MJML.
360
+ *
361
+ * @param component - The React component.
362
+ * @param props - Component properties.
363
+ * @param options - MJML options.
364
+ * @returns The current mailable instance for chaining.
365
+ */
366
+ mjmlReact<P extends object>(
367
+ component: ComponentType,
368
+ props?: P,
369
+ options?: Record<string, any>
370
+ ): this {
371
+ this.rendererResolver = async () => {
372
+ const { ReactMjmlRenderer } = await import('./renderers/ReactMjmlRenderer')
373
+ return new ReactMjmlRenderer(component, props, options)
374
+ }
375
+ return this
376
+ }
377
+
378
+ /**
379
+ * Set the content using a Vue component that outputs MJML.
380
+ *
381
+ * @param component - The Vue component.
382
+ * @param props - Component properties.
383
+ * @param options - MJML options.
384
+ * @returns The current mailable instance for chaining.
385
+ */
386
+ mjmlVue<P extends object>(
387
+ component: ComponentType,
388
+ props?: P,
389
+ options?: Record<string, any>
390
+ ): this {
391
+ this.rendererResolver = async () => {
392
+ const { VueMjmlRenderer } = await import('./renderers/VueMjmlRenderer')
393
+ return new VueMjmlRenderer(component, props, options)
394
+ }
395
+ return this
396
+ }
397
+
193
398
  // ===== Life Cycle =====
194
399
 
195
400
  /**
196
- * Setup the mailable. This is where you call from(), to(), view(), etc.
197
- * This method must be implemented by concrete classes.
401
+ * Configure the mailable's envelope and content.
402
+ *
403
+ * This abstract method must be implemented by subclasses to define the email's
404
+ * recipients, subject, and body using the fluent API.
405
+ *
406
+ * @returns The current mailable instance.
407
+ *
408
+ * @example
409
+ * ```typescript
410
+ * build() {
411
+ * return this.to('user@example.com').subject('Hi').html('...')
412
+ * }
413
+ * ```
198
414
  */
199
415
  abstract build(): this
200
416
 
@@ -210,7 +426,15 @@ export abstract class Mailable implements Queueable {
210
426
  priority?: number | string
211
427
 
212
428
  /**
213
- * Set the queue name for this mailable.
429
+ * Set the target queue for background processing.
430
+ *
431
+ * @param queue - The name of the queue.
432
+ * @returns The current mailable instance for chaining.
433
+ *
434
+ * @example
435
+ * ```typescript
436
+ * mailable.onQueue('notifications')
437
+ * ```
214
438
  */
215
439
  onQueue(queue: string): this {
216
440
  this.queueName = queue
@@ -218,7 +442,15 @@ export abstract class Mailable implements Queueable {
218
442
  }
219
443
 
220
444
  /**
221
- * Set the connection name for this mailable.
445
+ * Set the queue connection to be used.
446
+ *
447
+ * @param connection - The name of the connection (e.g., 'redis', 'sqs').
448
+ * @returns The current mailable instance for chaining.
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * mailable.onConnection('redis')
453
+ * ```
222
454
  */
223
455
  onConnection(connection: string): this {
224
456
  this.connectionName = connection
@@ -226,7 +458,17 @@ export abstract class Mailable implements Queueable {
226
458
  }
227
459
 
228
460
  /**
229
- * Set a delay for the queued mailable.
461
+ * Set a delay for the queued message.
462
+ *
463
+ * The message will remain in the queue and only be processed after the delay.
464
+ *
465
+ * @param seconds - The delay in seconds.
466
+ * @returns The current mailable instance for chaining.
467
+ *
468
+ * @example
469
+ * ```typescript
470
+ * mailable.delay(3600) // Delay for 1 hour
471
+ * ```
230
472
  */
231
473
  delay(seconds: number): this {
232
474
  this.delaySeconds = seconds
@@ -234,7 +476,17 @@ export abstract class Mailable implements Queueable {
234
476
  }
235
477
 
236
478
  /**
237
- * Set the priority for the queued mailable.
479
+ * Set the priority for the queued message.
480
+ *
481
+ * Higher priority messages are typically processed before lower priority ones.
482
+ *
483
+ * @param priority - The priority value (numeric or string).
484
+ * @returns The current mailable instance for chaining.
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * mailable.withPriority(10)
489
+ * ```
238
490
  */
239
491
  withPriority(priority: string | number): this {
240
492
  this.priority = priority
@@ -242,8 +494,17 @@ export abstract class Mailable implements Queueable {
242
494
  }
243
495
 
244
496
  /**
245
- * Queue the mailable for sending.
246
- * Attempts to resolve the mail service from the PlanetCore container.
497
+ * Push the mailable onto the configured queue.
498
+ *
499
+ * Automatically resolves the mail service from the Gravito container and
500
+ * dispatches this mailable for background processing.
501
+ *
502
+ * @returns A promise that resolves when the mailable is queued.
503
+ *
504
+ * @example
505
+ * ```typescript
506
+ * await new WelcomeEmail(user).queue()
507
+ * ```
247
508
  */
248
509
  async queue(): Promise<void> {
249
510
  // We should ideally use the container to get the mail service
@@ -268,9 +529,17 @@ export abstract class Mailable implements Queueable {
268
529
  protected translator?: (key: string, replace?: Record<string, unknown>, locale?: string) => string
269
530
 
270
531
  /**
271
- * Set the locale for the message.
532
+ * Set the locale for the email content.
533
+ *
534
+ * Used by the translator to resolve localized strings in templates or components.
535
+ *
536
+ * @param locale - The locale identifier (e.g., 'en-US', 'fr').
537
+ * @returns The current mailable instance for chaining.
272
538
  *
273
- * @param locale - Valid locale string (e.g., 'en', 'zh-TW').
539
+ * @example
540
+ * ```typescript
541
+ * mailable.locale('es')
542
+ * ```
274
543
  */
275
544
  locale(locale: string): this {
276
545
  this.currentLocale = locale
@@ -288,11 +557,18 @@ export abstract class Mailable implements Queueable {
288
557
  }
289
558
 
290
559
  /**
291
- * Translate a string using the configured translator.
560
+ * Translate a key into a localized string.
292
561
  *
293
- * @param key - Translation key.
294
- * @param replace - Interpolation variables.
295
- * @returns Translated string or the key if translator is missing.
562
+ * Uses the configured translator and current locale to resolve the key.
563
+ *
564
+ * @param key - The translation key.
565
+ * @param replace - Key-value pairs for string interpolation.
566
+ * @returns The translated string, or the key itself if no translator is available.
567
+ *
568
+ * @example
569
+ * ```typescript
570
+ * const text = mailable.t('messages.welcome', { name: 'Alice' })
571
+ * ```
296
572
  */
297
573
  t(key: string, replace?: Record<string, unknown>): string {
298
574
  if (this.translator) {
@@ -304,8 +580,18 @@ export abstract class Mailable implements Queueable {
304
580
  // ===== Internal Systems =====
305
581
 
306
582
  /**
307
- * Compile the envelope based on config defaults and mailable settings.
308
- * Called by OrbitSignal before rendering/sending.
583
+ * Compile the final email envelope.
584
+ *
585
+ * Merges mailable-specific settings with global configuration defaults.
586
+ * This is called internally by the mail service before sending.
587
+ *
588
+ * @param configPromise - The mail configuration or a promise resolving to it.
589
+ * @returns The fully constructed envelope.
590
+ *
591
+ * @example
592
+ * ```typescript
593
+ * const envelope = await mailable.buildEnvelope(config)
594
+ * ```
309
595
  */
310
596
  async buildEnvelope(configPromise: MailConfig | Promise<MailConfig>): Promise<Envelope> {
311
597
  const config = await Promise.resolve(configPromise)
@@ -348,8 +634,18 @@ export abstract class Mailable implements Queueable {
348
634
  }
349
635
 
350
636
  /**
351
- * Execute the renderer and produce HTML/Text content.
352
- * @returns Object containing rendered html and optional text content.
637
+ * Render the email content to HTML and plain text.
638
+ *
639
+ * Executes the chosen renderer (HTML, Template, React, or Vue) with the
640
+ * provided data and i18n helpers.
641
+ *
642
+ * @returns The rendered HTML and optional plain text content.
643
+ * @throws {Error} If no renderer has been specified.
644
+ *
645
+ * @example
646
+ * ```typescript
647
+ * const { html } = await mailable.renderContent()
648
+ * ```
353
649
  */
354
650
  async renderContent(): Promise<{ html: string; text?: string }> {
355
651
  // Resolve lazy renderer if needed