@gravito/signal 3.0.1 → 3.0.4
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/CHANGELOG.md +30 -0
- package/README.md +89 -60
- package/README.zh-TW.md +140 -9
- package/dist/MjmlRenderer-IUH663FT.mjs +8 -0
- package/dist/ReactMjmlRenderer-C3P5YO5L.mjs +8 -0
- package/dist/ReactRenderer-2JFLRVST.mjs +45 -0
- package/dist/{ReactRenderer-L5INVYKT.mjs → ReactRenderer-LYEOSYFS.mjs} +9 -8
- package/dist/ReactRenderer-V54CUUEI.mjs +45 -0
- package/dist/VueMjmlRenderer-4F4CXHDB.mjs +8 -0
- package/dist/VueMjmlRenderer-5WZR4CQG.mjs +8 -0
- package/dist/VueMjmlRenderer-U5YMWI44.mjs +8 -0
- package/dist/VueRenderer-3YBRQXME.mjs +48 -0
- package/dist/VueRenderer-46JGXTJ2.mjs +48 -0
- package/dist/VueRenderer-5KWD4R3C.mjs +48 -0
- package/dist/VueRenderer-C23U4O5E.mjs +48 -0
- package/dist/VueRenderer-LEVDFLHP.mjs +31 -0
- package/dist/VueRenderer-RNHSCCRI.mjs +48 -0
- package/dist/chunk-3WOR3XSL.mjs +82 -0
- package/dist/chunk-DBFIVHHG.mjs +79 -0
- package/dist/{chunk-6DZX6EAA.mjs → chunk-HEBXNMVQ.mjs} +12 -1
- package/dist/chunk-KB7IDDBT.mjs +82 -0
- package/dist/chunk-LZL5UUPC.mjs +82 -0
- package/dist/chunk-W6LXIJKK.mjs +57 -0
- package/dist/chunk-XBIVBJS2.mjs +8 -0
- package/dist/index.d.mts +1680 -209
- package/dist/index.d.ts +1680 -209
- package/dist/index.js +69405 -542
- package/dist/index.mjs +993 -110
- package/dist/lib-HJTRWKU5.mjs +67788 -0
- package/dist/{VueRenderer-Z5PRVBNH.mjs → server-renderer-4IM3P5XZ.mjs} +308 -423
- package/dist/server-renderer-7KWFSTPV.mjs +37193 -0
- package/dist/{VueRenderer-S65ZARRI.mjs → server-renderer-S5FPSTJ2.mjs} +931 -877
- package/dist/server-renderer-X5LUFVWT.mjs +37193 -0
- package/doc/OPTIMIZATION_PLAN.md +496 -0
- package/package.json +14 -12
- package/scripts/check-coverage.ts +64 -0
- package/src/Mailable.ts +340 -44
- package/src/OrbitSignal.ts +350 -50
- package/src/TypedMailable.ts +96 -0
- package/src/dev/DevMailbox.ts +89 -33
- package/src/dev/DevServer.ts +14 -14
- package/src/dev/storage/FileMailboxStorage.ts +66 -0
- package/src/dev/storage/MailboxStorage.ts +15 -0
- package/src/dev/storage/MemoryMailboxStorage.ts +36 -0
- package/src/dev/ui/mailbox.ts +1 -1
- package/src/dev/ui/preview.ts +4 -4
- package/src/errors.ts +69 -0
- package/src/events.ts +72 -0
- package/src/index.ts +20 -1
- package/src/renderers/HtmlRenderer.ts +20 -18
- package/src/renderers/MjmlRenderer.ts +73 -0
- package/src/renderers/ReactMjmlRenderer.ts +94 -0
- package/src/renderers/ReactRenderer.ts +26 -21
- package/src/renderers/Renderer.ts +43 -3
- package/src/renderers/TemplateRenderer.ts +48 -15
- package/src/renderers/VueMjmlRenderer.ts +99 -0
- package/src/renderers/VueRenderer.ts +26 -21
- package/src/renderers/mjml-templates.ts +50 -0
- package/src/transports/BaseTransport.ts +148 -0
- package/src/transports/LogTransport.ts +28 -6
- package/src/transports/MemoryTransport.ts +34 -6
- package/src/transports/SesTransport.ts +62 -17
- package/src/transports/SmtpTransport.ts +123 -27
- package/src/transports/Transport.ts +33 -4
- package/src/types.ts +172 -3
- package/src/utils/html.ts +43 -0
- package/src/webhooks/SendGridWebhookDriver.ts +80 -0
- package/src/webhooks/SesWebhookDriver.ts +44 -0
- package/tests/DevMailbox.test.ts +54 -0
- package/tests/FileMailboxStorage.test.ts +56 -0
- package/tests/MjmlLayout.test.ts +28 -0
- package/tests/MjmlRenderer.test.ts +53 -0
- package/tests/OrbitSignalWebhook.test.ts +56 -0
- package/tests/ReactMjmlRenderer.test.ts +33 -0
- package/tests/SendGridWebhookDriver.test.ts +69 -0
- package/tests/SesWebhookDriver.test.ts +46 -0
- package/tests/VueMjmlRenderer.test.ts +35 -0
- package/tests/dev-server.test.ts +1 -1
- package/tests/transports.test.ts +3 -3
- package/tsconfig.json +12 -24
- package/dist/OrbitMail-2Z7ZTKYA.mjs +0 -7
- package/dist/OrbitMail-BGV32HWN.mjs +0 -7
- package/dist/OrbitMail-FUYZQSAV.mjs +0 -7
- package/dist/OrbitMail-NAPCRK7B.mjs +0 -7
- package/dist/OrbitMail-REGJ276B.mjs +0 -7
- package/dist/OrbitMail-TCFBJWDT.mjs +0 -7
- package/dist/OrbitMail-XZZW6U4N.mjs +0 -7
- package/dist/OrbitSignal-IPSA2CDO.mjs +0 -7
- package/dist/OrbitSignal-MABW4DDW.mjs +0 -7
- package/dist/OrbitSignal-QSW5VQ5M.mjs +0 -7
- package/dist/OrbitSignal-R22QHWAA.mjs +0 -7
- package/dist/OrbitSignal-ZKKMEC27.mjs +0 -7
- package/dist/chunk-3U2CYJO5.mjs +0 -367
- package/dist/chunk-3XFC4T6M.mjs +0 -392
- package/dist/chunk-456QRYFW.mjs +0 -401
- package/dist/chunk-DT3R2TNV.mjs +0 -367
- package/dist/chunk-F6MVTUCT.mjs +0 -421
- package/dist/chunk-GADWIVC4.mjs +0 -400
- package/dist/chunk-HHKFAMSE.mjs +0 -380
- package/dist/chunk-NEQCQSZI.mjs +0 -406
- package/dist/chunk-OKRNL6PN.mjs +0 -400
- package/dist/chunk-ULN3GMY2.mjs +0 -367
- package/dist/chunk-XAWO7RSP.mjs +0 -398
- package/dist/chunk-YLVDJSED.mjs +0 -431
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @gravito/signal
|
|
2
2
|
|
|
3
|
+
## 3.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Convert all workspace:\* dependencies to version numbers for npm publishing
|
|
8
|
+
|
|
9
|
+
- Fixed 144 workspace:\* dependencies across 58 packages
|
|
10
|
+
- Ensures all packages work properly when installed from npm
|
|
11
|
+
- Resolves issues with bunx and npm installation of CLI tools
|
|
12
|
+
- All internal dependencies now use explicit version constraints
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @gravito/core@1.6.1
|
|
16
|
+
- @gravito/prism@3.1.1
|
|
17
|
+
- @gravito/stream@2.0.2
|
|
18
|
+
|
|
19
|
+
## 3.0.3
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [6234dab]
|
|
24
|
+
- @gravito/prism@3.0.2
|
|
25
|
+
|
|
26
|
+
## 3.0.2
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [905588f]
|
|
31
|
+
- @gravito/stream@2.0.1
|
|
32
|
+
|
|
3
33
|
## 3.0.1
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,42 +1,58 @@
|
|
|
1
|
+
# @gravito/signal 🛰️
|
|
1
2
|
|
|
2
|
-
|
|
3
|
+
`@gravito/signal` is the powerful, multi-driver email framework for the Gravito ecosystem. It provides a clean, fluent API for building and sending emails with support for multiple rendering engines and transport drivers.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
## 🌟 Features
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
- **
|
|
9
|
-
- **Content Renderers**:
|
|
7
|
+
- **Fluent API**: Expressive `Mailable` classes for building email messages.
|
|
8
|
+
- **Multi-Driver Transport**: Support for SMTP (Nodemailer), AWS SES, Log (console), and Memory.
|
|
9
|
+
- **Flexible Rendering**: Render email content using:
|
|
10
10
|
- Raw HTML
|
|
11
|
-
-
|
|
12
|
-
- React Components (
|
|
13
|
-
- Vue Components (
|
|
14
|
-
- **Development
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
- **Prism** (Edge-optimized view engine)
|
|
12
|
+
- **React** Components (via `react-dom/server`)
|
|
13
|
+
- **Vue** Components (via `@vue/server-renderer`)
|
|
14
|
+
- **Development Experience**:
|
|
15
|
+
- **Dev Mode**: Intercept emails locally and view them in a built-in UI.
|
|
16
|
+
- **Mailbox UI**: Access intercepted emails at `/__mail` during development.
|
|
17
|
+
- **Queue Integration**: Built-in support for asynchronous email sending via `@gravito/stream`.
|
|
18
|
+
- **Internationalization**: Integrated I18n support for localized email content.
|
|
19
|
+
- **Type-Safe**: Written in TypeScript with full type safety for configuration and usage.
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
19
22
|
|
|
20
23
|
```bash
|
|
21
24
|
bun add @gravito/signal
|
|
22
25
|
```
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
### Optional Dependencies
|
|
28
|
+
|
|
29
|
+
Depending on your transport or renderer choice, you may need additional packages:
|
|
30
|
+
|
|
25
31
|
```bash
|
|
32
|
+
# For AWS SES
|
|
26
33
|
bun add @aws-sdk/client-ses
|
|
34
|
+
|
|
35
|
+
# For React components
|
|
36
|
+
bun add react react-dom
|
|
37
|
+
|
|
38
|
+
# For Vue components
|
|
39
|
+
bun add vue @vue/server-renderer
|
|
27
40
|
```
|
|
28
41
|
|
|
29
|
-
##
|
|
42
|
+
## 🚀 Quick Start
|
|
30
43
|
|
|
31
|
-
###
|
|
44
|
+
### 1. Configure the Orbit
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
Register `OrbitSignal` in your Gravito application:
|
|
34
47
|
|
|
35
48
|
```typescript
|
|
49
|
+
import { PlanetCore } from '@gravito/core';
|
|
36
50
|
import { OrbitSignal, SmtpTransport } from '@gravito/signal';
|
|
37
51
|
|
|
38
|
-
const
|
|
39
|
-
|
|
52
|
+
const core = new PlanetCore();
|
|
53
|
+
|
|
54
|
+
const mail = new OrbitSignal({
|
|
55
|
+
from: { name: 'Gravito Support', address: 'support@example.com' },
|
|
40
56
|
transport: new SmtpTransport({
|
|
41
57
|
host: 'smtp.mailtrap.io',
|
|
42
58
|
port: 2525,
|
|
@@ -45,19 +61,18 @@ const mail = OrbitSignal.configure({
|
|
|
45
61
|
devMode: process.env.NODE_ENV === 'development',
|
|
46
62
|
});
|
|
47
63
|
|
|
48
|
-
// Install into PlanetCore
|
|
49
64
|
mail.install(core);
|
|
50
65
|
```
|
|
51
66
|
|
|
52
|
-
###
|
|
67
|
+
### 2. Create a Mailable
|
|
53
68
|
|
|
54
|
-
Extend the `Mailable` class to
|
|
69
|
+
Extend the `Mailable` class to define your email:
|
|
55
70
|
|
|
56
71
|
```typescript
|
|
57
72
|
import { Mailable } from '@gravito/signal';
|
|
58
73
|
|
|
59
74
|
export class WelcomeEmail extends Mailable {
|
|
60
|
-
constructor(private user:
|
|
75
|
+
constructor(private user: { name: string; email: string }) {
|
|
61
76
|
super();
|
|
62
77
|
}
|
|
63
78
|
|
|
@@ -70,60 +85,74 @@ export class WelcomeEmail extends Mailable {
|
|
|
70
85
|
}
|
|
71
86
|
```
|
|
72
87
|
|
|
73
|
-
###
|
|
88
|
+
### 3. Send the Email
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
import { WelcomeEmail } from './mail/WelcomeEmail';
|
|
90
|
+
Access the mail service via the Gravito context:
|
|
77
91
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
92
|
+
```typescript
|
|
93
|
+
// In your route handler
|
|
94
|
+
const mail = c.get('mail');
|
|
95
|
+
await mail.send(new WelcomeEmail(user));
|
|
81
96
|
```
|
|
82
97
|
|
|
83
|
-
|
|
98
|
+
## 🛠️ Advanced Usage
|
|
99
|
+
|
|
100
|
+
### React & Vue Rendering
|
|
84
101
|
|
|
85
|
-
|
|
102
|
+
You can use modern frontend frameworks to design your emails:
|
|
86
103
|
|
|
87
104
|
```typescript
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
105
|
+
// React example
|
|
106
|
+
export class MonthlyReport extends Mailable {
|
|
107
|
+
build() {
|
|
108
|
+
return this
|
|
109
|
+
.subject('Your Monthly Report')
|
|
110
|
+
.react(ReportComponent, { data: this.data });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
91
113
|
|
|
92
|
-
//
|
|
93
|
-
|
|
114
|
+
// Vue example
|
|
115
|
+
export class InvoiceEmail extends Mailable {
|
|
116
|
+
build() {
|
|
117
|
+
return this
|
|
118
|
+
.subject('Invoice #12345')
|
|
119
|
+
.vue(InvoiceTemplate, { total: 100 });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
94
122
|
```
|
|
95
123
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
### SMTP
|
|
99
|
-
Standard SMTP transport using `nodemailer`.
|
|
124
|
+
### Queueing Emails
|
|
100
125
|
|
|
101
|
-
|
|
102
|
-
Send via Amazon SES API.
|
|
126
|
+
For better performance, send emails asynchronously:
|
|
103
127
|
|
|
104
128
|
```typescript
|
|
105
|
-
|
|
129
|
+
const email = new WelcomeEmail(user)
|
|
130
|
+
.onQueue('notifications')
|
|
131
|
+
.delay(60); // Send after 60 seconds
|
|
106
132
|
|
|
107
|
-
|
|
108
|
-
region: 'us-east-1',
|
|
109
|
-
accessKeyId: '...', // Optional if using environment variables
|
|
110
|
-
secretAccessKey: '...'
|
|
111
|
-
});
|
|
133
|
+
await email.queue();
|
|
112
134
|
```
|
|
113
135
|
|
|
114
|
-
###
|
|
115
|
-
|
|
136
|
+
### Development Mailbox
|
|
137
|
+
|
|
138
|
+
When `devMode` is enabled, `OrbitSignal` intercepts all outgoing emails and stores them in memory. You can view them by navigating to `/__mail` (or your configured `devUiPrefix`) in your browser. This UI provides:
|
|
139
|
+
- A list of all intercepted emails.
|
|
140
|
+
- Preview of HTML and Plain Text content.
|
|
141
|
+
- Metadata view (Subject, To, From, etc.).
|
|
116
142
|
|
|
117
|
-
|
|
118
|
-
Stores emails in memory (used by Dev Mode).
|
|
143
|
+
## 🔧 Configuration Options
|
|
119
144
|
|
|
120
|
-
|
|
145
|
+
The `MailConfig` object supports the following options:
|
|
121
146
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
147
|
+
| Option | Type | Description |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `from` | `Address` | Default sender address. |
|
|
150
|
+
| `transport` | `Transport` | The transport driver to use. |
|
|
151
|
+
| `devMode` | `boolean` | Enable/disable email interception. |
|
|
152
|
+
| `viewsDir` | `string` | Path to template directory. |
|
|
153
|
+
| `devUiPrefix`| `string` | URL prefix for Dev UI (default: `/__mail`). |
|
|
154
|
+
| `translator` | `Function` | I18n translation function. |
|
|
126
155
|
|
|
127
|
-
## License
|
|
156
|
+
## 📄 License
|
|
128
157
|
|
|
129
|
-
MIT
|
|
158
|
+
MIT © Carl Lee
|
package/README.zh-TW.md
CHANGED
|
@@ -1,27 +1,158 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @gravito/signal 🛰️
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@gravito/signal` 是 Gravito 生態系統中功能強大且支援多種驅動程式的電子郵件框架。它提供了一個簡潔、流暢的 API 來構建和發送電子郵件,並支援多種渲染引擎和傳輸驅動程式。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 🌟 特性
|
|
6
|
+
|
|
7
|
+
- **流暢的 API**:使用具表現力的 `Mailable` 類別來構建電子郵件內容。
|
|
8
|
+
- **多驅動傳輸**:支援 SMTP (Nodemailer)、AWS SES、Log (控制台日誌) 和 Memory (記憶體)。
|
|
9
|
+
- **靈活的渲染引擎**:支援使用以下方式渲染郵件內容:
|
|
10
|
+
- 原生 HTML 字串
|
|
11
|
+
- **Prism** (Edge 優化的模板引擎)
|
|
12
|
+
- **React** 組件 (透過 `react-dom/server`)
|
|
13
|
+
- **Vue** 組件 (透過 `@vue/server-renderer`)
|
|
14
|
+
- **開發體驗優化**:
|
|
15
|
+
- **開發模式 (Dev Mode)**:在本地開發時攔截電子郵件,而不實際發送。
|
|
16
|
+
- **信箱 UI (Mailbox UI)**:在開發期間透過 `/__mail` 存取攔截到的郵件預覽界面。
|
|
17
|
+
- **隊列整合**:內建支援透過 `@gravito/stream` 進行異步郵件發送。
|
|
18
|
+
- **國際化 (I18n)**:整合多語系支援,輕鬆發送在地化郵件。
|
|
19
|
+
- **類型安全**:完全使用 TypeScript 編寫,提供完善的配置與使用類型定義。
|
|
20
|
+
|
|
21
|
+
## 📦 安裝
|
|
6
22
|
|
|
7
23
|
```bash
|
|
8
24
|
bun add @gravito/signal
|
|
9
25
|
```
|
|
10
26
|
|
|
11
|
-
|
|
27
|
+
### 選用依賴
|
|
28
|
+
|
|
29
|
+
根據您選擇的傳輸方式或渲染引擎,您可能需要安裝額外的套件:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 若使用 AWS SES
|
|
33
|
+
bun add @aws-sdk/client-ses
|
|
34
|
+
|
|
35
|
+
# 若使用 React 組件
|
|
36
|
+
bun add react react-dom
|
|
37
|
+
|
|
38
|
+
# 若使用 Vue 組件
|
|
39
|
+
bun add vue @vue/server-renderer
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 🚀 快速上手
|
|
43
|
+
|
|
44
|
+
### 1. 配置 Orbit
|
|
45
|
+
|
|
46
|
+
在您的 Gravito 應用程式中註冊 `OrbitSignal`:
|
|
12
47
|
|
|
13
48
|
```typescript
|
|
14
|
-
import {
|
|
49
|
+
import { PlanetCore } from '@gravito/core';
|
|
50
|
+
import { OrbitSignal, SmtpTransport } from '@gravito/signal';
|
|
15
51
|
|
|
16
|
-
const
|
|
17
|
-
|
|
52
|
+
const core = new PlanetCore();
|
|
53
|
+
|
|
54
|
+
const mail = new OrbitSignal({
|
|
55
|
+
from: { name: 'Gravito 支援團隊', address: 'support@example.com' },
|
|
18
56
|
transport: new SmtpTransport({
|
|
19
57
|
host: 'smtp.mailtrap.io',
|
|
20
58
|
port: 2525,
|
|
21
59
|
auth: { user: '...', pass: '...' }
|
|
22
60
|
}),
|
|
23
61
|
devMode: process.env.NODE_ENV === 'development',
|
|
24
|
-
})
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
mail.install(core);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. 建立 Mailable
|
|
68
|
+
|
|
69
|
+
繼承 `Mailable` 類別來定義您的郵件內容:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Mailable } from '@gravito/signal';
|
|
73
|
+
|
|
74
|
+
export class WelcomeEmail extends Mailable {
|
|
75
|
+
constructor(private user: { name: string; email: string }) {
|
|
76
|
+
super();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
build() {
|
|
80
|
+
return this
|
|
81
|
+
.to(this.user.email)
|
|
82
|
+
.subject('歡迎來到 Gravito!')
|
|
83
|
+
.view('emails/welcome', { name: this.user.name });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 3. 發送郵件
|
|
25
89
|
|
|
26
|
-
|
|
90
|
+
透過 Gravito Context 存取郵件服務:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// 在路由處理器中
|
|
94
|
+
const mail = c.get('mail');
|
|
95
|
+
await mail.send(new WelcomeEmail(user));
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 🛠️ 進階用法
|
|
99
|
+
|
|
100
|
+
### 使用 React 或 Vue 渲染
|
|
101
|
+
|
|
102
|
+
您可以使用現代前端框架來設計您的郵件:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// React 範例
|
|
106
|
+
export class MonthlyReport extends Mailable {
|
|
107
|
+
build() {
|
|
108
|
+
return this
|
|
109
|
+
.subject('您的每月報表')
|
|
110
|
+
.react(ReportComponent, { data: this.data });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Vue 範例
|
|
115
|
+
export class InvoiceEmail extends Mailable {
|
|
116
|
+
build() {
|
|
117
|
+
return this
|
|
118
|
+
.subject('發票單號 #12345')
|
|
119
|
+
.vue(InvoiceTemplate, { total: 100 });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 隊列發送 (Queueing)
|
|
125
|
+
|
|
126
|
+
為了提升應用程式效能,建議使用異步隊列發送郵件:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const email = new WelcomeEmail(user)
|
|
130
|
+
.onQueue('notifications')
|
|
131
|
+
.delay(60); // 60 秒後發送
|
|
132
|
+
|
|
133
|
+
await email.queue();
|
|
27
134
|
```
|
|
135
|
+
|
|
136
|
+
### 開發者信箱 (Dev Mailbox)
|
|
137
|
+
|
|
138
|
+
當啟用 `devMode` 時,`OrbitSignal` 會攔截所有外發郵件並將其存儲在記憶體中。您可以透過瀏覽器訪問 `/__mail` (或您配置的 `devUiPrefix`) 來查看。此界面提供:
|
|
139
|
+
- 所有已攔截郵件的列表。
|
|
140
|
+
- HTML 與純文字內容預覽。
|
|
141
|
+
- 中繼資料查看 (主旨、收件者、寄件者等)。
|
|
142
|
+
|
|
143
|
+
## 🔧 配置選項
|
|
144
|
+
|
|
145
|
+
`MailConfig` 物件支援以下選項:
|
|
146
|
+
|
|
147
|
+
| 選項 | 類型 | 描述 |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `from` | `Address` | 預設寄件者地址。 |
|
|
150
|
+
| `transport` | `Transport` | 使用的傳輸驅動程式。 |
|
|
151
|
+
| `devMode` | `boolean` | 是否啟用郵件攔截開發模式。 |
|
|
152
|
+
| `viewsDir` | `string` | 模板檔案存放目錄。 |
|
|
153
|
+
| `devUiPrefix`| `string` | 開發界面 URL 前綴 (預設: `/__mail`)。 |
|
|
154
|
+
| `translator` | `Function` | I18n 翻譯函數。 |
|
|
155
|
+
|
|
156
|
+
## 📄 授權
|
|
157
|
+
|
|
158
|
+
MIT © Carl Lee
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stripHtml
|
|
3
|
+
} from "./chunk-XBIVBJS2.mjs";
|
|
4
|
+
import "./chunk-EBO3CZXG.mjs";
|
|
5
|
+
|
|
6
|
+
// src/renderers/ReactRenderer.ts
|
|
7
|
+
var ReactRenderer = class {
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of ReactRenderer.
|
|
10
|
+
*
|
|
11
|
+
* @param component - The React component to render.
|
|
12
|
+
* @param props - Initial props for the component.
|
|
13
|
+
* @param deps - Optional dependency injection for testing.
|
|
14
|
+
*/
|
|
15
|
+
constructor(component, props, deps = {}) {
|
|
16
|
+
this.component = component;
|
|
17
|
+
this.props = props;
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders the React component to a static HTML string.
|
|
22
|
+
*
|
|
23
|
+
* This method performs dynamic imports of `react` and `react-dom/server`
|
|
24
|
+
* to ensure they are only loaded if this renderer is actually used.
|
|
25
|
+
*
|
|
26
|
+
* @param data - Runtime data to be merged with initial props.
|
|
27
|
+
* @returns A promise resolving to the rendered content.
|
|
28
|
+
* @throws {Error} If React dependencies cannot be loaded or rendering fails.
|
|
29
|
+
*/
|
|
30
|
+
async render(data) {
|
|
31
|
+
const createElement = this.deps.createElement ?? (await import("react")).createElement;
|
|
32
|
+
const renderToStaticMarkup = this.deps.renderToStaticMarkup ?? (await import("react-dom/server")).renderToStaticMarkup;
|
|
33
|
+
const mergedProps = { ...this.props, ...data };
|
|
34
|
+
const element = createElement(this.component, mergedProps);
|
|
35
|
+
const html = renderToStaticMarkup(element);
|
|
36
|
+
const fullHtml = html.startsWith("<!DOCTYPE") ? html : `<!DOCTYPE html>${html}`;
|
|
37
|
+
return {
|
|
38
|
+
html: fullHtml,
|
|
39
|
+
text: stripHtml(html)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
ReactRenderer
|
|
45
|
+
};
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
stripHtml
|
|
3
|
+
} from "./chunk-XBIVBJS2.mjs";
|
|
4
|
+
import "./chunk-EBO3CZXG.mjs";
|
|
2
5
|
|
|
3
6
|
// src/renderers/ReactRenderer.ts
|
|
4
|
-
import { createElement } from "react";
|
|
5
|
-
import { renderToStaticMarkup } from "react-dom/server";
|
|
6
7
|
var ReactRenderer = class {
|
|
7
|
-
constructor(component, props) {
|
|
8
|
+
constructor(component, props, deps = {}) {
|
|
8
9
|
this.component = component;
|
|
9
10
|
this.props = props;
|
|
11
|
+
this.deps = deps;
|
|
10
12
|
}
|
|
11
13
|
async render(data) {
|
|
14
|
+
const createElement = this.deps.createElement ?? (await import("react")).createElement;
|
|
15
|
+
const renderToStaticMarkup = this.deps.renderToStaticMarkup ?? (await import("react-dom/server")).renderToStaticMarkup;
|
|
12
16
|
const mergedProps = { ...this.props, ...data };
|
|
13
17
|
const element = createElement(this.component, mergedProps);
|
|
14
18
|
const html = renderToStaticMarkup(element);
|
|
15
19
|
const fullHtml = html.startsWith("<!DOCTYPE") ? html : `<!DOCTYPE html>${html}`;
|
|
16
20
|
return {
|
|
17
21
|
html: fullHtml,
|
|
18
|
-
text:
|
|
22
|
+
text: stripHtml(html)
|
|
19
23
|
};
|
|
20
24
|
}
|
|
21
|
-
stripHtml(html) {
|
|
22
|
-
return html.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<[^>]+>/g, "").replace(/ /g, " ").replace(/\s+/g, " ").trim();
|
|
23
|
-
}
|
|
24
25
|
};
|
|
25
26
|
export {
|
|
26
27
|
ReactRenderer
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stripHtml
|
|
3
|
+
} from "./chunk-XBIVBJS2.mjs";
|
|
4
|
+
import "./chunk-HEBXNMVQ.mjs";
|
|
5
|
+
|
|
6
|
+
// src/renderers/ReactRenderer.ts
|
|
7
|
+
var ReactRenderer = class {
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of ReactRenderer.
|
|
10
|
+
*
|
|
11
|
+
* @param component - The React component to render.
|
|
12
|
+
* @param props - Initial props for the component.
|
|
13
|
+
* @param deps - Optional dependency injection for testing.
|
|
14
|
+
*/
|
|
15
|
+
constructor(component, props, deps = {}) {
|
|
16
|
+
this.component = component;
|
|
17
|
+
this.props = props;
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders the React component to a static HTML string.
|
|
22
|
+
*
|
|
23
|
+
* This method performs dynamic imports of `react` and `react-dom/server`
|
|
24
|
+
* to ensure they are only loaded if this renderer is actually used.
|
|
25
|
+
*
|
|
26
|
+
* @param data - Runtime data to be merged with initial props.
|
|
27
|
+
* @returns A promise resolving to the rendered content.
|
|
28
|
+
* @throws {Error} If React dependencies cannot be loaded or rendering fails.
|
|
29
|
+
*/
|
|
30
|
+
async render(data) {
|
|
31
|
+
const createElement = this.deps.createElement ?? (await import("react")).createElement;
|
|
32
|
+
const renderToStaticMarkup = this.deps.renderToStaticMarkup ?? (await import("react-dom/server")).renderToStaticMarkup;
|
|
33
|
+
const mergedProps = { ...this.props, ...data };
|
|
34
|
+
const element = createElement(this.component, mergedProps);
|
|
35
|
+
const html = renderToStaticMarkup(element);
|
|
36
|
+
const fullHtml = html.startsWith("<!DOCTYPE") ? html : `<!DOCTYPE html>${html}`;
|
|
37
|
+
return {
|
|
38
|
+
html: fullHtml,
|
|
39
|
+
text: stripHtml(html)
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
ReactRenderer
|
|
45
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stripHtml
|
|
3
|
+
} from "./chunk-XBIVBJS2.mjs";
|
|
4
|
+
import "./chunk-HEBXNMVQ.mjs";
|
|
5
|
+
|
|
6
|
+
// src/renderers/VueRenderer.ts
|
|
7
|
+
var VueRenderer = class {
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of VueRenderer.
|
|
10
|
+
*
|
|
11
|
+
* @param component - The Vue component to render.
|
|
12
|
+
* @param props - Initial props for the component.
|
|
13
|
+
* @param deps - Optional dependency injection for testing.
|
|
14
|
+
*/
|
|
15
|
+
constructor(component, props, deps = {}) {
|
|
16
|
+
this.component = component;
|
|
17
|
+
this.props = props;
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders the Vue component to a static HTML string.
|
|
22
|
+
*
|
|
23
|
+
* This method performs dynamic imports of `vue` and `@vue/server-renderer`
|
|
24
|
+
* to ensure they are only loaded if this renderer is actually used.
|
|
25
|
+
*
|
|
26
|
+
* @param data - Runtime data to be merged with initial props.
|
|
27
|
+
* @returns A promise resolving to the rendered content.
|
|
28
|
+
* @throws {Error} If Vue dependencies cannot be loaded or rendering fails.
|
|
29
|
+
*/
|
|
30
|
+
async render(data) {
|
|
31
|
+
const createSSRApp = this.deps.createSSRApp ?? (await import("vue")).createSSRApp;
|
|
32
|
+
const h = this.deps.h ?? (await import("vue")).h;
|
|
33
|
+
const renderToString = this.deps.renderToString ?? (await import("./server-renderer-7KWFSTPV.mjs")).renderToString;
|
|
34
|
+
const mergedProps = { ...this.props, ...data };
|
|
35
|
+
const app = createSSRApp({
|
|
36
|
+
render: () => h(this.component, mergedProps)
|
|
37
|
+
});
|
|
38
|
+
const html = await renderToString(app);
|
|
39
|
+
const fullHtml = html.startsWith("<!DOCTYPE") ? html : `<!DOCTYPE html>${html}`;
|
|
40
|
+
return {
|
|
41
|
+
html: fullHtml,
|
|
42
|
+
text: stripHtml(html)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
VueRenderer
|
|
48
|
+
};
|