@gravito/signal 1.0.0-beta.1 → 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/dist/index.js CHANGED
@@ -33,59 +33,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
33
  ));
34
34
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
35
 
36
- // src/dev/DevMailbox.ts
37
- var import_node_crypto, DevMailbox;
38
- var init_DevMailbox = __esm({
39
- "src/dev/DevMailbox.ts"() {
40
- "use strict";
41
- import_node_crypto = require("crypto");
42
- DevMailbox = class {
43
- entries = [];
44
- maxEntries = 50;
45
- add(message) {
46
- const entry = {
47
- id: (0, import_node_crypto.randomUUID)(),
48
- envelope: {
49
- from: message.from,
50
- to: message.to,
51
- ...message.cc ? { cc: message.cc } : {},
52
- ...message.bcc ? { bcc: message.bcc } : {},
53
- ...message.replyTo ? { replyTo: message.replyTo } : {},
54
- subject: message.subject,
55
- ...message.priority ? { priority: message.priority } : {},
56
- ...message.attachments ? { attachments: message.attachments } : {}
57
- },
58
- html: message.html,
59
- ...message.text ? { text: message.text } : {},
60
- sentAt: /* @__PURE__ */ new Date()
61
- };
62
- this.entries.unshift(entry);
63
- if (this.entries.length > this.maxEntries) {
64
- this.entries = this.entries.slice(0, this.maxEntries);
65
- }
66
- return entry;
67
- }
68
- list() {
69
- return this.entries;
70
- }
71
- get(id) {
72
- return this.entries.find((e) => e.id === id);
73
- }
74
- delete(id) {
75
- const index = this.entries.findIndex((e) => e.id === id);
76
- if (index !== -1) {
77
- this.entries.splice(index, 1);
78
- return true;
79
- }
80
- return false;
81
- }
82
- clear() {
83
- this.entries = [];
84
- }
85
- };
86
- }
87
- });
88
-
89
36
  // src/renderers/ReactRenderer.ts
90
37
  var ReactRenderer_exports = {};
91
38
  __export(ReactRenderer_exports, {
@@ -96,13 +43,14 @@ var init_ReactRenderer = __esm({
96
43
  "src/renderers/ReactRenderer.ts"() {
97
44
  "use strict";
98
45
  ReactRenderer = class {
99
- constructor(component, props) {
46
+ constructor(component, props, deps = {}) {
100
47
  this.component = component;
101
48
  this.props = props;
49
+ this.deps = deps;
102
50
  }
103
51
  async render(data) {
104
- const { createElement } = await import("react");
105
- const { renderToStaticMarkup } = await import("react-dom/server");
52
+ const createElement = this.deps.createElement ?? (await import("react")).createElement;
53
+ const renderToStaticMarkup = this.deps.renderToStaticMarkup ?? (await import("react-dom/server")).renderToStaticMarkup;
106
54
  const mergedProps = { ...this.props, ...data };
107
55
  const element = createElement(this.component, mergedProps);
108
56
  const html = renderToStaticMarkup(element);
@@ -37353,13 +37301,15 @@ var init_VueRenderer = __esm({
37353
37301
  "src/renderers/VueRenderer.ts"() {
37354
37302
  "use strict";
37355
37303
  VueRenderer = class {
37356
- constructor(component, props) {
37304
+ constructor(component, props, deps = {}) {
37357
37305
  this.component = component;
37358
37306
  this.props = props;
37307
+ this.deps = deps;
37359
37308
  }
37360
37309
  async render(data) {
37361
- const { createSSRApp, h } = await import("vue");
37362
- const { renderToString } = await Promise.resolve().then(() => __toESM(require_server_renderer()));
37310
+ const createSSRApp = this.deps.createSSRApp ?? (await import("vue")).createSSRApp;
37311
+ const h = this.deps.h ?? (await import("vue")).h;
37312
+ const renderToString = this.deps.renderToString ?? (await Promise.resolve().then(() => __toESM(require_server_renderer()))).renderToString;
37363
37313
  const mergedProps = { ...this.props, ...data };
37364
37314
  const app = createSSRApp({
37365
37315
  render: () => h(this.component, mergedProps)
@@ -37378,436 +37328,6 @@ var init_VueRenderer = __esm({
37378
37328
  }
37379
37329
  });
37380
37330
 
37381
- // src/dev/ui/shared.ts
37382
- var styles, layout;
37383
- var init_shared = __esm({
37384
- "src/dev/ui/shared.ts"() {
37385
- "use strict";
37386
- styles = `
37387
- :root {
37388
- --primary: #6366f1;
37389
- --primary-dark: #4f46e5;
37390
- --bg-dark: #0f172a;
37391
- --bg-card: #1e293b;
37392
- --text: #f1f5f9;
37393
- --text-muted: #94a3b8;
37394
- --border: #334155;
37395
- --danger: #ef4444;
37396
- }
37397
- body { background: var(--bg-dark); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 20px; }
37398
- .container { max-width: 1000px; margin: 0 auto; }
37399
- .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
37400
- .title { font-size: 24px; font-weight: bold; display: flex; align-items: center; gap: 10px; }
37401
- .card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
37402
- .btn { background: var(--border); color: var(--text); border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; text-decoration: none; font-size: 14px; transition: 0.2s; }
37403
- .btn:hover { background: var(--bg-card-hover); }
37404
- .btn-primary { background: var(--primary); color: white; }
37405
- .btn-primary:hover { background: var(--primary-dark); }
37406
- .btn-danger { background: var(--danger); color: white; }
37407
- .list-item { padding: 16px; border-bottom: 1px solid var(--border); display: flex; flex-direction: column; gap: 4px; text-decoration: none; color: inherit; transition: background 0.2s; }
37408
- .list-item:last-child { border-bottom: none; }
37409
- .list-item:hover { background: #334155; }
37410
- .meta { display: flex; justify-content: space-between; font-size: 14px; color: var(--text-muted); }
37411
- .subject { font-weight: 600; font-size: 16px; }
37412
- .from { color: #cbd5e1; }
37413
- .badge { background: #475569; padding: 2px 6px; border-radius: 4px; font-size: 12px; }
37414
- .badge-high { background: #dc2626; color: white; }
37415
- .empty { padding: 40px; text-align: center; color: var(--text-muted); }
37416
- `;
37417
- layout = (title, content) => `
37418
- <!DOCTYPE html>
37419
- <html>
37420
- <head>
37421
- <title>${title} - Gravito Mailbox</title>
37422
- <style>${styles}</style>
37423
- </head>
37424
- <body>
37425
- <div class="container">
37426
- ${content}
37427
- </div>
37428
- </body>
37429
- </html>
37430
- `;
37431
- }
37432
- });
37433
-
37434
- // src/dev/ui/mailbox.ts
37435
- function formatAddress(addr) {
37436
- return addr.name ? `${addr.name} <${addr.address}>` : addr.address;
37437
- }
37438
- function timeAgo(date) {
37439
- const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
37440
- if (seconds < 60) {
37441
- return "Just now";
37442
- }
37443
- const minutes = Math.floor(seconds / 60);
37444
- if (minutes < 60) {
37445
- return `${minutes}m ago`;
37446
- }
37447
- const hours = Math.floor(minutes / 60);
37448
- if (hours < 24) {
37449
- return `${hours}h ago`;
37450
- }
37451
- return date.toLocaleDateString();
37452
- }
37453
- function getMailboxHtml(entries, prefix) {
37454
- const list = entries.length === 0 ? '<div class="empty">No emails found in mailbox.</div>' : entries.map(
37455
- (entry) => `
37456
- <a href="${prefix}/${entry.id}" class="list-item">
37457
- <div class="meta">
37458
- <span class="from">${formatAddress(entry.envelope.from || { address: "Unknown" })}</span>
37459
- <span>${timeAgo(entry.sentAt)}</span>
37460
- </div>
37461
- <div class="subject">
37462
- ${entry.envelope.priority === "high" ? '<span class="badge badge-high">High</span> ' : ""}
37463
- ${entry.envelope.subject || "(No Subject)"}
37464
- </div>
37465
- <div class="meta" style="margin-top: 4px;">
37466
- To: ${entry.envelope.to?.map((t) => t.address).join(", ")}
37467
- </div>
37468
- </a>
37469
- `
37470
- ).join("");
37471
- const content = `
37472
- <div class="header">
37473
- <div class="title">\u{1F4EC} Gravito Mailbox</div>
37474
- ${entries.length > 0 ? `<button onclick="clearAll()" class="btn btn-danger">Clear All</button>` : ""}
37475
- </div>
37476
-
37477
- <div class="card">
37478
- ${list}
37479
- </div>
37480
-
37481
- <script>
37482
- async function clearAll() {
37483
- if (!confirm('Clear all emails?')) return;
37484
- await fetch('${prefix}', { method: 'DELETE' });
37485
- window.location.reload();
37486
- }
37487
- </script>
37488
- `;
37489
- return layout("Inbox", content);
37490
- }
37491
- var init_mailbox = __esm({
37492
- "src/dev/ui/mailbox.ts"() {
37493
- "use strict";
37494
- init_shared();
37495
- }
37496
- });
37497
-
37498
- // src/dev/ui/preview.ts
37499
- function getPreviewHtml(entry, prefix) {
37500
- const from = entry.envelope.from ? `${entry.envelope.from.name || ""} &lt;${entry.envelope.from.address}&gt;` : "Unknown";
37501
- const to = entry.envelope.to?.map((t) => t.address).join(", ") || "Unknown";
37502
- const content = `
37503
- <div class="header">
37504
- <div class="title">
37505
- <a href="${prefix}" class="btn">\u2190 Back</a>
37506
- <span style="margin-left: 10px">Email Preview</span>
37507
- </div>
37508
- <button onclick="deleteEmail('${entry.id}')" class="btn btn-danger">Delete</button>
37509
- </div>
37510
-
37511
- <div class="card" style="margin-bottom: 20px; padding: 20px;">
37512
- <div style="font-size: 18px; font-weight: bold; margin-bottom: 10px;">${entry.envelope.subject || "(No Subject)"}</div>
37513
- <div class="meta" style="margin-bottom: 5px;">From: ${from}</div>
37514
- <div class="meta" style="margin-bottom: 5px;">To: ${to}</div>
37515
- <div class="meta">Date: ${entry.sentAt.toLocaleString()}</div>
37516
- </div>
37517
-
37518
- <div style="margin-bottom: 10px;">
37519
- <button onclick="setView('html')" id="btn-html" class="btn btn-primary">HTML</button>
37520
- <button onclick="setView('text')" id="btn-text" class="btn">Text</button>
37521
- <button onclick="setView('raw')" id="btn-raw" class="btn">Raw JSON</button>
37522
- <a href="${prefix}/${entry.id}/html" target="_blank" class="btn">Open HTML \u2197</a>
37523
- </div>
37524
-
37525
- <div class="card" style="height: 600px; display: flex;">
37526
- <iframe id="preview-frame" src="${prefix}/${entry.id}/html" style="width: 100%; height: 100%; border: none;"></iframe>
37527
- <pre id="raw-view" style="display: none; padding: 20px; overflow: auto; width: 100%;">${JSON.stringify(entry, null, 2)}</pre>
37528
- <pre id="text-view" style="display: none; padding: 20px; overflow: auto; width: 100%; white-space: pre-wrap; font-family: monospace;">${entry.text || "No text content"}</pre>
37529
- </div>
37530
-
37531
- <script>
37532
- function setView(mode) {
37533
- document.getElementById('preview-frame').style.display = mode === 'html' ? 'block' : 'none';
37534
- document.getElementById('raw-view').style.display = mode === 'raw' ? 'block' : 'none';
37535
- document.getElementById('text-view').style.display = mode === 'text' ? 'block' : 'none';
37536
-
37537
- document.getElementById('btn-html').className = mode === 'html' ? 'btn btn-primary' : 'btn';
37538
- document.getElementById('btn-text').className = mode === 'text' ? 'btn btn-primary' : 'btn';
37539
- document.getElementById('btn-raw').className = mode === 'raw' ? 'btn btn-primary' : 'btn';
37540
- }
37541
-
37542
- async function deleteEmail(id) {
37543
- if (!confirm('Delete this email?')) return;
37544
- await fetch('${prefix}/' + id, { method: 'DELETE' });
37545
- window.location.href = '${prefix}';
37546
- }
37547
- </script>
37548
- `;
37549
- return layout(entry.envelope.subject || "Preview", content);
37550
- }
37551
- var init_preview = __esm({
37552
- "src/dev/ui/preview.ts"() {
37553
- "use strict";
37554
- init_shared();
37555
- }
37556
- });
37557
-
37558
- // src/dev/DevServer.ts
37559
- var DevServer;
37560
- var init_DevServer = __esm({
37561
- "src/dev/DevServer.ts"() {
37562
- "use strict";
37563
- init_mailbox();
37564
- init_preview();
37565
- DevServer = class {
37566
- constructor(mailbox, base = "/__mail") {
37567
- this.mailbox = mailbox;
37568
- this.base = base;
37569
- }
37570
- register(core) {
37571
- const router = core.router;
37572
- const prefix = this.base.replace(/\/$/, "");
37573
- router.get(prefix, (ctx) => {
37574
- const entries = this.mailbox.list();
37575
- return ctx.html(getMailboxHtml(entries, prefix));
37576
- });
37577
- router.get(`${prefix}/:id`, (ctx) => {
37578
- const id = ctx.req.param("id");
37579
- if (!id) {
37580
- return ctx.text("Bad Request", 400);
37581
- }
37582
- const entry = this.mailbox.get(id);
37583
- if (!entry) {
37584
- return ctx.text("Email not found", 404);
37585
- }
37586
- return ctx.html(getPreviewHtml(entry, prefix));
37587
- });
37588
- router.get(`${prefix}/:id/html`, (ctx) => {
37589
- const id = ctx.req.param("id");
37590
- if (!id) {
37591
- return ctx.text("Bad Request", 400);
37592
- }
37593
- const entry = this.mailbox.get(id);
37594
- if (!entry) {
37595
- return ctx.text("Not found", 404);
37596
- }
37597
- return ctx.html(entry.html);
37598
- });
37599
- router.get(`${prefix}/:id/text`, (ctx) => {
37600
- const id = ctx.req.param("id");
37601
- if (!id) {
37602
- return ctx.text("Bad Request", 400);
37603
- }
37604
- const entry = this.mailbox.get(id);
37605
- if (!entry) {
37606
- return ctx.text("Not found", 404);
37607
- }
37608
- ctx.header("Content-Type", "text/plain; charset=utf-8");
37609
- return ctx.text(entry.text || "No text content", 200);
37610
- });
37611
- router.get(`${prefix}/:id/raw`, (ctx) => {
37612
- const id = ctx.req.param("id");
37613
- if (!id) {
37614
- return ctx.json({ error: "Bad Request" }, 400);
37615
- }
37616
- const entry = this.mailbox.get(id);
37617
- if (!entry) {
37618
- return ctx.json({ error: "Not found" }, 404);
37619
- }
37620
- return ctx.json(entry);
37621
- });
37622
- router.get(`${prefix}/:id/delete`, (ctx) => {
37623
- return ctx.text("Method not allowed", 405);
37624
- });
37625
- router.delete(`${prefix}/:id`, (ctx) => {
37626
- const id = ctx.req.param("id");
37627
- if (!id) {
37628
- return ctx.json({ success: false, error: "Bad Request" }, 400);
37629
- }
37630
- const success = this.mailbox.delete(id);
37631
- return ctx.json({ success });
37632
- });
37633
- router.delete(prefix, (ctx) => {
37634
- this.mailbox.clear();
37635
- return ctx.json({ success: true });
37636
- });
37637
- core.logger.info(`[OrbitSignal] Dev Mailbox available at ${prefix}`);
37638
- }
37639
- };
37640
- }
37641
- });
37642
-
37643
- // src/transports/LogTransport.ts
37644
- var LogTransport;
37645
- var init_LogTransport = __esm({
37646
- "src/transports/LogTransport.ts"() {
37647
- "use strict";
37648
- LogTransport = class {
37649
- async send(message) {
37650
- console.log("\n\u{1F4E7} [OrbitSignal] Email Sent (Simulated):");
37651
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
37652
- console.log(
37653
- `From: ${message.from.name ? `${message.from.name} <${message.from.address}>` : message.from.address}`
37654
- );
37655
- console.log(`To: ${message.to.map((t) => t.address).join(", ")}`);
37656
- console.log(`Subject: ${message.subject}`);
37657
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
37658
- console.log(`[Content Size]: ${message.html.length} chars (HTML)`);
37659
- console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
37660
- }
37661
- };
37662
- }
37663
- });
37664
-
37665
- // src/transports/MemoryTransport.ts
37666
- var MemoryTransport;
37667
- var init_MemoryTransport = __esm({
37668
- "src/transports/MemoryTransport.ts"() {
37669
- "use strict";
37670
- MemoryTransport = class {
37671
- constructor(mailbox) {
37672
- this.mailbox = mailbox;
37673
- }
37674
- async send(message) {
37675
- this.mailbox.add(message);
37676
- }
37677
- };
37678
- }
37679
- });
37680
-
37681
- // src/OrbitSignal.ts
37682
- var OrbitSignal_exports = {};
37683
- __export(OrbitSignal_exports, {
37684
- OrbitSignal: () => OrbitSignal
37685
- });
37686
- var OrbitSignal;
37687
- var init_OrbitSignal = __esm({
37688
- "src/OrbitSignal.ts"() {
37689
- "use strict";
37690
- init_DevMailbox();
37691
- init_DevServer();
37692
- init_LogTransport();
37693
- init_MemoryTransport();
37694
- OrbitSignal = class _OrbitSignal {
37695
- static instance;
37696
- config;
37697
- devMailbox;
37698
- constructor(config = {}) {
37699
- this.config = config;
37700
- _OrbitSignal.instance = this;
37701
- }
37702
- /**
37703
- * Get the singleton instance of OrbitSignal
37704
- *
37705
- * @returns The singleton instance of OrbitSignal.
37706
- * @throws {Error} If OrbitSignal has not been initialized.
37707
- */
37708
- static getInstance() {
37709
- if (!_OrbitSignal.instance) {
37710
- throw new Error("OrbitSignal has not been initialized. Call OrbitSignal.configure() first.");
37711
- }
37712
- return _OrbitSignal.instance;
37713
- }
37714
- /**
37715
- * Configure the OrbitSignal instance
37716
- *
37717
- * @param config - The mail configuration object.
37718
- * @returns A new instance of OrbitSignal.
37719
- */
37720
- static configure(config) {
37721
- if (!config.transport && !config.devMode) {
37722
- console.warn("[OrbitSignal] No transport provided, falling back to LogTransport");
37723
- config.transport = new LogTransport();
37724
- }
37725
- return new _OrbitSignal(config);
37726
- }
37727
- /**
37728
- * Install the orbit into PlanetCore
37729
- *
37730
- * @param core - The PlanetCore instance.
37731
- */
37732
- install(core) {
37733
- core.logger.info("[OrbitSignal] Initializing Mail Service (Exposed as: mail)");
37734
- if (!this.config.transport && !this.config.devMode) {
37735
- this.config.transport = new LogTransport();
37736
- }
37737
- if (this.config.devMode) {
37738
- this.devMailbox = new DevMailbox();
37739
- this.config.transport = new MemoryTransport(this.devMailbox);
37740
- core.logger.info("[OrbitSignal] Dev Mode Enabled: Emails will be intercepted to Dev Mailbox");
37741
- const devServer = new DevServer(this.devMailbox, this.config.devUiPrefix || "/__mail");
37742
- devServer.register(core);
37743
- }
37744
- core.adapter.use("*", async (c, next) => {
37745
- c.set("mail", {
37746
- send: (mailable) => this.send(mailable),
37747
- queue: (mailable) => this.queue(mailable)
37748
- });
37749
- await next();
37750
- return void 0;
37751
- });
37752
- }
37753
- /**
37754
- * Send a mailable instance
37755
- *
37756
- * @param mailable - The mailable object to send.
37757
- * @returns A promise that resolves when the email is sent.
37758
- * @throws {Error} If the message is missing "from" or "to" addresses, or if no transport is configured.
37759
- */
37760
- async send(mailable) {
37761
- const envelope = await mailable.buildEnvelope(this.config);
37762
- if (!envelope.from) {
37763
- throw new Error('Message is missing "from" address');
37764
- }
37765
- if (!envelope.to || envelope.to.length === 0) {
37766
- throw new Error('Message is missing "to" address');
37767
- }
37768
- const content = await mailable.renderContent();
37769
- const message = {
37770
- ...envelope,
37771
- from: envelope.from,
37772
- to: envelope.to,
37773
- subject: envelope.subject || "(No Subject)",
37774
- priority: envelope.priority || "normal",
37775
- html: content.html
37776
- };
37777
- if (content.text) {
37778
- message.text = content.text;
37779
- }
37780
- if (!this.config.transport) {
37781
- throw new Error(
37782
- "[OrbitSignal] No transport configured. Did you call configure() or register the orbit?"
37783
- );
37784
- }
37785
- await this.config.transport.send(message);
37786
- }
37787
- /**
37788
- * Queue a mailable instance
37789
- *
37790
- * Push a mailable into the queue for execution.
37791
- * Requires OrbitStream to be installed and available in the context.
37792
- *
37793
- * @param mailable - The mailable object to queue.
37794
- * @returns A promise that resolves when the job is pushed to the queue or sent immediately if no queue service is found.
37795
- */
37796
- async queue(mailable) {
37797
- const queue = this.queueService;
37798
- if (queue) {
37799
- await queue.push(mailable);
37800
- } else {
37801
- console.warn(
37802
- "[OrbitSignal] Queue service not available, sending immediately. Install OrbitStream to enable queuing."
37803
- );
37804
- await this.send(mailable);
37805
- }
37806
- }
37807
- };
37808
- }
37809
- });
37810
-
37811
37331
  // src/index.ts
37812
37332
  var index_exports = {};
37813
37333
  __export(index_exports, {
@@ -37822,7 +37342,53 @@ __export(index_exports, {
37822
37342
  TemplateRenderer: () => TemplateRenderer
37823
37343
  });
37824
37344
  module.exports = __toCommonJS(index_exports);
37825
- init_DevMailbox();
37345
+
37346
+ // src/dev/DevMailbox.ts
37347
+ var import_node_crypto = require("crypto");
37348
+ var DevMailbox = class {
37349
+ entries = [];
37350
+ maxEntries = 50;
37351
+ add(message) {
37352
+ const entry = {
37353
+ id: (0, import_node_crypto.randomUUID)(),
37354
+ envelope: {
37355
+ from: message.from,
37356
+ to: message.to,
37357
+ ...message.cc ? { cc: message.cc } : {},
37358
+ ...message.bcc ? { bcc: message.bcc } : {},
37359
+ ...message.replyTo ? { replyTo: message.replyTo } : {},
37360
+ subject: message.subject,
37361
+ ...message.priority ? { priority: message.priority } : {},
37362
+ ...message.attachments ? { attachments: message.attachments } : {}
37363
+ },
37364
+ html: message.html,
37365
+ ...message.text ? { text: message.text } : {},
37366
+ sentAt: /* @__PURE__ */ new Date()
37367
+ };
37368
+ this.entries.unshift(entry);
37369
+ if (this.entries.length > this.maxEntries) {
37370
+ this.entries = this.entries.slice(0, this.maxEntries);
37371
+ }
37372
+ return entry;
37373
+ }
37374
+ list() {
37375
+ return this.entries;
37376
+ }
37377
+ get(id) {
37378
+ return this.entries.find((e) => e.id === id);
37379
+ }
37380
+ delete(id) {
37381
+ const index = this.entries.findIndex((e) => e.id === id);
37382
+ if (index !== -1) {
37383
+ this.entries.splice(index, 1);
37384
+ return true;
37385
+ }
37386
+ return false;
37387
+ }
37388
+ clear() {
37389
+ this.entries = [];
37390
+ }
37391
+ };
37826
37392
 
37827
37393
  // src/renderers/HtmlRenderer.ts
37828
37394
  var HtmlRenderer = class {
@@ -37868,6 +37434,7 @@ var Mailable = class {
37868
37434
  renderer;
37869
37435
  rendererResolver;
37870
37436
  renderData = {};
37437
+ config;
37871
37438
  // ===== Fluent API (Envelope Construction) =====
37872
37439
  from(address) {
37873
37440
  this.envelope.from = typeof address === "string" ? { address } : address;
@@ -37893,7 +37460,7 @@ var Mailable = class {
37893
37460
  this.envelope.subject = subject;
37894
37461
  return this;
37895
37462
  }
37896
- priority(level) {
37463
+ emailPriority(level) {
37897
37464
  this.envelope.priority = level;
37898
37465
  return this;
37899
37466
  }
@@ -37924,10 +37491,10 @@ var Mailable = class {
37924
37491
  * Set the content using a React component.
37925
37492
  * Dynamically imports ReactRenderer to avoid hard dependency errors if React is not installed.
37926
37493
  */
37927
- react(component, props) {
37494
+ react(component, props, deps) {
37928
37495
  this.rendererResolver = async () => {
37929
37496
  const { ReactRenderer: ReactRenderer2 } = await Promise.resolve().then(() => (init_ReactRenderer(), ReactRenderer_exports));
37930
- return new ReactRenderer2(component, props);
37497
+ return new ReactRenderer2(component, props, deps);
37931
37498
  };
37932
37499
  return this;
37933
37500
  }
@@ -37935,10 +37502,10 @@ var Mailable = class {
37935
37502
  * Set the content using a Vue component.
37936
37503
  * Dynamically imports VueRenderer to avoid hard dependency errors if Vue is not installed.
37937
37504
  */
37938
- vue(component, props) {
37505
+ vue(component, props, deps) {
37939
37506
  this.rendererResolver = async () => {
37940
37507
  const { VueRenderer: VueRenderer2 } = await Promise.resolve().then(() => (init_VueRenderer(), VueRenderer_exports));
37941
- return new VueRenderer2(component, props);
37508
+ return new VueRenderer2(component, props, deps);
37942
37509
  };
37943
37510
  return this;
37944
37511
  }
@@ -37946,6 +37513,7 @@ var Mailable = class {
37946
37513
  queueName;
37947
37514
  connectionName;
37948
37515
  delaySeconds;
37516
+ priority;
37949
37517
  onQueue(queue) {
37950
37518
  this.queueName = queue;
37951
37519
  return this;
@@ -37958,12 +37526,23 @@ var Mailable = class {
37958
37526
  this.delaySeconds = seconds;
37959
37527
  return this;
37960
37528
  }
37529
+ withPriority(priority) {
37530
+ this.priority = priority;
37531
+ return this;
37532
+ }
37961
37533
  /**
37962
37534
  * Queue the mailable for sending.
37963
37535
  */
37964
37536
  async queue() {
37965
- const { OrbitSignal: OrbitSignal2 } = await Promise.resolve().then(() => (init_OrbitSignal(), OrbitSignal_exports));
37966
- return OrbitSignal2.getInstance().queue(this);
37537
+ try {
37538
+ const { app } = await import("@gravito/core");
37539
+ const mail = app().container.make("mail");
37540
+ if (mail) {
37541
+ return mail.queue(this);
37542
+ }
37543
+ } catch (_e) {
37544
+ console.warn("[Mailable] Could not auto-resolve mail service for queuing.");
37545
+ }
37967
37546
  }
37968
37547
  // ===== I18n Support =====
37969
37548
  currentLocale;
@@ -37996,11 +37575,13 @@ var Mailable = class {
37996
37575
  */
37997
37576
  async buildEnvelope(configPromise) {
37998
37577
  const config = await Promise.resolve(configPromise);
37578
+ this.config = config;
37999
37579
  if (config.translator) {
38000
37580
  this.setTranslator(config.translator);
38001
37581
  }
38002
37582
  this.build();
38003
37583
  if (this.renderer instanceof TemplateRenderer && config.viewsDir) {
37584
+ this.renderer = new TemplateRenderer(this.renderer.template, config.viewsDir);
38004
37585
  }
38005
37586
  const envelope = {
38006
37587
  from: this.envelope.from || config.from,
@@ -38045,10 +37626,427 @@ var Mailable = class {
38045
37626
  }
38046
37627
  };
38047
37628
 
38048
- // src/index.ts
38049
- init_OrbitSignal();
38050
- init_LogTransport();
38051
- init_MemoryTransport();
37629
+ // src/dev/ui/shared.ts
37630
+ var styles = `
37631
+ :root {
37632
+ --primary: #6366f1;
37633
+ --primary-dark: #4f46e5;
37634
+ --bg-dark: #0f172a;
37635
+ --bg-card: #1e293b;
37636
+ --text: #f1f5f9;
37637
+ --text-muted: #94a3b8;
37638
+ --border: #334155;
37639
+ --danger: #ef4444;
37640
+ }
37641
+ body { background: var(--bg-dark); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 20px; }
37642
+ .container { max-width: 1000px; margin: 0 auto; }
37643
+ .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
37644
+ .title { font-size: 24px; font-weight: bold; display: flex; align-items: center; gap: 10px; }
37645
+ .card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
37646
+ .btn { background: var(--border); color: var(--text); border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; text-decoration: none; font-size: 14px; transition: 0.2s; }
37647
+ .btn:hover { background: var(--bg-card-hover); }
37648
+ .btn-primary { background: var(--primary); color: white; }
37649
+ .btn-primary:hover { background: var(--primary-dark); }
37650
+ .btn-danger { background: var(--danger); color: white; }
37651
+ .list-item { padding: 16px; border-bottom: 1px solid var(--border); display: flex; flex-direction: column; gap: 4px; text-decoration: none; color: inherit; transition: background 0.2s; }
37652
+ .list-item:last-child { border-bottom: none; }
37653
+ .list-item:hover { background: #334155; }
37654
+ .meta { display: flex; justify-content: space-between; font-size: 14px; color: var(--text-muted); }
37655
+ .subject { font-weight: 600; font-size: 16px; }
37656
+ .from { color: #cbd5e1; }
37657
+ .badge { background: #475569; padding: 2px 6px; border-radius: 4px; font-size: 12px; }
37658
+ .badge-high { background: #dc2626; color: white; }
37659
+ .empty { padding: 40px; text-align: center; color: var(--text-muted); }
37660
+ `;
37661
+ var layout = (title, content) => `
37662
+ <!DOCTYPE html>
37663
+ <html>
37664
+ <head>
37665
+ <meta charset="utf-8">
37666
+ <title>${title} - Gravito Mailbox</title>
37667
+ <style>${styles}</style>
37668
+ </head>
37669
+ <body>
37670
+ <div class="container">
37671
+ ${content}
37672
+ </div>
37673
+ </body>
37674
+ </html>
37675
+ `;
37676
+
37677
+ // src/dev/ui/mailbox.ts
37678
+ function formatAddress(addr) {
37679
+ return addr.name ? `${addr.name} <${addr.address}>` : addr.address;
37680
+ }
37681
+ function timeAgo(date) {
37682
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
37683
+ if (seconds < 60) {
37684
+ return "Just now";
37685
+ }
37686
+ const minutes = Math.floor(seconds / 60);
37687
+ if (minutes < 60) {
37688
+ return `${minutes}m ago`;
37689
+ }
37690
+ const hours = Math.floor(minutes / 60);
37691
+ if (hours < 24) {
37692
+ return `${hours}h ago`;
37693
+ }
37694
+ return date.toLocaleDateString();
37695
+ }
37696
+ function getMailboxHtml(entries, prefix) {
37697
+ const list = entries.length === 0 ? '<div class="empty">No emails found in mailbox.</div>' : entries.map(
37698
+ (entry) => `
37699
+ <a href="${prefix}/${entry.id}" class="list-item">
37700
+ <div class="meta">
37701
+ <span class="from">${formatAddress(entry.envelope.from || { address: "Unknown" })}</span>
37702
+ <span>${timeAgo(entry.sentAt)}</span>
37703
+ </div>
37704
+ <div class="subject">
37705
+ ${entry.envelope.priority === "high" ? '<span class="badge badge-high">High</span> ' : ""}
37706
+ ${entry.envelope.subject || "(No Subject)"}
37707
+ </div>
37708
+ <div class="meta" style="margin-top: 4px;">
37709
+ To: ${entry.envelope.to?.map((t) => t.address).join(", ")}
37710
+ </div>
37711
+ </a>
37712
+ `
37713
+ ).join("");
37714
+ const content = `
37715
+ <div class="header">
37716
+ <div class="title">\u{1F4EC} Gravito Mailbox</div>
37717
+ ${entries.length > 0 ? `<button onclick="clearAll()" class="btn btn-danger">Clear All</button>` : ""}
37718
+ </div>
37719
+
37720
+ <div class="card">
37721
+ ${list}
37722
+ </div>
37723
+
37724
+ <script>
37725
+ async function clearAll() {
37726
+ if (!confirm('Clear all emails?')) return;
37727
+ await fetch('${prefix}', { method: 'DELETE' });
37728
+ window.location.reload();
37729
+ }
37730
+ </script>
37731
+ `;
37732
+ return layout("Inbox", content);
37733
+ }
37734
+
37735
+ // src/dev/ui/preview.ts
37736
+ function getPreviewHtml(entry, prefix) {
37737
+ const from = entry.envelope.from ? `${entry.envelope.from.name || ""} &lt;${entry.envelope.from.address}&gt;` : "Unknown";
37738
+ const to = entry.envelope.to?.map((t) => t.address).join(", ") || "Unknown";
37739
+ const content = `
37740
+ <div class="header">
37741
+ <div class="title">
37742
+ <a href="${prefix}" class="btn">\u2190 Back</a>
37743
+ <span style="margin-left: 10px">Email Preview</span>
37744
+ </div>
37745
+ <button onclick="deleteEmail('${entry.id}')" class="btn btn-danger">Delete</button>
37746
+ </div>
37747
+
37748
+ <div class="card" style="margin-bottom: 20px; padding: 20px;">
37749
+ <div style="font-size: 18px; font-weight: bold; margin-bottom: 10px;">${entry.envelope.subject || "(No Subject)"}</div>
37750
+ <div class="meta" style="margin-bottom: 5px;">From: ${from}</div>
37751
+ <div class="meta" style="margin-bottom: 5px;">To: ${to}</div>
37752
+ ${entry.envelope.cc ? `<div class="meta" style="margin-bottom: 5px;">CC: ${entry.envelope.cc.map((t) => t.address).join(", ")}</div>` : ""}
37753
+ ${entry.envelope.bcc ? `<div class="meta" style="margin-bottom: 5px;">BCC: ${entry.envelope.bcc.map((t) => t.address).join(", ")}</div>` : ""}
37754
+ ${entry.envelope.priority ? `<div class="meta" style="margin-bottom: 5px;">Priority: ${entry.envelope.priority}</div>` : ""}
37755
+ <div class="meta">Date: ${entry.sentAt.toLocaleString()}</div>
37756
+ ${entry.envelope.attachments && entry.envelope.attachments.length > 0 ? `
37757
+ <div style="margin-top: 15px; border-top: 1px solid var(--border); padding-top: 10px;">
37758
+ <div style="font-size: 14px; font-weight: bold; margin-bottom: 5px; color: var(--text-muted);">Attachments (${entry.envelope.attachments.length})</div>
37759
+ <div style="display: flex; gap: 10px; flex-wrap: wrap;">
37760
+ ${entry.envelope.attachments.map(
37761
+ (att) => `
37762
+ <div style="background: var(--bg-dark); padding: 8px 12px; border-radius: 6px; border: 1px solid var(--border); display: flex; align-items: center; gap: 8px;">
37763
+ <span style="font-size: 20px;">\u{1F4CE}</span>
37764
+ <div>
37765
+ <div style="font-size: 14px; font-weight: 500;">${att.filename || "untitled"}</div>
37766
+ <div style="font-size: 12px; color: var(--text-muted);">${att.contentType || "application/octet-stream"}</div>
37767
+ </div>
37768
+ </div>
37769
+ `
37770
+ ).join("")}
37771
+ </div>
37772
+ </div>
37773
+ ` : ""}
37774
+ </div>
37775
+
37776
+ <div style="margin-bottom: 10px;">
37777
+ <button onclick="setView('html')" id="btn-html" class="btn btn-primary">HTML</button>
37778
+ <button onclick="setView('text')" id="btn-text" class="btn">Text</button>
37779
+ <button onclick="setView('raw')" id="btn-raw" class="btn">Raw JSON</button>
37780
+ <a href="${prefix}/${entry.id}/html" target="_blank" class="btn">Open HTML \u2197</a>
37781
+ </div>
37782
+
37783
+ <div class="card" style="height: 600px; display: flex;">
37784
+ <iframe id="preview-frame" src="${prefix}/${entry.id}/html" style="width: 100%; height: 100%; border: none;"></iframe>
37785
+ <pre id="raw-view" style="display: none; padding: 20px; overflow: auto; width: 100%;">${JSON.stringify(entry, null, 2)}</pre>
37786
+ <pre id="text-view" style="display: none; padding: 20px; overflow: auto; width: 100%; white-space: pre-wrap; font-family: monospace;">${entry.text || "No text content"}</pre>
37787
+ </div>
37788
+
37789
+ <script>
37790
+ function setView(mode) {
37791
+ document.getElementById('preview-frame').style.display = mode === 'html' ? 'block' : 'none';
37792
+ document.getElementById('raw-view').style.display = mode === 'raw' ? 'block' : 'none';
37793
+ document.getElementById('text-view').style.display = mode === 'text' ? 'block' : 'none';
37794
+
37795
+ document.getElementById('btn-html').className = mode === 'html' ? 'btn btn-primary' : 'btn';
37796
+ document.getElementById('btn-text').className = mode === 'text' ? 'btn btn-primary' : 'btn';
37797
+ document.getElementById('btn-raw').className = mode === 'raw' ? 'btn btn-primary' : 'btn';
37798
+ }
37799
+
37800
+ async function deleteEmail(id) {
37801
+ if (!confirm('Delete this email?')) return;
37802
+ await fetch('${prefix}/' + id, { method: 'DELETE' });
37803
+ window.location.href = '${prefix}';
37804
+ }
37805
+ </script>
37806
+ `;
37807
+ return layout(entry.envelope.subject || "Preview", content);
37808
+ }
37809
+
37810
+ // src/dev/DevServer.ts
37811
+ var DevServer = class {
37812
+ constructor(mailbox, base = "/__mail", options) {
37813
+ this.mailbox = mailbox;
37814
+ this.base = base;
37815
+ this.options = options;
37816
+ }
37817
+ async canAccess(ctx) {
37818
+ const isProduction = process.env.NODE_ENV === "production";
37819
+ if (isProduction && !this.options?.allowInProduction && !this.options?.gate) {
37820
+ return false;
37821
+ }
37822
+ if (this.options?.gate) {
37823
+ return await this.options.gate(ctx);
37824
+ }
37825
+ return true;
37826
+ }
37827
+ register(core) {
37828
+ const router = core.router;
37829
+ const isProduction = process.env.NODE_ENV === "production";
37830
+ if (isProduction && !this.options?.allowInProduction && !this.options?.gate) {
37831
+ core.logger.warn(
37832
+ "[OrbitSignal] Dev Mailbox disabled in production. Configure a gate to allow access."
37833
+ );
37834
+ return;
37835
+ }
37836
+ const prefix = this.base.replace(/\/$/, "");
37837
+ const wrap = (handler) => {
37838
+ return async (ctx) => {
37839
+ const allowed = await this.canAccess(ctx);
37840
+ if (!allowed) {
37841
+ return ctx.text("Unauthorized", 403);
37842
+ }
37843
+ return await handler(ctx);
37844
+ };
37845
+ };
37846
+ router.get(
37847
+ prefix,
37848
+ wrap((ctx) => {
37849
+ const entries = this.mailbox.list();
37850
+ ctx.header("Content-Type", "text/html; charset=utf-8");
37851
+ return ctx.html(getMailboxHtml(entries, prefix));
37852
+ })
37853
+ );
37854
+ router.get(
37855
+ `${prefix}/:id`,
37856
+ wrap((ctx) => {
37857
+ const id = ctx.req.param("id");
37858
+ if (!id) {
37859
+ return ctx.text("Bad Request", 400);
37860
+ }
37861
+ const entry = this.mailbox.get(id);
37862
+ if (!entry) {
37863
+ return ctx.text("Email not found", 404);
37864
+ }
37865
+ ctx.header("Content-Type", "text/html; charset=utf-8");
37866
+ return ctx.html(getPreviewHtml(entry, prefix));
37867
+ })
37868
+ );
37869
+ router.get(
37870
+ `${prefix}/:id/html`,
37871
+ wrap((ctx) => {
37872
+ const id = ctx.req.param("id");
37873
+ if (!id) {
37874
+ return ctx.text("Bad Request", 400);
37875
+ }
37876
+ const entry = this.mailbox.get(id);
37877
+ if (!entry) {
37878
+ return ctx.text("Not found", 404);
37879
+ }
37880
+ ctx.header("Content-Type", "text/html; charset=utf-8");
37881
+ return ctx.html(entry.html);
37882
+ })
37883
+ );
37884
+ router.get(
37885
+ `${prefix}/:id/text`,
37886
+ wrap((ctx) => {
37887
+ const id = ctx.req.param("id");
37888
+ if (!id) {
37889
+ return ctx.text("Bad Request", 400);
37890
+ }
37891
+ const entry = this.mailbox.get(id);
37892
+ if (!entry) {
37893
+ return ctx.text("Not found", 404);
37894
+ }
37895
+ ctx.header("Content-Type", "text/plain; charset=utf-8");
37896
+ return ctx.text(entry.text || "No text content", 200);
37897
+ })
37898
+ );
37899
+ router.get(
37900
+ `${prefix}/:id/raw`,
37901
+ wrap((ctx) => {
37902
+ const id = ctx.req.param("id");
37903
+ if (!id) {
37904
+ return ctx.json({ error: "Bad Request" }, 400);
37905
+ }
37906
+ const entry = this.mailbox.get(id);
37907
+ if (!entry) {
37908
+ return ctx.json({ error: "Not found" }, 404);
37909
+ }
37910
+ return ctx.json(entry);
37911
+ })
37912
+ );
37913
+ router.get(
37914
+ `${prefix}/:id/delete`,
37915
+ wrap((ctx) => {
37916
+ return ctx.text("Method not allowed", 405);
37917
+ })
37918
+ );
37919
+ router.delete(
37920
+ `${prefix}/:id`,
37921
+ wrap((ctx) => {
37922
+ const id = ctx.req.param("id");
37923
+ if (!id) {
37924
+ return ctx.json({ success: false, error: "Bad Request" }, 400);
37925
+ }
37926
+ const success = this.mailbox.delete(id);
37927
+ return ctx.json({ success });
37928
+ })
37929
+ );
37930
+ router.delete(
37931
+ prefix,
37932
+ wrap((ctx) => {
37933
+ this.mailbox.clear();
37934
+ return ctx.json({ success: true });
37935
+ })
37936
+ );
37937
+ core.logger.info(`[OrbitSignal] Dev Mailbox available at ${prefix}`);
37938
+ }
37939
+ };
37940
+
37941
+ // src/transports/LogTransport.ts
37942
+ var LogTransport = class {
37943
+ async send(message) {
37944
+ console.log("\n\u{1F4E7} [OrbitSignal] Email Sent (Simulated):");
37945
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
37946
+ console.log(
37947
+ `From: ${message.from.name ? `${message.from.name} <${message.from.address}>` : message.from.address}`
37948
+ );
37949
+ console.log(`To: ${message.to.map((t) => t.address).join(", ")}`);
37950
+ console.log(`Subject: ${message.subject}`);
37951
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
37952
+ console.log(`[Content Size]: ${message.html.length} chars (HTML)`);
37953
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
37954
+ }
37955
+ };
37956
+
37957
+ // src/transports/MemoryTransport.ts
37958
+ var MemoryTransport = class {
37959
+ constructor(mailbox) {
37960
+ this.mailbox = mailbox;
37961
+ }
37962
+ async send(message) {
37963
+ this.mailbox.add(message);
37964
+ }
37965
+ };
37966
+
37967
+ // src/OrbitSignal.ts
37968
+ var OrbitSignal = class {
37969
+ config;
37970
+ devMailbox;
37971
+ core;
37972
+ constructor(config = {}) {
37973
+ this.config = config;
37974
+ }
37975
+ /**
37976
+ * Install the orbit into PlanetCore
37977
+ *
37978
+ * @param core - The PlanetCore instance.
37979
+ */
37980
+ install(core) {
37981
+ this.core = core;
37982
+ core.logger.info("[OrbitSignal] Initializing Mail Service");
37983
+ if (!this.config.transport && !this.config.devMode) {
37984
+ this.config.transport = new LogTransport();
37985
+ }
37986
+ if (this.config.devMode) {
37987
+ this.devMailbox = new DevMailbox();
37988
+ this.config.transport = new MemoryTransport(this.devMailbox);
37989
+ core.logger.info("[OrbitSignal] Dev Mode Enabled: Emails will be intercepted to Dev Mailbox");
37990
+ const devServer = new DevServer(this.devMailbox, this.config.devUiPrefix || "/__mail", {
37991
+ allowInProduction: this.config.devUiAllowInProduction,
37992
+ gate: this.config.devUiGate
37993
+ });
37994
+ devServer.register(core);
37995
+ }
37996
+ core.container.singleton("mail", () => this);
37997
+ core.adapter.use("*", async (c, next) => {
37998
+ c.set("mail", this);
37999
+ await next();
38000
+ return void 0;
38001
+ });
38002
+ }
38003
+ /**
38004
+ * Send a mailable instance
38005
+ *
38006
+ * @param mailable - The mailable object to send.
38007
+ * @returns A promise that resolves when the email is sent.
38008
+ * @throws {Error} If the message is missing "from" or "to" addresses, or if no transport is configured.
38009
+ */
38010
+ async send(mailable) {
38011
+ const envelope = await mailable.buildEnvelope(this.config);
38012
+ if (!envelope.from) {
38013
+ throw new Error('Message is missing "from" address');
38014
+ }
38015
+ if (!envelope.to || envelope.to.length === 0) {
38016
+ throw new Error('Message is missing "to" address');
38017
+ }
38018
+ const content = await mailable.renderContent();
38019
+ const message = {
38020
+ ...envelope,
38021
+ from: envelope.from,
38022
+ to: envelope.to,
38023
+ subject: envelope.subject || "(No Subject)",
38024
+ priority: envelope.priority || "normal",
38025
+ html: content.html
38026
+ };
38027
+ if (content.text) {
38028
+ message.text = content.text;
38029
+ }
38030
+ if (!this.config.transport) {
38031
+ throw new Error("[OrbitSignal] No transport configured. Did you call register the orbit?");
38032
+ }
38033
+ await this.config.transport.send(message);
38034
+ }
38035
+ /**
38036
+ * Queue a mailable instance
38037
+ */
38038
+ async queue(mailable) {
38039
+ try {
38040
+ const queue = this.core?.container.make("queue");
38041
+ if (queue) {
38042
+ await queue.push(mailable);
38043
+ return;
38044
+ }
38045
+ } catch (_e) {
38046
+ }
38047
+ await this.send(mailable);
38048
+ }
38049
+ };
38052
38050
 
38053
38051
  // src/transports/SesTransport.ts
38054
38052
  var import_client_ses = require("@aws-sdk/client-ses");