@nixxie-cms/email 1.0.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.
package/src/types.ts ADDED
@@ -0,0 +1,279 @@
1
+ import type {
2
+ NixxieEmailAttachment,
3
+ NixxieEmailQueueOptions,
4
+ NixxieEmailRecipient,
5
+ NixxieEmailSendOptions,
6
+ NixxieEmailSentInfo,
7
+ NixxieEmailQueueStats,
8
+ } from '@nixxie-cms/core/types'
9
+
10
+ // ── Re-export the shared types so consumers only need @nixxie-cms/email ──
11
+ export type {
12
+ NixxieEmailAttachment as EmailAttachment,
13
+ NixxieEmailQueueOptions as QueueEmailOptions,
14
+ NixxieEmailRecipient as EmailRecipient,
15
+ NixxieEmailSendOptions as SendEmailOptions,
16
+ NixxieEmailSentInfo as SentEmailInfo,
17
+ NixxieEmailQueueStats as EmailQueueStats,
18
+ }
19
+
20
+ // ─────────────────────────────────────────────────────────────
21
+ // Transport configs
22
+ // ─────────────────────────────────────────────────────────────
23
+
24
+ export type SmtpTransportConfig = {
25
+ type: 'smtp'
26
+ host: string
27
+ port?: number
28
+ secure?: boolean
29
+ auth?: {
30
+ user: string
31
+ pass: string
32
+ }
33
+ tls?: {
34
+ rejectUnauthorized?: boolean
35
+ ciphers?: string
36
+ }
37
+ connectionTimeout?: number
38
+ greetingTimeout?: number
39
+ socketTimeout?: number
40
+ pool?: boolean
41
+ maxConnections?: number
42
+ maxMessages?: number
43
+ }
44
+
45
+ export type SendGridTransportConfig = {
46
+ type: 'sendgrid'
47
+ apiKey: string
48
+ }
49
+
50
+ export type MailgunTransportConfig = {
51
+ type: 'mailgun'
52
+ apiKey: string
53
+ domain: string
54
+ /** 'us' (default) or 'eu' */
55
+ region?: 'us' | 'eu'
56
+ }
57
+
58
+ export type SesTransportConfig = {
59
+ type: 'ses'
60
+ region: string
61
+ credentials?: {
62
+ accessKeyId: string
63
+ secretAccessKey: string
64
+ sessionToken?: string
65
+ }
66
+ }
67
+
68
+ export type ResendTransportConfig = {
69
+ type: 'resend'
70
+ apiKey: string
71
+ }
72
+
73
+ /** Development transport — logs emails to the console instead of sending */
74
+ export type ConsoleTransportConfig = {
75
+ type: 'console'
76
+ }
77
+
78
+ export type EmailTransportConfig =
79
+ | SmtpTransportConfig
80
+ | SendGridTransportConfig
81
+ | MailgunTransportConfig
82
+ | SesTransportConfig
83
+ | ResendTransportConfig
84
+ | ConsoleTransportConfig
85
+
86
+ // ─────────────────────────────────────────────────────────────
87
+ // Template config
88
+ // ─────────────────────────────────────────────────────────────
89
+
90
+ export type EmailTemplateEngine = 'handlebars' | 'pug' | 'auto'
91
+
92
+ export type EmailTemplatesConfig = {
93
+ /** Absolute path to the templates directory */
94
+ dir: string
95
+ /**
96
+ * Default template engine. Use `'auto'` to detect the engine per-template from the file
97
+ * extension (.hbs/.handlebars vs .pug/.jade).
98
+ * @default 'handlebars'
99
+ */
100
+ engine?: EmailTemplateEngine
101
+ /**
102
+ * Enable layout support.
103
+ * Place a `layouts/base.hbs` (or `.pug`) file and use `{{{body}}}` inside it.
104
+ * @default true
105
+ */
106
+ layouts?: boolean
107
+ /**
108
+ * Auto-load Handlebars partials from `partials/` subdirectory.
109
+ * @default true
110
+ */
111
+ partials?: boolean
112
+ /**
113
+ * Options passed directly to the underlying template engine.
114
+ * For Handlebars: `{ noEscape?: boolean, helpers?: Record<string, Function> }`
115
+ * For Pug: `{ pretty?: boolean, filters?: object }`
116
+ */
117
+ engineOptions?: Record<string, unknown>
118
+ /**
119
+ * Reload templates from disk on every render (useful in development).
120
+ * @default false
121
+ */
122
+ cache?: boolean
123
+ }
124
+
125
+ // ─────────────────────────────────────────────────────────────
126
+ // Queue config
127
+ // ─────────────────────────────────────────────────────────────
128
+
129
+ export type EmailQueueConfig = {
130
+ /** Enabled unless explicitly set to false. @default true */
131
+ enabled?: boolean
132
+ /** Number of emails processed in parallel @default 5 */
133
+ concurrency?: number
134
+ /** How many times to retry a failed send @default 3 */
135
+ retries?: number
136
+ /**
137
+ * Base delay in ms between retries — doubled on each subsequent attempt.
138
+ * @default 5000
139
+ */
140
+ retryDelay?: number
141
+ /** Discard jobs older than this (ms). 0 = never discard. @default 86400000 (24h) */
142
+ maxAge?: number
143
+ }
144
+
145
+ // ─────────────────────────────────────────────────────────────
146
+ // Tracking config
147
+ // ─────────────────────────────────────────────────────────────
148
+
149
+ export type EmailTrackingConfig = {
150
+ /** Track email opens via a 1×1 pixel. @default false */
151
+ opens?: boolean
152
+ /** Rewrite links to track clicks. @default false */
153
+ clicks?: boolean
154
+ /**
155
+ * Base URL prepended to all tracking endpoints.
156
+ * Required when opens or clicks tracking is enabled.
157
+ */
158
+ baseUrl: string
159
+ /** Path prefix for tracking routes. @default '/email-tracking' */
160
+ path?: string
161
+ }
162
+
163
+ // ─────────────────────────────────────────────────────────────
164
+ // Development config
165
+ // ─────────────────────────────────────────────────────────────
166
+
167
+ export type EmailDevelopmentConfig = {
168
+ /**
169
+ * When true, emails are not sent — they are logged and optionally previewed.
170
+ * @default process.env.NODE_ENV !== 'production'
171
+ */
172
+ enabled?: boolean
173
+ /**
174
+ * Write rendered HTML to this directory as .html files for browser preview.
175
+ * Filenames are `{template}-{timestamp}.html`.
176
+ */
177
+ previewPath?: string
178
+ /**
179
+ * Override the "to" address for all emails in development mode.
180
+ * Useful for catching all outgoing mail in one inbox.
181
+ */
182
+ toOverride?: string | string[]
183
+ }
184
+
185
+ // ─────────────────────────────────────────────────────────────
186
+ // Callbacks
187
+ // ─────────────────────────────────────────────────────────────
188
+
189
+ export type EmailSentCallback = (info: NixxieEmailSentInfo, options: NixxieEmailSendOptions) => void | Promise<void>
190
+ export type EmailFailedCallback = (error: Error, options: NixxieEmailSendOptions) => void | Promise<void>
191
+
192
+ // ─────────────────────────────────────────────────────────────
193
+ // Top-level EmailConfig (accepted by createEmail())
194
+ // ─────────────────────────────────────────────────────────────
195
+
196
+ export type EmailConfig = {
197
+ /** Transport configuration — defines how emails are physically sent */
198
+ transport: EmailTransportConfig
199
+
200
+ /**
201
+ * Default "from" address used when `SendEmailOptions.from` is not set.
202
+ * Can be a plain address string or an object with name + address.
203
+ */
204
+ from: NixxieEmailRecipient
205
+
206
+ /** Default reply-to address */
207
+ replyTo?: NixxieEmailRecipient
208
+
209
+ /** Template engine configuration */
210
+ templates?: EmailTemplatesConfig
211
+
212
+ /** Outbound queue configuration */
213
+ queue?: EmailQueueConfig
214
+
215
+ /** Email open/click tracking */
216
+ tracking?: EmailTrackingConfig
217
+
218
+ /** Development-mode settings (preview, override recipients, etc.) */
219
+ development?: EmailDevelopmentConfig
220
+
221
+ /** Addresses that should never receive emails */
222
+ suppressionList?: string[]
223
+
224
+ /** Default headers appended to every message */
225
+ headers?: Record<string, string>
226
+
227
+ /** Called after every successfully sent email */
228
+ onSent?: EmailSentCallback
229
+
230
+ /** Called when an email fails to send */
231
+ onFailed?: EmailFailedCallback
232
+ }
233
+
234
+ // ─────────────────────────────────────────────────────────────
235
+ // Internal transport abstraction
236
+ // ─────────────────────────────────────────────────────────────
237
+
238
+ export type TransportMessage = {
239
+ from: string
240
+ to: string[]
241
+ cc?: string[]
242
+ bcc?: string[]
243
+ replyTo?: string[]
244
+ subject: string
245
+ html?: string
246
+ text?: string
247
+ attachments?: NixxieEmailAttachment[]
248
+ headers?: Record<string, string>
249
+ }
250
+
251
+ export type TransportResult = {
252
+ messageId: string
253
+ accepted: string[]
254
+ rejected: string[]
255
+ response?: string
256
+ }
257
+
258
+ export interface EmailTransporter {
259
+ send(message: TransportMessage): Promise<TransportResult>
260
+ verify(): Promise<boolean>
261
+ close(): Promise<void>
262
+ }
263
+
264
+ // ─────────────────────────────────────────────────────────────
265
+ // Queue internals
266
+ // ─────────────────────────────────────────────────────────────
267
+
268
+ export type QueueJobStatus = 'pending' | 'processing' | 'completed' | 'failed'
269
+
270
+ export type QueueJob = {
271
+ id: string
272
+ options: NixxieEmailQueueOptions
273
+ status: QueueJobStatus
274
+ attempts: number
275
+ createdAt: Date
276
+ sendAt?: Date
277
+ priority: 'high' | 'normal' | 'low'
278
+ lastError?: string
279
+ }