@superdangerous/app-framework 4.9.2 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +8 -2
  2. package/dist/api/logsRouter.d.ts +4 -1
  3. package/dist/api/logsRouter.d.ts.map +1 -1
  4. package/dist/api/logsRouter.js +100 -118
  5. package/dist/api/logsRouter.js.map +1 -1
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/middleware/validation.d.ts +48 -43
  11. package/dist/middleware/validation.d.ts.map +1 -1
  12. package/dist/middleware/validation.js +48 -43
  13. package/dist/middleware/validation.js.map +1 -1
  14. package/dist/services/emailService.d.ts +146 -0
  15. package/dist/services/emailService.d.ts.map +1 -0
  16. package/dist/services/emailService.js +649 -0
  17. package/dist/services/emailService.js.map +1 -0
  18. package/dist/services/index.d.ts +2 -0
  19. package/dist/services/index.d.ts.map +1 -1
  20. package/dist/services/index.js +2 -0
  21. package/dist/services/index.js.map +1 -1
  22. package/dist/services/websocketServer.d.ts +7 -4
  23. package/dist/services/websocketServer.d.ts.map +1 -1
  24. package/dist/services/websocketServer.js +22 -16
  25. package/dist/services/websocketServer.js.map +1 -1
  26. package/dist/types/index.d.ts +7 -8
  27. package/dist/types/index.d.ts.map +1 -1
  28. package/package.json +11 -2
  29. package/src/api/logsRouter.ts +119 -138
  30. package/src/index.ts +14 -0
  31. package/src/middleware/validation.ts +82 -90
  32. package/src/services/emailService.ts +812 -0
  33. package/src/services/index.ts +14 -0
  34. package/src/services/websocketServer.ts +37 -23
  35. package/src/types/index.ts +7 -8
  36. package/ui/data-table/components/BatchActionsBar.tsx +53 -0
  37. package/ui/data-table/components/ColumnVisibility.tsx +111 -0
  38. package/ui/data-table/components/DataTablePage.tsx +238 -0
  39. package/ui/data-table/components/Pagination.tsx +203 -0
  40. package/ui/data-table/components/PaginationControls.tsx +122 -0
  41. package/ui/data-table/components/TableFilters.tsx +139 -0
  42. package/ui/data-table/components/index.ts +27 -0
  43. package/ui/data-table/hooks/index.ts +17 -0
  44. package/ui/data-table/hooks/useColumnOrder.ts +233 -0
  45. package/ui/data-table/hooks/useColumnVisibility.ts +128 -0
  46. package/ui/data-table/hooks/usePagination.ts +160 -0
  47. package/ui/data-table/hooks/useResizableColumns.ts +280 -0
  48. package/ui/data-table/index.ts +74 -0
  49. package/ui/dist/index.d.mts +207 -5
  50. package/ui/dist/index.d.ts +207 -5
  51. package/ui/dist/index.js +36 -43
  52. package/ui/dist/index.js.map +1 -1
  53. package/ui/dist/index.mjs +36 -43
  54. package/ui/dist/index.mjs.map +1 -1
@@ -0,0 +1,649 @@
1
+ /**
2
+ * Email Service supporting Resend API and Nodemailer SMTP
3
+ * A generic, reusable email service for the app framework.
4
+ * Resend is preferred when API key is configured.
5
+ */
6
+ import { EventEmitter } from "events";
7
+ import nodemailer from "nodemailer";
8
+ import { Resend } from "resend";
9
+ import { createLogger } from "../core/index.js";
10
+ let logger;
11
+ function ensureLogger() {
12
+ if (!logger) {
13
+ logger = createLogger("EmailService");
14
+ }
15
+ return logger;
16
+ }
17
+ // ============================================================================
18
+ // Email Service
19
+ // ============================================================================
20
+ export class EmailService extends EventEmitter {
21
+ transporter;
22
+ resend;
23
+ enabled = false;
24
+ useResend = false;
25
+ notificationQueue = [];
26
+ processingInterval;
27
+ fromAddress = "App <noreply@example.com>";
28
+ defaultRecipients = [];
29
+ config;
30
+ // Branding configuration
31
+ appName = "App";
32
+ appTitle = "App";
33
+ logoUrl;
34
+ brandColor = "#6c5ce7";
35
+ footerText;
36
+ footerLink;
37
+ constructor(config = {}) {
38
+ super();
39
+ this.config = config;
40
+ this.enabled = config.enabled ?? false;
41
+ this.defaultRecipients = config.to || [];
42
+ this.fromAddress = config.from || this.fromAddress;
43
+ this.appName = config.appName || this.appName;
44
+ this.appTitle = config.appTitle || config.appName || this.appTitle;
45
+ this.logoUrl = config.logoUrl;
46
+ this.brandColor = config.brandColor || this.brandColor;
47
+ this.footerText = config.footerText;
48
+ this.footerLink = config.footerLink;
49
+ ensureLogger().debug("EmailService created", {
50
+ enabled: this.enabled,
51
+ provider: config.provider,
52
+ });
53
+ }
54
+ /**
55
+ * Initialize the email service
56
+ */
57
+ async initialize() {
58
+ if (!this.enabled) {
59
+ ensureLogger().info("Email service disabled in configuration");
60
+ return;
61
+ }
62
+ // Try Resend first (preferred)
63
+ const resendApiKey = this.config.resend?.apiKey || process.env.RESEND_API_KEY;
64
+ if (resendApiKey) {
65
+ try {
66
+ this.resend = new Resend(resendApiKey);
67
+ this.useResend = true;
68
+ ensureLogger().info("Email service initialized with Resend API");
69
+ this.startNotificationProcessor();
70
+ this.emit("initialized", { provider: "Resend" });
71
+ return;
72
+ }
73
+ catch (error) {
74
+ ensureLogger().warn("Failed to initialize Resend, falling back to SMTP:", error);
75
+ }
76
+ }
77
+ // Fall back to SMTP/Nodemailer
78
+ if (!this.config.smtp) {
79
+ ensureLogger().warn("No email provider configured (no Resend API key or SMTP config)");
80
+ this.enabled = false;
81
+ return;
82
+ }
83
+ try {
84
+ this.transporter = nodemailer.createTransport({
85
+ host: this.config.smtp.host,
86
+ port: this.config.smtp.port,
87
+ secure: this.config.smtp.secure,
88
+ auth: this.config.smtp.auth
89
+ ? {
90
+ user: this.config.smtp.auth.user,
91
+ pass: this.config.smtp.auth.pass,
92
+ }
93
+ : undefined,
94
+ });
95
+ await this.transporter.verify();
96
+ ensureLogger().info("Email service initialized with SMTP");
97
+ this.startNotificationProcessor();
98
+ this.emit("initialized", { provider: "SMTP" });
99
+ }
100
+ catch (error) {
101
+ ensureLogger().error("Failed to initialize email service:", error);
102
+ this.enabled = false;
103
+ }
104
+ }
105
+ /**
106
+ * Update branding configuration
107
+ */
108
+ setBranding(options) {
109
+ if (options.appName)
110
+ this.appName = options.appName;
111
+ if (options.appTitle)
112
+ this.appTitle = options.appTitle;
113
+ if (options.logoUrl)
114
+ this.logoUrl = options.logoUrl;
115
+ if (options.brandColor)
116
+ this.brandColor = options.brandColor;
117
+ if (options.footerText)
118
+ this.footerText = options.footerText;
119
+ if (options.footerLink)
120
+ this.footerLink = options.footerLink;
121
+ }
122
+ /**
123
+ * Send an email
124
+ */
125
+ async sendEmail(options) {
126
+ if (!this.enabled) {
127
+ ensureLogger().debug("Email service not available, skipping email");
128
+ return;
129
+ }
130
+ const recipients = Array.isArray(options.to) ? options.to : [options.to];
131
+ const toAddresses = recipients.length > 0 ? recipients : this.defaultRecipients;
132
+ if (toAddresses.length === 0) {
133
+ ensureLogger().warn("No email recipients configured");
134
+ return;
135
+ }
136
+ try {
137
+ if (this.useResend && this.resend) {
138
+ const { data, error } = await this.resend.emails.send({
139
+ from: this.fromAddress,
140
+ to: toAddresses,
141
+ subject: options.subject,
142
+ text: options.text || "No content",
143
+ html: options.html,
144
+ });
145
+ if (error) {
146
+ throw new Error(error.message);
147
+ }
148
+ ensureLogger().info(`Email sent via Resend: ${data?.id}`);
149
+ this.emit("sent", { id: data?.id, provider: "Resend" });
150
+ }
151
+ else if (this.transporter) {
152
+ const info = await this.transporter.sendMail({
153
+ from: this.fromAddress,
154
+ to: toAddresses.join(", "),
155
+ subject: options.subject,
156
+ text: options.text,
157
+ html: options.html,
158
+ attachments: options.attachments,
159
+ });
160
+ ensureLogger().info(`Email sent via SMTP: ${info.messageId}`);
161
+ this.emit("sent", { id: info.messageId, provider: "SMTP" });
162
+ }
163
+ }
164
+ catch (error) {
165
+ ensureLogger().error("Failed to send email:", error);
166
+ this.emit("error", error);
167
+ throw error;
168
+ }
169
+ }
170
+ /**
171
+ * Queue a notification event
172
+ */
173
+ queueNotification(event) {
174
+ if (!this.enabled) {
175
+ return;
176
+ }
177
+ this.notificationQueue.push(event);
178
+ ensureLogger().debug(`Queued ${event.type} notification`);
179
+ this.emit("queued", event);
180
+ }
181
+ /**
182
+ * Send immediate notification (bypasses queue)
183
+ */
184
+ async sendImmediateNotification(event) {
185
+ if (!this.enabled) {
186
+ return;
187
+ }
188
+ try {
189
+ await this.sendNotificationEmail(event.type, [event]);
190
+ ensureLogger().info(`Sent immediate ${event.type} notification`);
191
+ }
192
+ catch (error) {
193
+ ensureLogger().error(`Failed to send immediate ${event.type} notification:`, error);
194
+ }
195
+ }
196
+ /**
197
+ * Send a notification with custom type and data
198
+ */
199
+ async notify(type, title, data, immediate = true) {
200
+ const event = {
201
+ type,
202
+ title,
203
+ data,
204
+ timestamp: new Date(),
205
+ };
206
+ if (immediate) {
207
+ await this.sendImmediateNotification(event);
208
+ }
209
+ else {
210
+ this.queueNotification(event);
211
+ }
212
+ }
213
+ /**
214
+ * Send startup notification
215
+ */
216
+ async notifyStartup(data = {}) {
217
+ const uptime = process.uptime();
218
+ const nodeVersion = process.version;
219
+ const platform = process.platform;
220
+ await this.sendImmediateNotification({
221
+ type: "startup",
222
+ title: "Application Started",
223
+ data: {
224
+ nodeVersion,
225
+ platform,
226
+ startupTime: `${uptime.toFixed(2)}s`,
227
+ timestamp: new Date().toISOString(),
228
+ ...data,
229
+ },
230
+ timestamp: new Date(),
231
+ });
232
+ }
233
+ /**
234
+ * Send error notification
235
+ */
236
+ async notifyError(errorMessage, details) {
237
+ await this.sendImmediateNotification({
238
+ type: "error",
239
+ title: "Error Alert",
240
+ data: {
241
+ errorMessage,
242
+ ...details,
243
+ },
244
+ timestamp: new Date(),
245
+ });
246
+ }
247
+ /**
248
+ * Send test email
249
+ */
250
+ async sendTestEmail() {
251
+ const provider = this.useResend ? "Resend API" : "SMTP";
252
+ await this.sendEmail({
253
+ to: this.defaultRecipients,
254
+ subject: `[${this.appTitle}] Test Email - Configuration Verified`,
255
+ text: `This is a test email from ${this.appTitle}.\n\nEmail Provider: ${provider}\n\nIf you received this email, your email configuration is working correctly.`,
256
+ html: this.generateTestEmailHtml(provider),
257
+ });
258
+ }
259
+ /**
260
+ * Get service status
261
+ */
262
+ getStatus() {
263
+ return {
264
+ enabled: this.enabled,
265
+ provider: this.useResend ? "Resend" : this.transporter ? "SMTP" : "None",
266
+ recipients: this.defaultRecipients,
267
+ };
268
+ }
269
+ /**
270
+ * Shutdown the service
271
+ */
272
+ async shutdown() {
273
+ if (this.processingInterval) {
274
+ clearInterval(this.processingInterval);
275
+ }
276
+ if (this.notificationQueue.length > 0) {
277
+ await this.processNotificationQueue();
278
+ }
279
+ if (this.transporter) {
280
+ this.transporter.close();
281
+ }
282
+ ensureLogger().info("Email service shut down");
283
+ this.emit("shutdown");
284
+ }
285
+ // ============================================================================
286
+ // Private Methods
287
+ // ============================================================================
288
+ startNotificationProcessor() {
289
+ // Process queue every 5 minutes
290
+ this.processingInterval = setInterval(() => {
291
+ this.processNotificationQueue();
292
+ }, 300000);
293
+ }
294
+ async processNotificationQueue() {
295
+ if (this.notificationQueue.length === 0) {
296
+ return;
297
+ }
298
+ const grouped = this.groupNotificationsByType();
299
+ for (const [type, events] of Object.entries(grouped)) {
300
+ try {
301
+ await this.sendNotificationEmail(type, events);
302
+ }
303
+ catch (error) {
304
+ ensureLogger().error(`Failed to send ${type} notification:`, error);
305
+ }
306
+ }
307
+ this.notificationQueue = [];
308
+ }
309
+ groupNotificationsByType() {
310
+ const grouped = {};
311
+ for (const event of this.notificationQueue) {
312
+ if (!grouped[event.type]) {
313
+ grouped[event.type] = [];
314
+ }
315
+ grouped[event.type].push(event);
316
+ }
317
+ return grouped;
318
+ }
319
+ async sendNotificationEmail(type, events) {
320
+ const subject = this.getNotificationSubject(type, events);
321
+ const html = this.formatNotificationHtml(type, events);
322
+ const text = this.formatNotificationText(type, events);
323
+ await this.sendEmail({
324
+ to: this.defaultRecipients,
325
+ subject,
326
+ text,
327
+ html,
328
+ });
329
+ }
330
+ getNotificationSubject(type, events) {
331
+ const count = events.length;
332
+ const customTitle = events[0]?.title;
333
+ switch (type) {
334
+ case "startup":
335
+ return `[${this.appTitle}] Application Started`;
336
+ case "shutdown":
337
+ return `[${this.appTitle}] Application Shutdown`;
338
+ case "error":
339
+ return `[${this.appTitle}] Error Alert${count > 1 ? ` (${count})` : ""}`;
340
+ case "warning":
341
+ return `[${this.appTitle}] Warning${count > 1 ? ` (${count})` : ""}`;
342
+ case "info":
343
+ return `[${this.appTitle}] Information`;
344
+ case "success":
345
+ return `[${this.appTitle}] Success`;
346
+ case "custom":
347
+ return customTitle
348
+ ? `[${this.appTitle}] ${customTitle}`
349
+ : `[${this.appTitle}] Notification`;
350
+ default:
351
+ return `[${this.appTitle}] Notification`;
352
+ }
353
+ }
354
+ getNotificationIcon(type) {
355
+ switch (type) {
356
+ case "startup":
357
+ return "🚀";
358
+ case "shutdown":
359
+ return "🛑";
360
+ case "error":
361
+ return "❌";
362
+ case "warning":
363
+ return "⚠️";
364
+ case "info":
365
+ return "ℹ️";
366
+ case "success":
367
+ return "✅";
368
+ case "custom":
369
+ return "📧";
370
+ default:
371
+ return "📧";
372
+ }
373
+ }
374
+ getAccentColor(type) {
375
+ switch (type) {
376
+ case "error":
377
+ return "#e74c3c";
378
+ case "warning":
379
+ return "#f39c12";
380
+ case "success":
381
+ return "#27ae60";
382
+ case "startup":
383
+ return "#3498db";
384
+ case "shutdown":
385
+ return "#95a5a6";
386
+ default:
387
+ return this.brandColor;
388
+ }
389
+ }
390
+ formatDateTime(date) {
391
+ const pad = (n) => n.toString().padStart(2, "0");
392
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
393
+ }
394
+ formatEventDataHtml(data) {
395
+ if (!data || typeof data !== "object") {
396
+ return `<tr><td colspan="2">${data || "No details"}</td></tr>`;
397
+ }
398
+ const formatValue = (val) => {
399
+ if (val instanceof Date)
400
+ return this.formatDateTime(val);
401
+ if (typeof val === "object")
402
+ return JSON.stringify(val);
403
+ return String(val ?? "-");
404
+ };
405
+ return Object.entries(data)
406
+ .map(([key, val]) => {
407
+ const label = key
408
+ .replace(/([A-Z])/g, " $1")
409
+ .replace(/^./, (s) => s.toUpperCase());
410
+ return `<tr><td style="font-weight:600;color:#495057;padding:4px 8px;">${label}:</td><td style="padding:4px 8px;">${formatValue(val)}</td></tr>`;
411
+ })
412
+ .join("");
413
+ }
414
+ formatNotificationHtml(type, events) {
415
+ const accentColor = this.getAccentColor(type);
416
+ const icon = this.getNotificationIcon(type);
417
+ const title = events[0]?.title || this.getNotificationTitle(type);
418
+ let html = `
419
+ <!DOCTYPE html>
420
+ <html>
421
+ <head>
422
+ <meta charset="utf-8">
423
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
424
+ <title>${this.getNotificationSubject(type, events)}</title>
425
+ </head>
426
+ <body style="margin: 0; padding: 0; background-color: #f6f9fc; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Ubuntu, sans-serif;">
427
+ <table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f6f9fc; padding: 40px 20px;">
428
+ <tr>
429
+ <td align="center">
430
+ <table width="100%" cellpadding="0" cellspacing="0" style="max-width: 600px; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);">
431
+
432
+ <!-- Header -->
433
+ <tr>
434
+ <td style="padding: 32px 40px 24px 40px; border-bottom: 1px solid #e9ecef;">
435
+ <table width="100%" cellpadding="0" cellspacing="0">
436
+ <tr>
437
+ <td>
438
+ ${this.logoUrl ? `<img src="${this.logoUrl}" alt="${this.appName}" width="150" style="display: block; border: 0;" />` : `<span style="font-size: 24px; font-weight: 700; color: ${this.brandColor};">${this.appName}</span>`}
439
+ </td>
440
+ <td align="right">
441
+ <span style="font-size: 12px; color: #6c757d; text-transform: uppercase; letter-spacing: 1px;">${this.appTitle}</span>
442
+ </td>
443
+ </tr>
444
+ </table>
445
+ </td>
446
+ </tr>
447
+
448
+ <!-- Main content -->
449
+ <tr>
450
+ <td style="padding: 32px 40px;">
451
+ <!-- Title section -->
452
+ <div style="margin-bottom: 24px;">
453
+ <span style="font-size: 32px; margin-right: 12px;">${icon}</span>
454
+ <h1 style="display: inline; font-size: 24px; font-weight: 600; color: #2d3436; margin: 0; vertical-align: middle;">${title}</h1>
455
+ </div>
456
+
457
+ <!-- Status badge -->
458
+ <div style="margin-bottom: 24px;">
459
+ <span style="display: inline-block; background-color: ${accentColor}15; color: ${accentColor}; font-size: 12px; font-weight: 600; padding: 6px 12px; border-radius: 16px; text-transform: uppercase; letter-spacing: 0.5px;">
460
+ ${type.replace(/_/g, " ")}
461
+ </span>
462
+ </div>
463
+ `;
464
+ for (const event of events) {
465
+ html += `
466
+ <!-- Event content -->
467
+ <div style="background-color: #f8f9fa; border-radius: 8px; padding: 24px; margin-bottom: 24px;">
468
+ <div style="font-size: 12px; color: #6c757d; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.5px;">
469
+ ${this.formatDateTime(event.timestamp)}
470
+ </div>
471
+ <table width="100%" cellpadding="0" cellspacing="0">
472
+ ${this.formatEventDataHtml(event.data)}
473
+ </table>
474
+ </div>
475
+ `;
476
+ }
477
+ html += `
478
+ </td>
479
+ </tr>
480
+
481
+ <!-- Footer -->
482
+ <tr>
483
+ <td style="padding: 24px 40px; background-color: #f8f9fa; border-top: 1px solid #e9ecef;">
484
+ <p style="margin: 0; font-size: 12px; color: #6c757d; line-height: 1.5;">
485
+ This is an automated notification from ${this.appTitle}.${this.footerText ? `<br>${this.footerText}` : ""}${this.footerLink ? `<br><a href="${this.footerLink}" style="color: ${this.brandColor}; text-decoration: none;">${this.footerLink}</a>` : ""}
486
+ </p>
487
+ </td>
488
+ </tr>
489
+
490
+ </table>
491
+ </td>
492
+ </tr>
493
+ </table>
494
+ </body>
495
+ </html>
496
+ `;
497
+ return html;
498
+ }
499
+ formatNotificationText(type, events) {
500
+ const timestamp = this.formatDateTime(new Date());
501
+ const title = events[0]?.title || this.getNotificationTitle(type);
502
+ let text = `${this.appTitle} - ${title}\n`;
503
+ text += `Generated: ${timestamp}\n`;
504
+ text += "=".repeat(60) + "\n\n";
505
+ for (const event of events) {
506
+ text += `Time: ${this.formatDateTime(event.timestamp)}\n`;
507
+ text += `Details:\n${this.formatEventDataText(event.data)}\n`;
508
+ text += "-".repeat(40) + "\n\n";
509
+ }
510
+ text += `This is an automated notification from ${this.appTitle}.\n`;
511
+ if (this.footerText)
512
+ text += `${this.footerText}\n`;
513
+ return text;
514
+ }
515
+ formatEventDataText(data) {
516
+ if (!data || typeof data !== "object") {
517
+ return String(data || "No details");
518
+ }
519
+ const formatValue = (val) => {
520
+ if (val instanceof Date)
521
+ return this.formatDateTime(val);
522
+ if (typeof val === "object")
523
+ return JSON.stringify(val);
524
+ return String(val ?? "-");
525
+ };
526
+ return Object.entries(data)
527
+ .map(([key, val]) => {
528
+ const label = key
529
+ .replace(/([A-Z])/g, " $1")
530
+ .replace(/^./, (s) => s.toUpperCase());
531
+ return ` ${label}: ${formatValue(val)}`;
532
+ })
533
+ .join("\n");
534
+ }
535
+ getNotificationTitle(type) {
536
+ switch (type) {
537
+ case "startup":
538
+ return "Application Started";
539
+ case "shutdown":
540
+ return "Application Shutdown";
541
+ case "error":
542
+ return "Error Alert";
543
+ case "warning":
544
+ return "Warning";
545
+ case "info":
546
+ return "Information";
547
+ case "success":
548
+ return "Success";
549
+ case "custom":
550
+ return "Notification";
551
+ default:
552
+ return "Notification";
553
+ }
554
+ }
555
+ generateTestEmailHtml(provider) {
556
+ return `
557
+ <!DOCTYPE html>
558
+ <html>
559
+ <head>
560
+ <meta charset="utf-8">
561
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
562
+ <title>Email Configuration Verified</title>
563
+ </head>
564
+ <body style="margin: 0; padding: 0; background-color: #f6f9fc; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Ubuntu, sans-serif;">
565
+ <table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f6f9fc; padding: 40px 20px;">
566
+ <tr>
567
+ <td align="center">
568
+ <table width="100%" cellpadding="0" cellspacing="0" style="max-width: 600px; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);">
569
+
570
+ <!-- Header -->
571
+ <tr>
572
+ <td style="padding: 32px 40px 24px 40px; border-bottom: 1px solid #e9ecef;">
573
+ <table width="100%" cellpadding="0" cellspacing="0">
574
+ <tr>
575
+ <td>
576
+ ${this.logoUrl ? `<img src="${this.logoUrl}" alt="${this.appName}" width="150" style="display: block; border: 0;" />` : `<span style="font-size: 24px; font-weight: 700; color: ${this.brandColor};">${this.appName}</span>`}
577
+ </td>
578
+ <td align="right">
579
+ <span style="font-size: 12px; color: #6c757d; text-transform: uppercase; letter-spacing: 1px;">${this.appTitle}</span>
580
+ </td>
581
+ </tr>
582
+ </table>
583
+ </td>
584
+ </tr>
585
+
586
+ <!-- Main content -->
587
+ <tr>
588
+ <td style="padding: 32px 40px; text-align: center;">
589
+ <div style="width: 64px; height: 64px; background-color: #d4edda; border-radius: 50%; margin: 0 auto 24px; display: flex; align-items: center; justify-content: center;">
590
+ <span style="font-size: 32px; line-height: 64px;">✅</span>
591
+ </div>
592
+ <h1 style="font-size: 24px; font-weight: 600; color: #2d3436; margin: 0 0 16px 0;">Email Configuration Verified</h1>
593
+ <p style="font-size: 16px; color: #6c757d; margin: 0 0 32px 0;">Your email notifications are configured correctly.</p>
594
+
595
+ <!-- Info card -->
596
+ <div style="background-color: #f8f9fa; border-radius: 8px; padding: 24px; text-align: left;">
597
+ <div style="display: flex; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid #e9ecef;">
598
+ <span style="color: #6c757d; font-size: 14px;">Provider</span>
599
+ <span style="font-weight: 600; color: #2d3436; font-size: 14px;">${provider}</span>
600
+ </div>
601
+ <div style="display: flex; justify-content: space-between; padding: 12px 0;">
602
+ <span style="color: #6c757d; font-size: 14px;">App</span>
603
+ <span style="font-weight: 600; color: #2d3436; font-size: 14px;">${this.appTitle}</span>
604
+ </div>
605
+ </div>
606
+ </td>
607
+ </tr>
608
+
609
+ <!-- Footer -->
610
+ <tr>
611
+ <td style="padding: 24px 40px; background-color: #f8f9fa; border-top: 1px solid #e9ecef; text-align: center;">
612
+ <p style="margin: 0; font-size: 12px; color: #6c757d; line-height: 1.5;">
613
+ This is an automated test from ${this.appTitle}.${this.footerText ? `<br>${this.footerText}` : ""}${this.footerLink ? `<br><a href="${this.footerLink}" style="color: ${this.brandColor}; text-decoration: none;">${this.footerLink}</a>` : ""}
614
+ </p>
615
+ </td>
616
+ </tr>
617
+
618
+ </table>
619
+ </td>
620
+ </tr>
621
+ </table>
622
+ </body>
623
+ </html>
624
+ `;
625
+ }
626
+ }
627
+ // ============================================================================
628
+ // Singleton Pattern
629
+ // ============================================================================
630
+ let emailServiceInstance = null;
631
+ /**
632
+ * Get the email service instance (singleton)
633
+ */
634
+ export function getEmailService() {
635
+ return emailServiceInstance;
636
+ }
637
+ /**
638
+ * Create and initialize the email service
639
+ */
640
+ export async function createEmailService(config) {
641
+ if (emailServiceInstance) {
642
+ return emailServiceInstance;
643
+ }
644
+ emailServiceInstance = new EmailService(config);
645
+ await emailServiceInstance.initialize();
646
+ return emailServiceInstance;
647
+ }
648
+ export default EmailService;
649
+ //# sourceMappingURL=emailService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emailService.js","sourceRoot":"","sources":["../../src/services/emailService.ts"],"names":[],"mappings":"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"}