@gravito/signal 1.0.0-alpha.2 → 1.0.0-alpha.5
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/README.zh-TW.md +27 -0
- package/dist/OrbitSignal-IPSA2CDO.mjs +7 -0
- package/dist/OrbitSignal-MABW4DDW.mjs +7 -0
- package/dist/OrbitSignal-QSW5VQ5M.mjs +7 -0
- package/dist/OrbitSignal-R22QHWAA.mjs +7 -0
- package/dist/ReactRenderer-24SQ4KRU.mjs +27 -0
- package/dist/VueRenderer-SUP66ISX.mjs +29 -0
- package/dist/chunk-456QRYFW.mjs +401 -0
- package/dist/chunk-EBO3CZXG.mjs +15 -0
- package/dist/chunk-F6MVTUCT.mjs +421 -0
- package/dist/chunk-NEQCQSZI.mjs +406 -0
- package/dist/chunk-YLVDJSED.mjs +431 -0
- package/dist/index.d.mts +26 -18
- package/dist/index.d.ts +26 -18
- package/dist/index.js +59 -28
- package/dist/index.mjs +10 -10
- package/dist/server-renderer-4W4FI7YG.mjs +37269 -0
- package/package.json +12 -13
- package/src/OrbitSignal.ts +16 -21
- package/src/augmentation.ts +13 -0
- package/src/dev/DevServer.ts +26 -10
- package/src/index.ts +2 -0
- package/src/renderers/ReactRenderer.ts +5 -4
- package/src/renderers/TemplateRenderer.ts +7 -5
- package/src/renderers/VueRenderer.ts +5 -3
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
// src/dev/DevMailbox.ts
|
|
2
|
+
import { randomUUID } from "crypto";
|
|
3
|
+
var DevMailbox = class {
|
|
4
|
+
entries = [];
|
|
5
|
+
maxEntries = 50;
|
|
6
|
+
add(message) {
|
|
7
|
+
const entry = {
|
|
8
|
+
id: randomUUID(),
|
|
9
|
+
envelope: {
|
|
10
|
+
from: message.from,
|
|
11
|
+
to: message.to,
|
|
12
|
+
...message.cc ? { cc: message.cc } : {},
|
|
13
|
+
...message.bcc ? { bcc: message.bcc } : {},
|
|
14
|
+
...message.replyTo ? { replyTo: message.replyTo } : {},
|
|
15
|
+
subject: message.subject,
|
|
16
|
+
...message.priority ? { priority: message.priority } : {},
|
|
17
|
+
...message.attachments ? { attachments: message.attachments } : {}
|
|
18
|
+
},
|
|
19
|
+
html: message.html,
|
|
20
|
+
...message.text ? { text: message.text } : {},
|
|
21
|
+
sentAt: /* @__PURE__ */ new Date()
|
|
22
|
+
};
|
|
23
|
+
this.entries.unshift(entry);
|
|
24
|
+
if (this.entries.length > this.maxEntries) {
|
|
25
|
+
this.entries = this.entries.slice(0, this.maxEntries);
|
|
26
|
+
}
|
|
27
|
+
return entry;
|
|
28
|
+
}
|
|
29
|
+
list() {
|
|
30
|
+
return this.entries;
|
|
31
|
+
}
|
|
32
|
+
get(id) {
|
|
33
|
+
return this.entries.find((e) => e.id === id);
|
|
34
|
+
}
|
|
35
|
+
delete(id) {
|
|
36
|
+
const index = this.entries.findIndex((e) => e.id === id);
|
|
37
|
+
if (index !== -1) {
|
|
38
|
+
this.entries.splice(index, 1);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
clear() {
|
|
44
|
+
this.entries = [];
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/dev/ui/shared.ts
|
|
49
|
+
var styles = `
|
|
50
|
+
:root {
|
|
51
|
+
--primary: #6366f1;
|
|
52
|
+
--primary-dark: #4f46e5;
|
|
53
|
+
--bg-dark: #0f172a;
|
|
54
|
+
--bg-card: #1e293b;
|
|
55
|
+
--text: #f1f5f9;
|
|
56
|
+
--text-muted: #94a3b8;
|
|
57
|
+
--border: #334155;
|
|
58
|
+
--danger: #ef4444;
|
|
59
|
+
}
|
|
60
|
+
body { background: var(--bg-dark); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 20px; }
|
|
61
|
+
.container { max-width: 1000px; margin: 0 auto; }
|
|
62
|
+
.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
|
|
63
|
+
.title { font-size: 24px; font-weight: bold; display: flex; align-items: center; gap: 10px; }
|
|
64
|
+
.card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
|
|
65
|
+
.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; }
|
|
66
|
+
.btn:hover { background: var(--bg-card-hover); }
|
|
67
|
+
.btn-primary { background: var(--primary); color: white; }
|
|
68
|
+
.btn-primary:hover { background: var(--primary-dark); }
|
|
69
|
+
.btn-danger { background: var(--danger); color: white; }
|
|
70
|
+
.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; }
|
|
71
|
+
.list-item:last-child { border-bottom: none; }
|
|
72
|
+
.list-item:hover { background: #334155; }
|
|
73
|
+
.meta { display: flex; justify-content: space-between; font-size: 14px; color: var(--text-muted); }
|
|
74
|
+
.subject { font-weight: 600; font-size: 16px; }
|
|
75
|
+
.from { color: #cbd5e1; }
|
|
76
|
+
.badge { background: #475569; padding: 2px 6px; border-radius: 4px; font-size: 12px; }
|
|
77
|
+
.badge-high { background: #dc2626; color: white; }
|
|
78
|
+
.empty { padding: 40px; text-align: center; color: var(--text-muted); }
|
|
79
|
+
`;
|
|
80
|
+
var layout = (title, content) => `
|
|
81
|
+
<!DOCTYPE html>
|
|
82
|
+
<html>
|
|
83
|
+
<head>
|
|
84
|
+
<title>${title} - Gravito Mailbox</title>
|
|
85
|
+
<style>${styles}</style>
|
|
86
|
+
</head>
|
|
87
|
+
<body>
|
|
88
|
+
<div class="container">
|
|
89
|
+
${content}
|
|
90
|
+
</div>
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
// src/dev/ui/mailbox.ts
|
|
96
|
+
function formatAddress(addr) {
|
|
97
|
+
return addr.name ? `${addr.name} <${addr.address}>` : addr.address;
|
|
98
|
+
}
|
|
99
|
+
function timeAgo(date) {
|
|
100
|
+
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
101
|
+
if (seconds < 60) {
|
|
102
|
+
return "Just now";
|
|
103
|
+
}
|
|
104
|
+
const minutes = Math.floor(seconds / 60);
|
|
105
|
+
if (minutes < 60) {
|
|
106
|
+
return `${minutes}m ago`;
|
|
107
|
+
}
|
|
108
|
+
const hours = Math.floor(minutes / 60);
|
|
109
|
+
if (hours < 24) {
|
|
110
|
+
return `${hours}h ago`;
|
|
111
|
+
}
|
|
112
|
+
return date.toLocaleDateString();
|
|
113
|
+
}
|
|
114
|
+
function getMailboxHtml(entries, prefix) {
|
|
115
|
+
const list = entries.length === 0 ? '<div class="empty">No emails found in mailbox.</div>' : entries.map(
|
|
116
|
+
(entry) => `
|
|
117
|
+
<a href="${prefix}/${entry.id}" class="list-item">
|
|
118
|
+
<div class="meta">
|
|
119
|
+
<span class="from">${formatAddress(entry.envelope.from || { address: "Unknown" })}</span>
|
|
120
|
+
<span>${timeAgo(entry.sentAt)}</span>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="subject">
|
|
123
|
+
${entry.envelope.priority === "high" ? '<span class="badge badge-high">High</span> ' : ""}
|
|
124
|
+
${entry.envelope.subject || "(No Subject)"}
|
|
125
|
+
</div>
|
|
126
|
+
<div class="meta" style="margin-top: 4px;">
|
|
127
|
+
To: ${entry.envelope.to?.map((t) => t.address).join(", ")}
|
|
128
|
+
</div>
|
|
129
|
+
</a>
|
|
130
|
+
`
|
|
131
|
+
).join("");
|
|
132
|
+
const content = `
|
|
133
|
+
<div class="header">
|
|
134
|
+
<div class="title">\u{1F4EC} Gravito Mailbox</div>
|
|
135
|
+
${entries.length > 0 ? `<button onclick="clearAll()" class="btn btn-danger">Clear All</button>` : ""}
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="card">
|
|
139
|
+
${list}
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<script>
|
|
143
|
+
async function clearAll() {
|
|
144
|
+
if (!confirm('Clear all emails?')) return;
|
|
145
|
+
await fetch('${prefix}', { method: 'DELETE' });
|
|
146
|
+
window.location.reload();
|
|
147
|
+
}
|
|
148
|
+
</script>
|
|
149
|
+
`;
|
|
150
|
+
return layout("Inbox", content);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/dev/ui/preview.ts
|
|
154
|
+
function getPreviewHtml(entry, prefix) {
|
|
155
|
+
const from = entry.envelope.from ? `${entry.envelope.from.name || ""} <${entry.envelope.from.address}>` : "Unknown";
|
|
156
|
+
const to = entry.envelope.to?.map((t) => t.address).join(", ") || "Unknown";
|
|
157
|
+
const content = `
|
|
158
|
+
<div class="header">
|
|
159
|
+
<div class="title">
|
|
160
|
+
<a href="${prefix}" class="btn">\u2190 Back</a>
|
|
161
|
+
<span style="margin-left: 10px">Email Preview</span>
|
|
162
|
+
</div>
|
|
163
|
+
<button onclick="deleteEmail('${entry.id}')" class="btn btn-danger">Delete</button>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<div class="card" style="margin-bottom: 20px; padding: 20px;">
|
|
167
|
+
<div style="font-size: 18px; font-weight: bold; margin-bottom: 10px;">${entry.envelope.subject || "(No Subject)"}</div>
|
|
168
|
+
<div class="meta" style="margin-bottom: 5px;">From: ${from}</div>
|
|
169
|
+
<div class="meta" style="margin-bottom: 5px;">To: ${to}</div>
|
|
170
|
+
<div class="meta">Date: ${entry.sentAt.toLocaleString()}</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div style="margin-bottom: 10px;">
|
|
174
|
+
<button onclick="setView('html')" id="btn-html" class="btn btn-primary">HTML</button>
|
|
175
|
+
<button onclick="setView('text')" id="btn-text" class="btn">Text</button>
|
|
176
|
+
<button onclick="setView('raw')" id="btn-raw" class="btn">Raw JSON</button>
|
|
177
|
+
<a href="${prefix}/${entry.id}/html" target="_blank" class="btn">Open HTML \u2197</a>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
<div class="card" style="height: 600px; display: flex;">
|
|
181
|
+
<iframe id="preview-frame" src="${prefix}/${entry.id}/html" style="width: 100%; height: 100%; border: none;"></iframe>
|
|
182
|
+
<pre id="raw-view" style="display: none; padding: 20px; overflow: auto; width: 100%;">${JSON.stringify(entry, null, 2)}</pre>
|
|
183
|
+
<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>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<script>
|
|
187
|
+
function setView(mode) {
|
|
188
|
+
document.getElementById('preview-frame').style.display = mode === 'html' ? 'block' : 'none';
|
|
189
|
+
document.getElementById('raw-view').style.display = mode === 'raw' ? 'block' : 'none';
|
|
190
|
+
document.getElementById('text-view').style.display = mode === 'text' ? 'block' : 'none';
|
|
191
|
+
|
|
192
|
+
document.getElementById('btn-html').className = mode === 'html' ? 'btn btn-primary' : 'btn';
|
|
193
|
+
document.getElementById('btn-text').className = mode === 'text' ? 'btn btn-primary' : 'btn';
|
|
194
|
+
document.getElementById('btn-raw').className = mode === 'raw' ? 'btn btn-primary' : 'btn';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function deleteEmail(id) {
|
|
198
|
+
if (!confirm('Delete this email?')) return;
|
|
199
|
+
await fetch('${prefix}/' + id, { method: 'DELETE' });
|
|
200
|
+
window.location.href = '${prefix}';
|
|
201
|
+
}
|
|
202
|
+
</script>
|
|
203
|
+
`;
|
|
204
|
+
return layout(entry.envelope.subject || "Preview", content);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/dev/DevServer.ts
|
|
208
|
+
var DevServer = class {
|
|
209
|
+
constructor(mailbox, base = "/__mail") {
|
|
210
|
+
this.mailbox = mailbox;
|
|
211
|
+
this.base = base;
|
|
212
|
+
}
|
|
213
|
+
register(core) {
|
|
214
|
+
const router = core.router;
|
|
215
|
+
const prefix = this.base.replace(/\/$/, "");
|
|
216
|
+
router.get(prefix, (ctx) => {
|
|
217
|
+
const entries = this.mailbox.list();
|
|
218
|
+
return ctx.html(getMailboxHtml(entries, prefix));
|
|
219
|
+
});
|
|
220
|
+
router.get(`${prefix}/:id`, (ctx) => {
|
|
221
|
+
const id = ctx.req.param("id");
|
|
222
|
+
if (!id) {
|
|
223
|
+
return ctx.text("Bad Request", 400);
|
|
224
|
+
}
|
|
225
|
+
const entry = this.mailbox.get(id);
|
|
226
|
+
if (!entry) {
|
|
227
|
+
return ctx.text("Email not found", 404);
|
|
228
|
+
}
|
|
229
|
+
return ctx.html(getPreviewHtml(entry, prefix));
|
|
230
|
+
});
|
|
231
|
+
router.get(`${prefix}/:id/html`, (ctx) => {
|
|
232
|
+
const id = ctx.req.param("id");
|
|
233
|
+
if (!id) {
|
|
234
|
+
return ctx.text("Bad Request", 400);
|
|
235
|
+
}
|
|
236
|
+
const entry = this.mailbox.get(id);
|
|
237
|
+
if (!entry) {
|
|
238
|
+
return ctx.text("Not found", 404);
|
|
239
|
+
}
|
|
240
|
+
return ctx.html(entry.html);
|
|
241
|
+
});
|
|
242
|
+
router.get(`${prefix}/:id/text`, (ctx) => {
|
|
243
|
+
const id = ctx.req.param("id");
|
|
244
|
+
if (!id) {
|
|
245
|
+
return ctx.text("Bad Request", 400);
|
|
246
|
+
}
|
|
247
|
+
const entry = this.mailbox.get(id);
|
|
248
|
+
if (!entry) {
|
|
249
|
+
return ctx.text("Not found", 404);
|
|
250
|
+
}
|
|
251
|
+
ctx.header("Content-Type", "text/plain; charset=utf-8");
|
|
252
|
+
return ctx.text(entry.text || "No text content", 200);
|
|
253
|
+
});
|
|
254
|
+
router.get(`${prefix}/:id/raw`, (ctx) => {
|
|
255
|
+
const id = ctx.req.param("id");
|
|
256
|
+
if (!id) {
|
|
257
|
+
return ctx.json({ error: "Bad Request" }, 400);
|
|
258
|
+
}
|
|
259
|
+
const entry = this.mailbox.get(id);
|
|
260
|
+
if (!entry) {
|
|
261
|
+
return ctx.json({ error: "Not found" }, 404);
|
|
262
|
+
}
|
|
263
|
+
return ctx.json(entry);
|
|
264
|
+
});
|
|
265
|
+
router.get(`${prefix}/:id/delete`, (ctx) => {
|
|
266
|
+
return ctx.text("Method not allowed", 405);
|
|
267
|
+
});
|
|
268
|
+
router.delete(`${prefix}/:id`, (ctx) => {
|
|
269
|
+
const id = ctx.req.param("id");
|
|
270
|
+
if (!id) {
|
|
271
|
+
return ctx.json({ success: false, error: "Bad Request" }, 400);
|
|
272
|
+
}
|
|
273
|
+
const success = this.mailbox.delete(id);
|
|
274
|
+
return ctx.json({ success });
|
|
275
|
+
});
|
|
276
|
+
router.delete(prefix, (ctx) => {
|
|
277
|
+
this.mailbox.clear();
|
|
278
|
+
return ctx.json({ success: true });
|
|
279
|
+
});
|
|
280
|
+
core.logger.info(`[OrbitSignal] Dev Mailbox available at ${prefix}`);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
// src/transports/LogTransport.ts
|
|
285
|
+
var LogTransport = class {
|
|
286
|
+
async send(message) {
|
|
287
|
+
console.log("\n\u{1F4E7} [OrbitSignal] Email Sent (Simulated):");
|
|
288
|
+
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");
|
|
289
|
+
console.log(
|
|
290
|
+
`From: ${message.from.name ? `${message.from.name} <${message.from.address}>` : message.from.address}`
|
|
291
|
+
);
|
|
292
|
+
console.log(`To: ${message.to.map((t) => t.address).join(", ")}`);
|
|
293
|
+
console.log(`Subject: ${message.subject}`);
|
|
294
|
+
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");
|
|
295
|
+
console.log(`[Content Size]: ${message.html.length} chars (HTML)`);
|
|
296
|
+
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");
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// src/transports/MemoryTransport.ts
|
|
301
|
+
var MemoryTransport = class {
|
|
302
|
+
constructor(mailbox) {
|
|
303
|
+
this.mailbox = mailbox;
|
|
304
|
+
}
|
|
305
|
+
async send(message) {
|
|
306
|
+
this.mailbox.add(message);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
// src/OrbitSignal.ts
|
|
311
|
+
var OrbitSignal = class _OrbitSignal {
|
|
312
|
+
static instance;
|
|
313
|
+
config;
|
|
314
|
+
devMailbox;
|
|
315
|
+
constructor(config = {}) {
|
|
316
|
+
this.config = config;
|
|
317
|
+
_OrbitSignal.instance = this;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get the singleton instance of OrbitSignal
|
|
321
|
+
*
|
|
322
|
+
* @returns The singleton instance of OrbitSignal.
|
|
323
|
+
* @throws {Error} If OrbitSignal has not been initialized.
|
|
324
|
+
*/
|
|
325
|
+
static getInstance() {
|
|
326
|
+
if (!_OrbitSignal.instance) {
|
|
327
|
+
throw new Error("OrbitSignal has not been initialized. Call OrbitSignal.configure() first.");
|
|
328
|
+
}
|
|
329
|
+
return _OrbitSignal.instance;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Configure the OrbitSignal instance
|
|
333
|
+
*
|
|
334
|
+
* @param config - The mail configuration object.
|
|
335
|
+
* @returns A new instance of OrbitSignal.
|
|
336
|
+
*/
|
|
337
|
+
static configure(config) {
|
|
338
|
+
if (!config.transport && !config.devMode) {
|
|
339
|
+
console.warn("[OrbitSignal] No transport provided, falling back to LogTransport");
|
|
340
|
+
config.transport = new LogTransport();
|
|
341
|
+
}
|
|
342
|
+
return new _OrbitSignal(config);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Install the orbit into PlanetCore
|
|
346
|
+
*
|
|
347
|
+
* @param core - The PlanetCore instance.
|
|
348
|
+
*/
|
|
349
|
+
install(core) {
|
|
350
|
+
core.logger.info("[OrbitSignal] Initializing Mail Service (Exposed as: mail)");
|
|
351
|
+
if (!this.config.transport && !this.config.devMode) {
|
|
352
|
+
this.config.transport = new LogTransport();
|
|
353
|
+
}
|
|
354
|
+
if (this.config.devMode) {
|
|
355
|
+
this.devMailbox = new DevMailbox();
|
|
356
|
+
this.config.transport = new MemoryTransport(this.devMailbox);
|
|
357
|
+
core.logger.info("[OrbitSignal] Dev Mode Enabled: Emails will be intercepted to Dev Mailbox");
|
|
358
|
+
const devServer = new DevServer(this.devMailbox, this.config.devUiPrefix || "/__mail");
|
|
359
|
+
devServer.register(core);
|
|
360
|
+
}
|
|
361
|
+
core.adapter.use("*", async (c, next) => {
|
|
362
|
+
c.set("mail", {
|
|
363
|
+
send: (mailable) => this.send(mailable),
|
|
364
|
+
queue: (mailable) => this.queue(mailable)
|
|
365
|
+
});
|
|
366
|
+
await next();
|
|
367
|
+
return void 0;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Send a mailable instance
|
|
372
|
+
*
|
|
373
|
+
* @param mailable - The mailable object to send.
|
|
374
|
+
* @returns A promise that resolves when the email is sent.
|
|
375
|
+
* @throws {Error} If the message is missing "from" or "to" addresses, or if no transport is configured.
|
|
376
|
+
*/
|
|
377
|
+
async send(mailable) {
|
|
378
|
+
const envelope = await mailable.buildEnvelope(this.config);
|
|
379
|
+
if (!envelope.from) {
|
|
380
|
+
throw new Error('Message is missing "from" address');
|
|
381
|
+
}
|
|
382
|
+
if (!envelope.to || envelope.to.length === 0) {
|
|
383
|
+
throw new Error('Message is missing "to" address');
|
|
384
|
+
}
|
|
385
|
+
const content = await mailable.renderContent();
|
|
386
|
+
const message = {
|
|
387
|
+
...envelope,
|
|
388
|
+
from: envelope.from,
|
|
389
|
+
to: envelope.to,
|
|
390
|
+
subject: envelope.subject || "(No Subject)",
|
|
391
|
+
priority: envelope.priority || "normal",
|
|
392
|
+
html: content.html
|
|
393
|
+
};
|
|
394
|
+
if (content.text) {
|
|
395
|
+
message.text = content.text;
|
|
396
|
+
}
|
|
397
|
+
if (!this.config.transport) {
|
|
398
|
+
throw new Error(
|
|
399
|
+
"[OrbitSignal] No transport configured. Did you call configure() or register the orbit?"
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
await this.config.transport.send(message);
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Queue a mailable instance
|
|
406
|
+
*
|
|
407
|
+
* Push a mailable into the queue for execution.
|
|
408
|
+
* Requires OrbitStream to be installed and available in the context.
|
|
409
|
+
*
|
|
410
|
+
* @param mailable - The mailable object to queue.
|
|
411
|
+
* @returns A promise that resolves when the job is pushed to the queue or sent immediately if no queue service is found.
|
|
412
|
+
*/
|
|
413
|
+
async queue(mailable) {
|
|
414
|
+
const queue = this.queueService;
|
|
415
|
+
if (queue) {
|
|
416
|
+
await queue.push(mailable);
|
|
417
|
+
} else {
|
|
418
|
+
console.warn(
|
|
419
|
+
"[OrbitSignal] Queue service not available, sending immediately. Install OrbitStream to enable queuing."
|
|
420
|
+
);
|
|
421
|
+
await this.send(mailable);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
export {
|
|
427
|
+
DevMailbox,
|
|
428
|
+
LogTransport,
|
|
429
|
+
MemoryTransport,
|
|
430
|
+
OrbitSignal
|
|
431
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,16 @@ import { Queueable } from '@gravito/stream';
|
|
|
2
2
|
export { Queueable } from '@gravito/stream';
|
|
3
3
|
import { GravitoOrbit, PlanetCore } from 'gravito-core';
|
|
4
4
|
|
|
5
|
+
declare module 'gravito-core' {
|
|
6
|
+
interface GravitoVariables {
|
|
7
|
+
/** Mail service for sending emails */
|
|
8
|
+
mail?: {
|
|
9
|
+
send: (mailable: any) => Promise<void>;
|
|
10
|
+
queue: (mailable: any) => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
interface Transport {
|
|
6
16
|
/**
|
|
7
17
|
* Send the given message
|
|
@@ -178,18 +188,30 @@ declare class OrbitSignal implements GravitoOrbit {
|
|
|
178
188
|
constructor(config?: MailConfig);
|
|
179
189
|
/**
|
|
180
190
|
* Get the singleton instance of OrbitSignal
|
|
191
|
+
*
|
|
192
|
+
* @returns The singleton instance of OrbitSignal.
|
|
193
|
+
* @throws {Error} If OrbitSignal has not been initialized.
|
|
181
194
|
*/
|
|
182
195
|
static getInstance(): OrbitSignal;
|
|
183
196
|
/**
|
|
184
197
|
* Configure the OrbitSignal instance
|
|
198
|
+
*
|
|
199
|
+
* @param config - The mail configuration object.
|
|
200
|
+
* @returns A new instance of OrbitSignal.
|
|
185
201
|
*/
|
|
186
202
|
static configure(config: MailConfig): OrbitSignal;
|
|
187
203
|
/**
|
|
188
204
|
* Install the orbit into PlanetCore
|
|
205
|
+
*
|
|
206
|
+
* @param core - The PlanetCore instance.
|
|
189
207
|
*/
|
|
190
208
|
install(core: PlanetCore): void;
|
|
191
209
|
/**
|
|
192
210
|
* Send a mailable instance
|
|
211
|
+
*
|
|
212
|
+
* @param mailable - The mailable object to send.
|
|
213
|
+
* @returns A promise that resolves when the email is sent.
|
|
214
|
+
* @throws {Error} If the message is missing "from" or "to" addresses, or if no transport is configured.
|
|
193
215
|
*/
|
|
194
216
|
send(mailable: Mailable): Promise<void>;
|
|
195
217
|
/**
|
|
@@ -197,26 +219,12 @@ declare class OrbitSignal implements GravitoOrbit {
|
|
|
197
219
|
*
|
|
198
220
|
* Push a mailable into the queue for execution.
|
|
199
221
|
* Requires OrbitStream to be installed and available in the context.
|
|
222
|
+
*
|
|
223
|
+
* @param mailable - The mailable object to queue.
|
|
224
|
+
* @returns A promise that resolves when the job is pushed to the queue or sent immediately if no queue service is found.
|
|
200
225
|
*/
|
|
201
226
|
queue(mailable: Mailable): Promise<void>;
|
|
202
227
|
}
|
|
203
|
-
declare module 'hono' {
|
|
204
|
-
interface ContextVariableMap {
|
|
205
|
-
mail: {
|
|
206
|
-
send: (mailable: Mailable) => Promise<void>;
|
|
207
|
-
queue: (mailable: Mailable) => Promise<void>;
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
declare module 'gravito-core' {
|
|
212
|
-
interface GravitoVariables {
|
|
213
|
-
/** Mail service for sending emails */
|
|
214
|
-
mail?: {
|
|
215
|
-
send: (mailable: Mailable) => Promise<void>;
|
|
216
|
-
queue: (mailable: Mailable) => Promise<void>;
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
228
|
|
|
221
229
|
declare class HtmlRenderer implements Renderer {
|
|
222
230
|
private content;
|
|
@@ -226,8 +234,8 @@ declare class HtmlRenderer implements Renderer {
|
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
declare class TemplateRenderer implements Renderer {
|
|
229
|
-
private engine;
|
|
230
237
|
private template;
|
|
238
|
+
private viewsDir;
|
|
231
239
|
constructor(templateName: string, viewsDir?: string);
|
|
232
240
|
render(data: Record<string, unknown>): Promise<RenderResult>;
|
|
233
241
|
private stripHtml;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,16 @@ import { Queueable } from '@gravito/stream';
|
|
|
2
2
|
export { Queueable } from '@gravito/stream';
|
|
3
3
|
import { GravitoOrbit, PlanetCore } from 'gravito-core';
|
|
4
4
|
|
|
5
|
+
declare module 'gravito-core' {
|
|
6
|
+
interface GravitoVariables {
|
|
7
|
+
/** Mail service for sending emails */
|
|
8
|
+
mail?: {
|
|
9
|
+
send: (mailable: any) => Promise<void>;
|
|
10
|
+
queue: (mailable: any) => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
interface Transport {
|
|
6
16
|
/**
|
|
7
17
|
* Send the given message
|
|
@@ -178,18 +188,30 @@ declare class OrbitSignal implements GravitoOrbit {
|
|
|
178
188
|
constructor(config?: MailConfig);
|
|
179
189
|
/**
|
|
180
190
|
* Get the singleton instance of OrbitSignal
|
|
191
|
+
*
|
|
192
|
+
* @returns The singleton instance of OrbitSignal.
|
|
193
|
+
* @throws {Error} If OrbitSignal has not been initialized.
|
|
181
194
|
*/
|
|
182
195
|
static getInstance(): OrbitSignal;
|
|
183
196
|
/**
|
|
184
197
|
* Configure the OrbitSignal instance
|
|
198
|
+
*
|
|
199
|
+
* @param config - The mail configuration object.
|
|
200
|
+
* @returns A new instance of OrbitSignal.
|
|
185
201
|
*/
|
|
186
202
|
static configure(config: MailConfig): OrbitSignal;
|
|
187
203
|
/**
|
|
188
204
|
* Install the orbit into PlanetCore
|
|
205
|
+
*
|
|
206
|
+
* @param core - The PlanetCore instance.
|
|
189
207
|
*/
|
|
190
208
|
install(core: PlanetCore): void;
|
|
191
209
|
/**
|
|
192
210
|
* Send a mailable instance
|
|
211
|
+
*
|
|
212
|
+
* @param mailable - The mailable object to send.
|
|
213
|
+
* @returns A promise that resolves when the email is sent.
|
|
214
|
+
* @throws {Error} If the message is missing "from" or "to" addresses, or if no transport is configured.
|
|
193
215
|
*/
|
|
194
216
|
send(mailable: Mailable): Promise<void>;
|
|
195
217
|
/**
|
|
@@ -197,26 +219,12 @@ declare class OrbitSignal implements GravitoOrbit {
|
|
|
197
219
|
*
|
|
198
220
|
* Push a mailable into the queue for execution.
|
|
199
221
|
* Requires OrbitStream to be installed and available in the context.
|
|
222
|
+
*
|
|
223
|
+
* @param mailable - The mailable object to queue.
|
|
224
|
+
* @returns A promise that resolves when the job is pushed to the queue or sent immediately if no queue service is found.
|
|
200
225
|
*/
|
|
201
226
|
queue(mailable: Mailable): Promise<void>;
|
|
202
227
|
}
|
|
203
|
-
declare module 'hono' {
|
|
204
|
-
interface ContextVariableMap {
|
|
205
|
-
mail: {
|
|
206
|
-
send: (mailable: Mailable) => Promise<void>;
|
|
207
|
-
queue: (mailable: Mailable) => Promise<void>;
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
declare module 'gravito-core' {
|
|
212
|
-
interface GravitoVariables {
|
|
213
|
-
/** Mail service for sending emails */
|
|
214
|
-
mail?: {
|
|
215
|
-
send: (mailable: Mailable) => Promise<void>;
|
|
216
|
-
queue: (mailable: Mailable) => Promise<void>;
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
228
|
|
|
221
229
|
declare class HtmlRenderer implements Renderer {
|
|
222
230
|
private content;
|
|
@@ -226,8 +234,8 @@ declare class HtmlRenderer implements Renderer {
|
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
declare class TemplateRenderer implements Renderer {
|
|
229
|
-
private engine;
|
|
230
237
|
private template;
|
|
238
|
+
private viewsDir;
|
|
231
239
|
constructor(templateName: string, viewsDir?: string);
|
|
232
240
|
render(data: Record<string, unknown>): Promise<RenderResult>;
|
|
233
241
|
private stripHtml;
|