@igniter-js/mail 0.1.0 → 0.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.
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
  var nodemailer__default = /*#__PURE__*/_interopDefault(nodemailer);
12
12
  var React__default = /*#__PURE__*/_interopDefault(React);
13
13
 
14
- // src/errors/igniter-mail.error.ts
14
+ // src/errors/mail.error.ts
15
15
  var IgniterMailError = class _IgniterMailError extends core.IgniterError {
16
16
  constructor(payload) {
17
17
  super({
@@ -34,560 +34,375 @@ var IgniterMailError = class _IgniterMailError extends core.IgniterError {
34
34
  };
35
35
 
36
36
  // src/adapters/postmark.adapter.ts
37
- var PostmarkMailAdapterBuilder = class _PostmarkMailAdapterBuilder {
38
- /** Creates a new builder instance. */
39
- static create() {
40
- return new _PostmarkMailAdapterBuilder();
41
- }
42
- /** Sets the Postmark Server Token. */
43
- withSecret(secret) {
44
- this.secret = secret;
45
- return this;
37
+ var PostmarkMailAdapter = class _PostmarkMailAdapter {
38
+ /**
39
+ * Creates a new adapter instance.
40
+ *
41
+ * @param credentials - Provider credentials (secret/from).
42
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
43
+ */
44
+ constructor(credentials = {}) {
45
+ this.credentials = credentials;
46
46
  }
47
- /** Sets the default FROM address used when sending emails via Postmark. */
48
- withFrom(from) {
49
- this.from = from;
50
- return this;
47
+ /**
48
+ * Creates a new adapter instance.
49
+ *
50
+ * @param credentials - Provider credentials (secret/from).
51
+ * @returns A Postmark adapter instance.
52
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
53
+ * @example
54
+ * ```ts
55
+ * const adapter = PostmarkMailAdapter.create({ secret: 'token', from: 'no-reply@acme.com' })
56
+ * ```
57
+ */
58
+ static create(credentials) {
59
+ return new _PostmarkMailAdapter(credentials);
51
60
  }
52
- /** Builds the adapter instance. */
53
- build() {
54
- if (!this.secret) {
61
+ /**
62
+ * Sends an email using Postmark (HTTP API).
63
+ *
64
+ * @param params - Normalized email parameters.
65
+ * @returns A promise that resolves when the email is accepted.
66
+ * @throws {IgniterMailError} When configuration is invalid or Postmark rejects the request.
67
+ * @example
68
+ * ```ts
69
+ * await adapter.send({ to: 'user@example.com', subject: 'Hello', html: '<p>Hi</p>', text: 'Hi' })
70
+ * ```
71
+ */
72
+ async send(params) {
73
+ if (!this.credentials.secret) {
55
74
  throw new IgniterMailError({
56
75
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
57
76
  message: "Postmark adapter secret is required"
58
77
  });
59
78
  }
60
- if (!this.from) {
79
+ if (!this.credentials.from) {
61
80
  throw new IgniterMailError({
62
81
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
63
82
  message: "Postmark adapter from is required"
64
83
  });
65
84
  }
66
- const token = this.secret;
67
- const from = this.from;
68
- return {
69
- /** Sends an email using Postmark (HTTP API). */
70
- send: async ({ to, subject, html, text }) => {
71
- const response = await fetch("https://api.postmarkapp.com/email", {
72
- method: "POST",
73
- headers: {
74
- Accept: "application/json",
75
- "Content-Type": "application/json",
76
- "X-Postmark-Server-Token": token
77
- },
78
- body: JSON.stringify({
79
- From: from,
80
- To: to,
81
- Subject: subject,
82
- HtmlBody: html,
83
- TextBody: text
84
- })
85
- });
86
- if (!response.ok) {
87
- const body = await response.text().catch(() => "");
88
- throw new IgniterMailError({
89
- code: "MAIL_PROVIDER_SEND_FAILED",
90
- message: "Postmark send failed",
91
- metadata: {
92
- status: response.status,
93
- body
94
- }
95
- });
85
+ const token = this.credentials.secret;
86
+ const from = this.credentials.from;
87
+ const response = await fetch("https://api.postmarkapp.com/email", {
88
+ method: "POST",
89
+ headers: {
90
+ Accept: "application/json",
91
+ "Content-Type": "application/json",
92
+ "X-Postmark-Server-Token": token
93
+ },
94
+ body: JSON.stringify({
95
+ From: from,
96
+ To: params.to,
97
+ Subject: params.subject,
98
+ HtmlBody: params.html,
99
+ TextBody: params.text
100
+ })
101
+ });
102
+ if (!response.ok) {
103
+ const body = await response.text().catch(() => "");
104
+ throw new IgniterMailError({
105
+ code: "MAIL_PROVIDER_SEND_FAILED",
106
+ message: "Postmark send failed",
107
+ metadata: {
108
+ status: response.status,
109
+ body
96
110
  }
97
- }
98
- };
111
+ });
112
+ }
99
113
  }
100
114
  };
101
- var postmarkAdapter = (options) => PostmarkMailAdapterBuilder.create().withSecret(options.secret).withFrom(options.from).build();
102
- var ResendMailAdapterBuilder = class _ResendMailAdapterBuilder {
103
- /** Creates a new builder instance. */
104
- static create() {
105
- return new _ResendMailAdapterBuilder();
106
- }
107
- /** Sets the Resend API key. */
108
- withSecret(secret) {
109
- this.secret = secret;
110
- return this;
115
+ var ResendMailAdapter = class _ResendMailAdapter {
116
+ /**
117
+ * Creates an adapter with credentials.
118
+ *
119
+ * @param credentials - Adapter credentials including API secret and default from.
120
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
121
+ */
122
+ constructor(credentials = {}) {
123
+ this.credentials = credentials;
111
124
  }
112
- /** Sets the default FROM address used when sending emails via Resend. */
113
- withFrom(from) {
114
- this.from = from;
115
- return this;
125
+ /**
126
+ * Creates a new adapter instance.
127
+ *
128
+ * @param credentials - Adapter credentials including API secret and default from.
129
+ * @returns A configured Resend adapter.
130
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
131
+ * @example
132
+ * ```ts
133
+ * const adapter = ResendMailAdapter.create({ secret: 'token', from: 'no-reply@acme.com' })
134
+ * ```
135
+ */
136
+ static create(credentials) {
137
+ return new _ResendMailAdapter(credentials);
116
138
  }
117
- /** Builds the adapter instance. */
118
- build() {
119
- if (!this.secret) {
139
+ /**
140
+ * Sends an email using Resend.
141
+ *
142
+ * @param params - Email payload to send.
143
+ * @returns Resolves when the email is accepted by Resend.
144
+ * @throws {IgniterMailError} When credentials are missing or Resend rejects the request.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * await adapter.send({ to: 'user@example.com', subject: 'Welcome', html: '<p>Hi</p>', text: 'Hi' })
149
+ * ```
150
+ */
151
+ async send(params) {
152
+ if (!this.credentials.secret) {
120
153
  throw new IgniterMailError({
121
154
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
122
155
  message: "Resend adapter secret is required"
123
156
  });
124
157
  }
125
- if (!this.from) {
158
+ if (!this.credentials.from) {
126
159
  throw new IgniterMailError({
127
160
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
128
161
  message: "Resend adapter from is required"
129
162
  });
130
163
  }
131
- const resend$1 = new resend.Resend(this.secret);
132
- const from = this.from;
133
- return {
134
- /**
135
- * Sends an email using Resend.
136
- *
137
- * Note: Resend accepts `scheduledAt` as an ISO string.
138
- */
139
- send: async ({ to, subject, html, text, scheduledAt }) => {
140
- await resend$1.emails.create({
141
- to,
142
- from,
143
- subject,
144
- html,
145
- text,
146
- scheduledAt: scheduledAt?.toISOString()
147
- });
148
- }
149
- };
164
+ const resend$1 = new resend.Resend(this.credentials.secret);
165
+ const from = this.credentials.from;
166
+ await resend$1.emails.create({
167
+ to: params.to,
168
+ from,
169
+ subject: params.subject,
170
+ html: params.html,
171
+ text: params.text,
172
+ scheduledAt: params.scheduledAt?.toISOString()
173
+ });
150
174
  }
151
175
  };
152
- var resendAdapter = (options) => ResendMailAdapterBuilder.create().withSecret(options.secret).withFrom(options.from).build();
153
176
 
154
177
  // src/adapters/sendgrid.adapter.ts
155
- var SendGridMailAdapterBuilder = class _SendGridMailAdapterBuilder {
156
- /** Creates a new builder instance. */
157
- static create() {
158
- return new _SendGridMailAdapterBuilder();
159
- }
160
- /** Sets the SendGrid API key. */
161
- withSecret(secret) {
162
- this.secret = secret;
163
- return this;
178
+ var SendGridMailAdapter = class _SendGridMailAdapter {
179
+ /**
180
+ * Creates an adapter with credentials.
181
+ *
182
+ * @param credentials - Adapter credentials including API secret and default from.
183
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
184
+ */
185
+ constructor(credentials = {}) {
186
+ this.credentials = credentials;
164
187
  }
165
- /** Sets the default FROM address used when sending emails via SendGrid. */
166
- withFrom(from) {
167
- this.from = from;
168
- return this;
188
+ /**
189
+ * Creates a new adapter instance.
190
+ *
191
+ * @param credentials - Adapter credentials including API secret and default from.
192
+ * @returns A configured SendGrid adapter.
193
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
194
+ * @example
195
+ * ```ts
196
+ * const adapter = SendGridMailAdapter.create({ secret: 'token', from: 'no-reply@acme.com' })
197
+ * ```
198
+ */
199
+ static create(credentials) {
200
+ return new _SendGridMailAdapter(credentials);
169
201
  }
170
- /** Builds the adapter instance. */
171
- build() {
172
- if (!this.secret) {
202
+ /**
203
+ * Sends an email using SendGrid (HTTP API).
204
+ *
205
+ * @param params - Email payload to send.
206
+ * @returns Resolves when the email is accepted by SendGrid.
207
+ * @throws {IgniterMailError} When credentials are missing or the API fails.
208
+ *
209
+ * @example
210
+ * ```ts
211
+ * await adapter.send({ to: 'user@example.com', subject: 'Hi', html: '<p>Hi</p>', text: 'Hi' })
212
+ * ```
213
+ */
214
+ async send(params) {
215
+ if (!this.credentials.secret) {
173
216
  throw new IgniterMailError({
174
217
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
175
218
  message: "SendGrid adapter secret is required"
176
219
  });
177
220
  }
178
- if (!this.from) {
221
+ if (!this.credentials.from) {
179
222
  throw new IgniterMailError({
180
223
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
181
224
  message: "SendGrid adapter from is required"
182
225
  });
183
226
  }
184
- const apiKey = this.secret;
185
- const from = this.from;
186
- return {
187
- /** Sends an email using SendGrid (HTTP API). */
188
- send: async ({ to, subject, html, text }) => {
189
- const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
190
- method: "POST",
191
- headers: {
192
- Authorization: `Bearer ${apiKey}`,
193
- "Content-Type": "application/json"
194
- },
195
- body: JSON.stringify({
196
- personalizations: [{
197
- to: [{ email: to }]
198
- }],
199
- from: { email: from },
200
- subject,
201
- content: [
202
- { type: "text/plain", value: text },
203
- { type: "text/html", value: html }
204
- ]
205
- })
206
- });
207
- if (!response.ok) {
208
- const body = await response.text().catch(() => "");
209
- throw new IgniterMailError({
210
- code: "MAIL_PROVIDER_SEND_FAILED",
211
- message: "SendGrid send failed",
212
- metadata: {
213
- status: response.status,
214
- body
215
- }
216
- });
227
+ const apiKey = this.credentials.secret;
228
+ const from = this.credentials.from;
229
+ const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
230
+ method: "POST",
231
+ headers: {
232
+ Authorization: `Bearer ${apiKey}`,
233
+ "Content-Type": "application/json"
234
+ },
235
+ body: JSON.stringify({
236
+ personalizations: [
237
+ {
238
+ to: [{ email: params.to }]
239
+ }
240
+ ],
241
+ from: { email: from },
242
+ subject: params.subject,
243
+ content: [
244
+ { type: "text/plain", value: params.text },
245
+ { type: "text/html", value: params.html }
246
+ ]
247
+ })
248
+ });
249
+ if (!response.ok) {
250
+ const body = await response.text().catch(() => "");
251
+ throw new IgniterMailError({
252
+ code: "MAIL_PROVIDER_SEND_FAILED",
253
+ message: "SendGrid send failed",
254
+ metadata: {
255
+ status: response.status,
256
+ body
217
257
  }
218
- }
219
- };
258
+ });
259
+ }
220
260
  }
221
261
  };
222
- var sendgridAdapter = (options) => SendGridMailAdapterBuilder.create().withSecret(options.secret).withFrom(options.from).build();
223
- var SmtpMailAdapterBuilder = class _SmtpMailAdapterBuilder {
224
- /** Creates a new builder instance. */
225
- static create() {
226
- return new _SmtpMailAdapterBuilder();
227
- }
228
- /** Sets the SMTP connection URL (e.g. `smtps://user:pass@host:port`). */
229
- withSecret(secret) {
230
- this.secret = secret;
231
- return this;
262
+ var SmtpMailAdapter = class _SmtpMailAdapter {
263
+ /**
264
+ * Creates an adapter with credentials.
265
+ *
266
+ * @param credentials - Adapter credentials including SMTP URL and default from.
267
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
268
+ */
269
+ constructor(credentials = {}) {
270
+ this.credentials = credentials;
232
271
  }
233
- /** Sets the default FROM address used when sending emails via SMTP. */
234
- withFrom(from) {
235
- this.from = from;
236
- return this;
272
+ /**
273
+ * Creates a new adapter instance.
274
+ *
275
+ * @param credentials - Adapter credentials including SMTP URL and default from.
276
+ * @returns A configured SMTP adapter.
277
+ * @throws {IgniterMailError} Does not throw on creation; errors surface on send.
278
+ * @example
279
+ * ```ts
280
+ * const adapter = SmtpMailAdapter.create({ secret: 'smtps://user:pass@host:465', from: 'no-reply@acme.com' })
281
+ * ```
282
+ */
283
+ static create(credentials) {
284
+ return new _SmtpMailAdapter(credentials);
237
285
  }
238
- /** Builds the adapter instance. */
239
- build() {
240
- if (!this.secret) {
286
+ /**
287
+ * Sends an email using Nodemailer over SMTP.
288
+ *
289
+ * @param params - Email payload to send.
290
+ * @returns Resolves when the email is sent.
291
+ * @throws {IgniterMailError} When credentials are missing or the SMTP send fails.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * await adapter.send({ to: 'user@example.com', subject: 'Hi', html: '<p>Hi</p>', text: 'Hi' })
296
+ * ```
297
+ */
298
+ async send(params) {
299
+ if (!this.credentials.secret) {
241
300
  throw new IgniterMailError({
242
301
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
243
302
  message: "SMTP adapter secret is required"
244
303
  });
245
304
  }
246
- if (!this.from) {
305
+ if (!this.credentials.from) {
247
306
  throw new IgniterMailError({
248
307
  code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
249
308
  message: "SMTP adapter from is required"
250
309
  });
251
310
  }
252
- const smtpUrl = this.secret;
253
- const from = this.from;
254
- const createTransporter = () => {
255
- return nodemailer__default.default.createTransport(smtpUrl, {
256
- tls: {
257
- rejectUnauthorized: false
258
- },
259
- connectionTimeout: 1e4,
260
- greetingTimeout: 5e3,
261
- socketTimeout: 1e4
262
- });
263
- };
264
- return {
265
- /** Sends an email using Nodemailer over SMTP. */
266
- send: async ({ to, subject, html, text }) => {
267
- const transport = createTransporter();
268
- const mailOptions = {
269
- from,
270
- to,
271
- subject,
272
- html,
273
- text
274
- };
275
- try {
276
- await transport.sendMail(mailOptions);
277
- transport.close();
278
- } catch (error) {
279
- transport.close();
280
- throw error;
281
- }
311
+ const smtpUrl = this.credentials.secret;
312
+ const from = this.credentials.from;
313
+ const transport = nodemailer__default.default.createTransport(smtpUrl, {
314
+ connectionTimeout: 1e4,
315
+ greetingTimeout: 5e3,
316
+ socketTimeout: 1e4,
317
+ tls: {
318
+ rejectUnauthorized: false
282
319
  }
283
- };
284
- }
285
- };
286
- var smtpAdapter = (options) => SmtpMailAdapterBuilder.create().withSecret(options.secret).withFrom(options.from).build();
287
-
288
- // src/adapters/test.adapter.ts
289
- function createTestMailAdapter(options = {}) {
290
- const sent = [];
291
- const logger = options.logger ?? console;
292
- const silent = options.silent ?? false;
293
- return {
294
- sent,
295
- reset: () => {
296
- sent.length = 0;
297
- },
298
- last: () => sent.at(-1),
299
- send: async (params) => {
300
- sent.push({ ...params, at: /* @__PURE__ */ new Date() });
301
- if (!silent) {
302
- logger.info(
303
- `[TestMailAdapter] to=${params.to} subject=${params.subject} html=${params.html.length}B text=${params.text.length}B`
304
- );
305
- }
306
- }
307
- };
308
- }
309
-
310
- // src/adapters/webhook.adapter.ts
311
- var WebhookMailAdapterBuilder = class _WebhookMailAdapterBuilder {
312
- /** Creates a new builder instance. */
313
- static create() {
314
- return new _WebhookMailAdapterBuilder();
315
- }
316
- /**
317
- * Sets the webhook URL.
318
- *
319
- * Note: when using `IgniterMailBuilder.withAdapter('webhook', secret)`, the `secret`
320
- * is treated as the webhook URL.
321
- */
322
- withUrl(url) {
323
- this.url = url;
324
- return this;
325
- }
326
- /** Sets the default FROM address. */
327
- withFrom(from) {
328
- this.from = from;
329
- return this;
330
- }
331
- /** Builds the adapter instance. */
332
- build() {
333
- if (!this.url) {
334
- throw new IgniterMailError({
335
- code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
336
- message: "Webhook adapter url is required"
320
+ });
321
+ try {
322
+ await transport.sendMail({
323
+ from,
324
+ to: params.to,
325
+ subject: params.subject,
326
+ html: params.html,
327
+ text: params.text
337
328
  });
338
- }
339
- if (!this.from) {
329
+ } catch (error) {
340
330
  throw new IgniterMailError({
341
- code: "MAIL_ADAPTER_CONFIGURATION_INVALID",
342
- message: "Webhook adapter from is required"
331
+ code: "MAIL_PROVIDER_SEND_FAILED",
332
+ message: "SMTP send failed",
333
+ metadata: {
334
+ originalError: error
335
+ }
343
336
  });
337
+ } finally {
338
+ transport.close();
344
339
  }
345
- const url = this.url;
346
- const from = this.from;
347
- return {
348
- /** Sends an email by POST-ing to the configured webhook URL. */
349
- send: async ({ to, subject, html, text, scheduledAt }) => {
350
- const response = await fetch(url, {
351
- method: "POST",
352
- headers: {
353
- "Content-Type": "application/json"
354
- },
355
- body: JSON.stringify({
356
- to,
357
- from,
358
- subject,
359
- html,
360
- text,
361
- scheduledAt: scheduledAt?.toISOString()
362
- })
363
- });
364
- if (!response.ok) {
365
- const body = await response.text().catch(() => "");
366
- throw new IgniterMailError({
367
- code: "MAIL_PROVIDER_SEND_FAILED",
368
- message: "Webhook send failed",
369
- metadata: {
370
- status: response.status,
371
- body
372
- }
373
- });
374
- }
375
- }
376
- };
377
340
  }
378
341
  };
379
- var webhookAdapter = (options) => WebhookMailAdapterBuilder.create().withUrl(options.secret).withFrom(options.from).build();
380
342
 
381
- // src/builders/igniter-mail.builder.ts
382
- var IgniterMailBuilder = class _IgniterMailBuilder {
383
- constructor(factory) {
384
- this.templates = {};
385
- this.factory = factory;
386
- }
387
- /**
388
- * Creates a new builder.
389
- */
390
- static create(factory) {
391
- return new _IgniterMailBuilder(factory);
392
- }
393
- /** Sets the default FROM address. */
394
- withFrom(from) {
395
- this.from = from;
396
- return this;
397
- }
398
- /** Attaches a logger instance. */
399
- withLogger(logger) {
400
- this.logger = logger;
401
- return this;
402
- }
343
+ // src/types/telemetry.ts
344
+ var IGNITER_MAIL_TELEMETRY_EVENTS = {
345
+ /** Emitted when mail send operation starts */
346
+ SEND_STARTED: "igniter.mail.send.started",
347
+ /** Emitted when mail send operation succeeds */
348
+ SEND_SUCCESS: "igniter.mail.send.success",
349
+ /** Emitted when mail send operation fails */
350
+ SEND_ERROR: "igniter.mail.send.error",
351
+ /** Emitted when mail schedule operation starts */
352
+ SCHEDULE_STARTED: "igniter.mail.schedule.started",
353
+ /** Emitted when mail schedule operation succeeds */
354
+ SCHEDULE_SUCCESS: "igniter.mail.schedule.success",
355
+ /** Emitted when mail schedule operation fails */
356
+ SCHEDULE_ERROR: "igniter.mail.schedule.error"
357
+ };
358
+
359
+ // src/utils/schema.ts
360
+ var IgniterMailSchema = class {
403
361
  /**
404
- * Enables queue delivery.
362
+ * Validates an unknown input using `StandardSchemaV1` when the schema provides `~standard.validate`.
405
363
  *
406
- * If configured, `IgniterMail.schedule()` will enqueue jobs instead of using `setTimeout`.
407
- */
408
- withQueue(adapter, options) {
409
- this.queue = { adapter, options };
410
- return this;
411
- }
412
- withAdapter(adapterOrProvider, secret) {
413
- if (typeof adapterOrProvider === "string") {
414
- if (!secret) {
415
- throw new IgniterMailError({
416
- code: "MAIL_PROVIDER_ADAPTER_SECRET_REQUIRED",
417
- message: "MAIL_PROVIDER_ADAPTER_SECRET_REQUIRED",
418
- logger: this.logger
419
- });
420
- }
421
- this.adapter = {
422
- kind: "provider",
423
- provider: adapterOrProvider,
424
- secret
425
- };
426
- return this;
427
- }
428
- this.adapter = {
429
- kind: "adapter",
430
- adapter: adapterOrProvider
431
- };
432
- return this;
433
- }
434
- /**
435
- * Registers a template.
436
- */
437
- addTemplate(key, template) {
438
- this.templates[key] = template;
439
- return this;
440
- }
441
- /** Hook invoked before sending. */
442
- withOnSendStarted(onSendStarted) {
443
- this.onSendStarted = onSendStarted;
444
- return this;
445
- }
446
- /** Hook invoked on error. */
447
- withOnSendError(onSendError) {
448
- this.onSendError = onSendError;
449
- return this;
450
- }
451
- /** Hook invoked on success. */
452
- withOnSendSuccess(onSendSuccess) {
453
- this.onSendSuccess = onSendSuccess;
454
- return this;
455
- }
456
- /**
457
- * Builds the {@link IgniterMail} instance.
364
+ * If the schema does not provide a validator, this method returns the input as-is.
458
365
  */
459
- build() {
460
- if (!this.from) {
461
- throw new IgniterMailError({
462
- code: "MAIL_PROVIDER_FROM_REQUIRED",
463
- message: "MAIL_PROVIDER_FROM_REQUIRED",
464
- logger: this.logger
465
- });
366
+ static async validateInput(schema, input) {
367
+ const standard = schema?.["~standard"];
368
+ if (!standard?.validate) {
369
+ return input;
466
370
  }
467
- if (!this.adapter) {
371
+ const result = await standard.validate(input);
372
+ if (result?.issues?.length) {
468
373
  throw new IgniterMailError({
469
- code: "MAIL_PROVIDER_ADAPTER_REQUIRED",
470
- message: "MAIL_PROVIDER_ADAPTER_REQUIRED",
471
- logger: this.logger
374
+ code: "MAIL_PROVIDER_TEMPLATE_DATA_INVALID",
375
+ message: "Invalid mail template payload",
376
+ statusCode: 400,
377
+ details: result.issues
472
378
  });
473
379
  }
474
- const resolvedAdapter = this.adapter.kind === "adapter" ? this.adapter.adapter : (() => {
475
- switch (this.adapter.provider) {
476
- case "resend":
477
- return ResendMailAdapterBuilder.create().withSecret(this.adapter.secret).withFrom(this.from).build();
478
- case "smtp":
479
- return SmtpMailAdapterBuilder.create().withSecret(this.adapter.secret).withFrom(this.from).build();
480
- case "postmark":
481
- return PostmarkMailAdapterBuilder.create().withSecret(this.adapter.secret).withFrom(this.from).build();
482
- case "sendgrid":
483
- return SendGridMailAdapterBuilder.create().withSecret(this.adapter.secret).withFrom(this.from).build();
484
- case "webhook":
485
- return WebhookMailAdapterBuilder.create().withUrl(this.adapter.secret).withFrom(this.from).build();
486
- default:
487
- throw new IgniterMailError({
488
- code: "MAIL_PROVIDER_ADAPTER_NOT_FOUND",
489
- message: `MAIL_PROVIDER_ADAPTER_NOT_FOUND: ${this.adapter.provider}`,
490
- logger: this.logger,
491
- metadata: {
492
- provider: this.adapter.provider
493
- }
494
- });
495
- }
496
- })();
497
- return this.factory({
498
- from: this.from,
499
- adapter: resolvedAdapter,
500
- templates: this.templates,
501
- onSendStarted: this.onSendStarted,
502
- onSendError: this.onSendError,
503
- onSendSuccess: this.onSendSuccess,
504
- logger: this.logger,
505
- queue: this.queue ? {
506
- adapter: this.queue.adapter,
507
- id: `${this.queue.options?.namespace ?? "mail"}.${this.queue.options?.task ?? "send"}`,
508
- options: this.queue.options
509
- } : void 0
510
- });
380
+ return result?.value ?? input;
511
381
  }
512
- };
513
-
514
- // src/builders/mail-template.builder.ts
515
- var MailTemplateBuilder = class _MailTemplateBuilder {
516
- /** Creates a new builder instance. */
517
- static create() {
518
- return new _MailTemplateBuilder();
519
- }
520
- /** Sets the default subject for the template. */
521
- withSubject(subject) {
522
- this.subject = subject;
523
- return this;
524
- }
525
- /** Attaches the schema used to validate and infer payload types. */
526
- withSchema(schema) {
527
- this.schema = schema;
528
- return this;
529
- }
530
- /** Sets the React Email render function for the template. */
531
- withRender(render2) {
532
- this.render = render2;
533
- return this;
534
- }
535
- /** Builds the template definition. */
536
- build() {
537
- if (!this.subject) {
538
- throw new IgniterMailError({
539
- code: "MAIL_TEMPLATE_CONFIGURATION_INVALID",
540
- message: "Mail template subject is required"
541
- });
542
- }
543
- if (!this.schema) {
544
- throw new IgniterMailError({
545
- code: "MAIL_TEMPLATE_CONFIGURATION_INVALID",
546
- message: "Mail template schema is required"
547
- });
548
- }
549
- if (!this.render) {
550
- throw new IgniterMailError({
551
- code: "MAIL_TEMPLATE_CONFIGURATION_INVALID",
552
- message: "Mail template render is required"
553
- });
554
- }
382
+ /**
383
+ * Creates a passthrough StandardSchema validator.
384
+ */
385
+ static createPassthroughSchema() {
555
386
  return {
556
- subject: this.subject,
557
- schema: this.schema,
558
- render: this.render
387
+ "~standard": {
388
+ vendor: "@igniter-js/mail",
389
+ version: 1,
390
+ validate: async (value) => ({ value })
391
+ }
559
392
  };
560
393
  }
561
394
  };
562
395
 
563
- // src/utils/validate-standard-schema-input.ts
564
- async function validateStandardSchemaInput(schema, input) {
565
- const standard = schema?.["~standard"];
566
- if (!standard?.validate) {
567
- return input;
568
- }
569
- const result = await standard.validate(input);
570
- if (result?.issues?.length) {
571
- throw new IgniterMailError({
572
- code: "MAIL_PROVIDER_TEMPLATE_DATA_INVALID",
573
- message: "Invalid mail template payload",
574
- statusCode: 400,
575
- details: result.issues
576
- });
577
- }
578
- return result?.value ?? input;
579
- }
580
-
581
- // src/core/igniter-mail.tsx
582
- var _IgniterMail = class _IgniterMail {
396
+ // src/core/manager.tsx
397
+ var IgniterMailManagerCore = class {
583
398
  constructor(options) {
584
399
  this.queueJobRegistered = false;
585
400
  /**
586
401
  * Type inference helper.
587
402
  * Access via `typeof mail.$Infer` (type-level only).
588
403
  */
589
- this.$Infer = void 0;
590
- const { adapter, templates, logger, queue, ...rest } = options;
404
+ this.$Infer = {};
405
+ const { adapter, templates, logger, telemetry, queue, ...rest } = options;
591
406
  if (!adapter) {
592
407
  throw new IgniterMailError({
593
408
  code: "MAIL_PROVIDER_ADAPTER_REQUIRED",
@@ -605,6 +420,7 @@ var _IgniterMail = class _IgniterMail {
605
420
  this.adapter = adapter;
606
421
  this.templates = templates;
607
422
  this.logger = logger;
423
+ this.telemetry = telemetry;
608
424
  this.queue = queue;
609
425
  this.options = rest;
610
426
  }
@@ -618,30 +434,20 @@ var _IgniterMail = class _IgniterMail {
618
434
  }
619
435
  this.queueJobRegistering = (async () => {
620
436
  const queueOptions = queue.options;
621
- const name = queueOptions?.name ?? "send";
622
- const passthroughSchema = {
623
- "~standard": {
624
- vendor: "@igniter-js/mail",
625
- version: 1,
626
- validate: async (value) => ({ value })
627
- }
628
- };
629
- const definition = queue.adapter.register({
630
- name,
437
+ const passthroughSchema = IgniterMailSchema.createPassthroughSchema();
438
+ queue.adapter.register({
439
+ name: queueOptions?.job ?? "send",
631
440
  input: passthroughSchema,
632
- handler: async ({ input }) => {
633
- await this.send(input);
634
- },
635
- queue: queueOptions?.queue,
636
441
  attempts: queueOptions?.attempts,
637
442
  priority: queueOptions?.priority,
638
443
  removeOnComplete: queueOptions?.removeOnComplete,
639
444
  removeOnFail: queueOptions?.removeOnFail,
640
445
  metadata: queueOptions?.metadata,
641
- limiter: queueOptions?.limiter
642
- });
643
- await queue.adapter.bulkRegister({
644
- [queue.id]: definition
446
+ limiter: queueOptions?.limiter,
447
+ queue: { name: queueOptions?.queue ?? "mail" },
448
+ handler: async ({ input }) => {
449
+ await this.send(input);
450
+ }
645
451
  });
646
452
  this.queueJobRegistered = true;
647
453
  })();
@@ -653,7 +459,7 @@ var _IgniterMail = class _IgniterMail {
653
459
  }
654
460
  async validateTemplateData(template, data) {
655
461
  try {
656
- return await validateStandardSchemaInput(
462
+ return await IgniterMailSchema.validateInput(
657
463
  template.schema,
658
464
  data
659
465
  );
@@ -672,11 +478,20 @@ var _IgniterMail = class _IgniterMail {
672
478
  * Sends an email immediately.
673
479
  */
674
480
  async send(params) {
481
+ const startTime = Date.now();
675
482
  try {
676
483
  this.logger?.debug("IgniterMail.send started", {
677
484
  to: params.to,
678
485
  template: String(params.template)
679
486
  });
487
+ this.telemetry?.emit(IGNITER_MAIL_TELEMETRY_EVENTS.SEND_STARTED, {
488
+ level: "debug",
489
+ attributes: {
490
+ "mail.to": params.to,
491
+ "mail.template": String(params.template),
492
+ "mail.subject": params.subject
493
+ }
494
+ });
680
495
  await this.onSendStarted(params);
681
496
  const template = this.templates[params.template];
682
497
  if (!template) {
@@ -705,9 +520,20 @@ var _IgniterMail = class _IgniterMail {
705
520
  text
706
521
  });
707
522
  await this.onSendSuccess(params);
523
+ const durationMs = Date.now() - startTime;
524
+ this.telemetry?.emit(IGNITER_MAIL_TELEMETRY_EVENTS.SEND_SUCCESS, {
525
+ level: "info",
526
+ attributes: {
527
+ "mail.to": params.to,
528
+ "mail.template": String(params.template),
529
+ "mail.subject": params.subject || template.subject,
530
+ "mail.duration_ms": durationMs
531
+ }
532
+ });
708
533
  this.logger?.info("IgniterMail.send success", {
709
534
  to: params.to,
710
- template: String(params.template)
535
+ template: String(params.template),
536
+ durationMs
711
537
  });
712
538
  } catch (error) {
713
539
  const normalizedError = IgniterMailError.is(error) ? error : new IgniterMailError({
@@ -720,6 +546,18 @@ var _IgniterMail = class _IgniterMail {
720
546
  template: String(params.template)
721
547
  }
722
548
  });
549
+ const durationMs = Date.now() - startTime;
550
+ this.telemetry?.emit(IGNITER_MAIL_TELEMETRY_EVENTS.SEND_ERROR, {
551
+ level: "error",
552
+ attributes: {
553
+ "mail.to": params.to,
554
+ "mail.template": String(params.template),
555
+ "mail.subject": params.subject,
556
+ "mail.error.code": normalizedError.code,
557
+ "mail.error.message": normalizedError.message,
558
+ "mail.duration_ms": durationMs
559
+ }
560
+ });
723
561
  this.logger?.error("IgniterMail.send failed", normalizedError);
724
562
  await this.onSendError(params, normalizedError);
725
563
  throw normalizedError;
@@ -728,10 +566,10 @@ var _IgniterMail = class _IgniterMail {
728
566
  /**
729
567
  * Schedules an email for a future date.
730
568
  *
731
- * If a queue is configured, this method enqueues a job.
732
- * Otherwise, it uses a best-effort `setTimeout`.
569
+ * Requires a queue adapter; otherwise it throws.
733
570
  */
734
571
  async schedule(params, date) {
572
+ const startTime = Date.now();
735
573
  if (date.getTime() <= Date.now()) {
736
574
  throw new IgniterMailError({
737
575
  code: "MAIL_PROVIDER_SCHEDULE_DATE_INVALID",
@@ -739,24 +577,60 @@ var _IgniterMail = class _IgniterMail {
739
577
  logger: this.logger
740
578
  });
741
579
  }
742
- if (this.queue) {
743
- try {
744
- await this.ensureQueueJobRegistered();
745
- const delay = Math.max(0, date.getTime() - Date.now());
746
- this.logger?.info("IgniterMail.schedule enqueued", {
747
- id: this.queue.id,
748
- to: params.to,
749
- template: String(params.template),
750
- delay
751
- });
752
- await this.queue.adapter.invoke({
753
- id: this.queue.id,
754
- input: params,
755
- delay
756
- });
757
- return;
758
- } catch (error) {
759
- const normalizedError = IgniterMailError.is(error) ? error : new IgniterMailError({
580
+ const delay = Math.max(0, date.getTime() - Date.now());
581
+ this.logger?.debug("IgniterMail.schedule started", {
582
+ to: params.to,
583
+ template: String(params.template),
584
+ scheduledAt: date.toISOString(),
585
+ delayMs: delay
586
+ });
587
+ this.telemetry?.emit(IGNITER_MAIL_TELEMETRY_EVENTS.SCHEDULE_STARTED, {
588
+ level: "debug",
589
+ attributes: {
590
+ "mail.to": params.to,
591
+ "mail.template": String(params.template),
592
+ "mail.scheduled_at": date.toISOString(),
593
+ "mail.delay_ms": delay
594
+ }
595
+ });
596
+ if (!this.queue) {
597
+ throw new IgniterMailError({
598
+ code: "MAIL_PROVIDER_SCHEDULE_QUEUE_NOT_CONFIGURED",
599
+ message: "MAIL_PROVIDER_SCHEDULE_QUEUE_NOT_CONFIGURED",
600
+ logger: this.logger
601
+ });
602
+ }
603
+ try {
604
+ await this.ensureQueueJobRegistered();
605
+ const queue = this.queue.options?.queue ?? "mail";
606
+ const job = this.queue.options?.job ?? "send";
607
+ const id = `${queue}.${job}`;
608
+ this.logger?.info("IgniterMail.schedule enqueued", {
609
+ to: params.to,
610
+ template: String(params.template),
611
+ delay,
612
+ durationMs: Date.now() - startTime
613
+ });
614
+ await this.queue.adapter.invoke({
615
+ id,
616
+ input: params,
617
+ delay
618
+ });
619
+ this.telemetry?.emit(IGNITER_MAIL_TELEMETRY_EVENTS.SCHEDULE_SUCCESS, {
620
+ level: "info",
621
+ attributes: {
622
+ "mail.to": params.to,
623
+ "mail.template": String(params.template),
624
+ "mail.scheduled_at": date.toISOString(),
625
+ "mail.delay_ms": delay,
626
+ "mail.queue_id": this.queue.options?.queue ?? "mail"
627
+ }
628
+ });
629
+ return;
630
+ } catch (error) {
631
+ let normalizedError = error;
632
+ if (!IgniterMailError.is(error)) {
633
+ normalizedError = new IgniterMailError({
760
634
  code: "MAIL_PROVIDER_SCHEDULE_FAILED",
761
635
  message: "MAIL_PROVIDER_SCHEDULE_FAILED",
762
636
  cause: error,
@@ -764,19 +638,23 @@ var _IgniterMail = class _IgniterMail {
764
638
  metadata: {
765
639
  to: params.to,
766
640
  template: String(params.template),
767
- date: date.toISOString()
641
+ scheduledAt: date.toISOString()
768
642
  }
769
643
  });
770
- this.logger?.error("IgniterMail.schedule failed", normalizedError);
771
- throw normalizedError;
772
644
  }
773
- }
774
- const timeout = date.getTime() - Date.now();
775
- setTimeout(() => {
776
- this.send(params).catch((error) => {
777
- console.error("Failed to send scheduled email:", error);
645
+ this.telemetry?.emit(IGNITER_MAIL_TELEMETRY_EVENTS.SCHEDULE_ERROR, {
646
+ level: "error",
647
+ attributes: {
648
+ "mail.to": params.to,
649
+ "mail.template": String(params.template),
650
+ "mail.scheduled_at": date.toISOString(),
651
+ "mail.error.code": normalizedError.code,
652
+ "mail.error.message": normalizedError.message
653
+ }
778
654
  });
779
- }, timeout);
655
+ this.logger?.error("IgniterMail.schedule failed", normalizedError);
656
+ throw normalizedError;
657
+ }
780
658
  }
781
659
  async onSendStarted(params) {
782
660
  await this.options.onSendStarted?.(params);
@@ -788,93 +666,233 @@ var _IgniterMail = class _IgniterMail {
788
666
  await this.options.onSendSuccess?.(params);
789
667
  }
790
668
  };
791
- /** Helper to declare adapter factories. */
792
- _IgniterMail.adapter = (adapter) => adapter;
793
- /** Helper to declare templates with inferred payload types. */
794
- _IgniterMail.template = (template) => template;
795
- /**
796
- * Creates a new builder instance.
797
- */
798
- _IgniterMail.create = () => IgniterMailBuilder.create((options) => new _IgniterMail(options));
799
- /**
800
- * Initializes (singleton) instance.
801
- *
802
- * Prefer using {@link IgniterMail.create} for new code.
803
- */
804
- _IgniterMail.initialize = (options) => {
805
- if (_IgniterMail.instance) {
806
- return _IgniterMail.instance;
807
- }
808
- const adapter = options.adapter;
809
- if (typeof adapter === "function") {
810
- const legacyOptions = options;
811
- _IgniterMail.instance = new _IgniterMail({
812
- from: legacyOptions.from,
813
- templates: legacyOptions.templates,
814
- adapter: legacyOptions.adapter(legacyOptions),
815
- onSendStarted: legacyOptions.onSendStarted,
816
- onSendError: legacyOptions.onSendError,
817
- onSendSuccess: legacyOptions.onSendSuccess
669
+
670
+ // src/builders/main.builder.ts
671
+ var IgniterMailBuilder = class _IgniterMailBuilder {
672
+ constructor(options) {
673
+ this.templates = {};
674
+ this.from = options.from;
675
+ this.adapter = options.adapter;
676
+ this.templates = options.templates;
677
+ this.logger = options.logger;
678
+ this.telemetry = options.telemetry;
679
+ this.onSendStartedHandler = options.onSendStarted;
680
+ this.onSendErrorHandler = options.onSendError;
681
+ this.onSendSuccessHandler = options.onSendSuccess;
682
+ if (options.queue) {
683
+ this.queue = {
684
+ adapter: options.queue.adapter,
685
+ options: options.queue.options
686
+ };
687
+ }
688
+ }
689
+ /**
690
+ * Creates a new builder.
691
+ */
692
+ static create() {
693
+ return new _IgniterMailBuilder({ from: "", adapter: {}, templates: {} });
694
+ }
695
+ /** Sets the default FROM address. */
696
+ withFrom(from) {
697
+ this.from = from;
698
+ return this;
699
+ }
700
+ /** Attaches a logger instance. */
701
+ withLogger(logger) {
702
+ this.logger = logger;
703
+ return this;
704
+ }
705
+ /** Attaches a telemetry instance for observability. */
706
+ withTelemetry(telemetry) {
707
+ this.telemetry = telemetry;
708
+ return this;
709
+ }
710
+ /**
711
+ * Enables queue delivery.
712
+ *
713
+ * When configured, `IgniterMail.schedule()` will enqueue jobs using the queue adapter.
714
+ */
715
+ withQueue(adapter, options) {
716
+ this.queue = { adapter, options };
717
+ return this;
718
+ }
719
+ withAdapter(adapterOrProvider, secret) {
720
+ if (typeof adapterOrProvider === "string") {
721
+ if (!secret) {
722
+ throw new IgniterMailError({
723
+ code: "MAIL_PROVIDER_ADAPTER_SECRET_REQUIRED",
724
+ message: "MAIL_PROVIDER_ADAPTER_SECRET_REQUIRED",
725
+ logger: this.logger
726
+ });
727
+ }
728
+ switch (adapterOrProvider) {
729
+ case "resend":
730
+ this.adapter = ResendMailAdapter.create({
731
+ secret,
732
+ from: this.from
733
+ });
734
+ return this;
735
+ case "smtp":
736
+ this.adapter = SmtpMailAdapter.create({
737
+ secret,
738
+ from: this.from
739
+ });
740
+ return this;
741
+ case "postmark":
742
+ this.adapter = PostmarkMailAdapter.create({
743
+ secret,
744
+ from: this.from
745
+ });
746
+ return this;
747
+ case "sendgrid":
748
+ this.adapter = SendGridMailAdapter.create({
749
+ secret,
750
+ from: this.from
751
+ });
752
+ return this;
753
+ default:
754
+ throw new IgniterMailError({
755
+ code: "MAIL_PROVIDER_ADAPTER_NOT_FOUND",
756
+ message: `MAIL_PROVIDER_ADAPTER_NOT_FOUND: ${adapterOrProvider}`,
757
+ logger: this.logger,
758
+ metadata: {
759
+ provider: adapterOrProvider
760
+ }
761
+ });
762
+ }
763
+ }
764
+ this.adapter = adapterOrProvider;
765
+ return this;
766
+ }
767
+ /**
768
+ * Registers a template.
769
+ */
770
+ addTemplate(key, template) {
771
+ return new _IgniterMailBuilder({
772
+ from: this.from,
773
+ adapter: this.adapter,
774
+ templates: {
775
+ ...this.templates,
776
+ [key]: template
777
+ },
778
+ logger: this.logger,
779
+ telemetry: this.telemetry,
780
+ onSendStarted: this.onSendStartedHandler,
781
+ onSendError: this.onSendErrorHandler,
782
+ onSendSuccess: this.onSendSuccessHandler,
783
+ queue: this.queue ? {
784
+ adapter: this.queue.adapter,
785
+ options: this.queue.options
786
+ } : void 0
787
+ });
788
+ }
789
+ /** Hook invoked before sending. */
790
+ onSendStarted(handler) {
791
+ this.onSendStartedHandler = handler;
792
+ return this;
793
+ }
794
+ /** Hook invoked on error. */
795
+ onSendError(handler) {
796
+ this.onSendErrorHandler = handler;
797
+ return this;
798
+ }
799
+ /** Hook invoked on success. */
800
+ onSendSuccess(handler) {
801
+ this.onSendSuccessHandler = handler;
802
+ return this;
803
+ }
804
+ /**
805
+ * Builds the {@link IgniterMail} instance.
806
+ */
807
+ build() {
808
+ if (!this.from) {
809
+ throw new IgniterMailError({
810
+ code: "MAIL_PROVIDER_FROM_REQUIRED",
811
+ message: "MAIL_PROVIDER_FROM_REQUIRED",
812
+ logger: this.logger
813
+ });
814
+ }
815
+ if (!this.adapter) {
816
+ throw new IgniterMailError({
817
+ code: "MAIL_PROVIDER_ADAPTER_REQUIRED",
818
+ message: "MAIL_PROVIDER_ADAPTER_REQUIRED",
819
+ logger: this.logger
820
+ });
821
+ }
822
+ return new IgniterMailManagerCore({
823
+ from: this.from,
824
+ adapter: this.adapter,
825
+ templates: this.templates,
826
+ onSendStarted: this.onSendStartedHandler,
827
+ onSendError: this.onSendErrorHandler,
828
+ onSendSuccess: this.onSendSuccessHandler,
829
+ telemetry: this.telemetry,
830
+ logger: this.logger,
831
+ queue: this.queue ? {
832
+ adapter: this.queue.adapter,
833
+ options: this.queue.options
834
+ } : void 0
818
835
  });
819
- return _IgniterMail.instance;
820
836
  }
821
- _IgniterMail.instance = new _IgniterMail(
822
- options
823
- );
824
- return _IgniterMail.instance;
825
837
  };
826
- var IgniterMail = _IgniterMail;
838
+ var IgniterMail = IgniterMailBuilder;
827
839
 
828
- // src/types/provider.ts
829
- function createPassthroughSchema() {
830
- return {
831
- "~standard": {
832
- vendor: "@igniter-js/mail",
833
- version: 1,
834
- validate: async (value) => ({ value })
840
+ // src/builders/template.builder.ts
841
+ var IgniterMailTemplateBuilder = class _IgniterMailTemplateBuilder {
842
+ /** Creates a new builder instance. */
843
+ static create() {
844
+ return new _IgniterMailTemplateBuilder();
845
+ }
846
+ /** Sets the default subject for the template. */
847
+ withSubject(subject) {
848
+ this.subject = subject;
849
+ return this;
850
+ }
851
+ /** Attaches the schema used to validate and infer payload types. */
852
+ withSchema(schema) {
853
+ this.schema = schema;
854
+ return this;
855
+ }
856
+ /** Sets the React Email render function for the template. */
857
+ withRender(render2) {
858
+ this.render = render2;
859
+ return this;
860
+ }
861
+ /** Builds the template definition. */
862
+ build() {
863
+ if (!this.subject) {
864
+ throw new IgniterMailError({
865
+ code: "MAIL_TEMPLATE_CONFIGURATION_INVALID",
866
+ message: "Mail template subject is required"
867
+ });
835
868
  }
836
- };
837
- }
838
-
839
- // src/utils/get-adapter.ts
840
- var getAdapter = (adapter) => {
841
- switch (adapter) {
842
- case "resend":
843
- return resendAdapter;
844
- case "smtp":
845
- return smtpAdapter;
846
- case "postmark":
847
- return postmarkAdapter;
848
- case "sendgrid":
849
- return sendgridAdapter;
850
- case "webhook":
851
- return webhookAdapter;
852
- default:
869
+ if (!this.schema) {
853
870
  throw new IgniterMailError({
854
- code: "MAIL_PROVIDER_ADAPTER_NOT_FOUND",
855
- message: `MAIL_PROVIDER_ADAPTER_NOT_FOUND: ${adapter}`,
856
- metadata: { adapter }
871
+ code: "MAIL_TEMPLATE_CONFIGURATION_INVALID",
872
+ message: "Mail template schema is required"
857
873
  });
874
+ }
875
+ if (!this.render) {
876
+ throw new IgniterMailError({
877
+ code: "MAIL_TEMPLATE_CONFIGURATION_INVALID",
878
+ message: "Mail template render is required"
879
+ });
880
+ }
881
+ return {
882
+ subject: this.subject,
883
+ schema: this.schema,
884
+ render: this.render
885
+ };
858
886
  }
859
887
  };
888
+ var IgniterMailTemplate = IgniterMailTemplateBuilder;
860
889
 
861
890
  exports.IgniterMail = IgniterMail;
862
891
  exports.IgniterMailBuilder = IgniterMailBuilder;
863
892
  exports.IgniterMailError = IgniterMailError;
864
- exports.MailTemplateBuilder = MailTemplateBuilder;
865
- exports.PostmarkMailAdapterBuilder = PostmarkMailAdapterBuilder;
866
- exports.ResendMailAdapterBuilder = ResendMailAdapterBuilder;
867
- exports.SendGridMailAdapterBuilder = SendGridMailAdapterBuilder;
868
- exports.SmtpMailAdapterBuilder = SmtpMailAdapterBuilder;
869
- exports.WebhookMailAdapterBuilder = WebhookMailAdapterBuilder;
870
- exports.createPassthroughSchema = createPassthroughSchema;
871
- exports.createTestMailAdapter = createTestMailAdapter;
872
- exports.getAdapter = getAdapter;
873
- exports.postmarkAdapter = postmarkAdapter;
874
- exports.resendAdapter = resendAdapter;
875
- exports.sendgridAdapter = sendgridAdapter;
876
- exports.smtpAdapter = smtpAdapter;
877
- exports.validateStandardSchemaInput = validateStandardSchemaInput;
878
- exports.webhookAdapter = webhookAdapter;
893
+ exports.IgniterMailManagerCore = IgniterMailManagerCore;
894
+ exports.IgniterMailSchema = IgniterMailSchema;
895
+ exports.IgniterMailTemplate = IgniterMailTemplate;
896
+ exports.IgniterMailTemplateBuilder = IgniterMailTemplateBuilder;
879
897
  //# sourceMappingURL=index.js.map
880
898
  //# sourceMappingURL=index.js.map