@ossy/email 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +209 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 1.3.0 (2026-05-30)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **dependencies:** update Playwright to version 1.60.0 and enhance build task externalization ([b7787b7](https://github.com/ossy-se/ossy/commit/b7787b7c29e0f5edee85ab998db2f841097e4f88))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## 1.2.1 (2026-05-30)
|
|
7
18
|
|
|
8
19
|
**Note:** Version bump only for package @ossy/email
|
package/README.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# @ossy/email
|
|
2
|
+
|
|
3
|
+
React email rendering and AWS SES integration for the Ossy platform. Provides layout components, a server-side renderer, and the `email.integration.js` that the platform connects at startup.
|
|
4
|
+
|
|
5
|
+
## Packages at a glance
|
|
6
|
+
|
|
7
|
+
| Export | Purpose |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `EmailLayout` | Responsive email shell (600 px centered table layout) |
|
|
10
|
+
| `EmailButton` | Themed call-to-action button |
|
|
11
|
+
| `EmailText` | Body paragraph with sensible defaults |
|
|
12
|
+
| `EmailRenderer` | Renders a React component to `{ html, text }` |
|
|
13
|
+
| `emailIntegration` / `connect` | AWS SES integration factory |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## `*.email.jsx` — Transactional email template primitive
|
|
18
|
+
|
|
19
|
+
An email template is a React component discovered and bundled by `@ossy/app build`. You do not register it manually — the platform picks it up by filename.
|
|
20
|
+
|
|
21
|
+
**File naming:** `<name>.email.jsx` or `<name>.email.tsx`. Place it anywhere inside `src/`.
|
|
22
|
+
|
|
23
|
+
**Required exports:**
|
|
24
|
+
|
|
25
|
+
| Export | Type | Description |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `id` | `string` | Unique template id, e.g. `'authentication/verify-sign-in'`. |
|
|
28
|
+
| `default` | `React.ComponentType` | The email component. |
|
|
29
|
+
|
|
30
|
+
**Optional exports:**
|
|
31
|
+
|
|
32
|
+
| Export | Type | Description |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `subject` | `string` | Default subject line. |
|
|
35
|
+
|
|
36
|
+
**Minimal example:**
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
// src/auth/verify-sign-in.email.jsx
|
|
40
|
+
import { EmailLayout, EmailButton, EmailText } from '@ossy/email'
|
|
41
|
+
|
|
42
|
+
export const id = 'auth/verify-sign-in'
|
|
43
|
+
export const subject = 'Sign in'
|
|
44
|
+
|
|
45
|
+
export default function VerifySignInEmail({ token, baseUrl = 'https://app.example.com', theme }) {
|
|
46
|
+
const url = `${baseUrl}/verify?token=${token}`
|
|
47
|
+
return (
|
|
48
|
+
<EmailLayout theme={theme}>
|
|
49
|
+
<h1 style={{ color: '#111111', margin: '0 0 16px' }}>Sign in</h1>
|
|
50
|
+
<EmailText>Click the button below to sign in.</EmailText>
|
|
51
|
+
<EmailButton href={url} theme={theme}>Sign in</EmailButton>
|
|
52
|
+
</EmailLayout>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
See [PRIMITIVES.md](../platform/PRIMITIVES.md#email) for the full primitive specification.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Components
|
|
62
|
+
|
|
63
|
+
### `EmailLayout`
|
|
64
|
+
|
|
65
|
+
A responsive 600 px centered table layout. Wraps the email body.
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
import { EmailLayout } from '@ossy/email'
|
|
69
|
+
|
|
70
|
+
<EmailLayout theme={theme}>
|
|
71
|
+
{/* email content */}
|
|
72
|
+
</EmailLayout>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Props:**
|
|
76
|
+
|
|
77
|
+
| Prop | Type | Default | Description |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| `children` | `ReactNode` | — | Email body content. |
|
|
80
|
+
| `theme` | `{ primaryColor?, backgroundColor?, fontFamily? }` | `{}` | Colour/font overrides. |
|
|
81
|
+
|
|
82
|
+
**Theme defaults:**
|
|
83
|
+
|
|
84
|
+
| Key | Default |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `primaryColor` | `'#111111'` |
|
|
87
|
+
| `backgroundColor` | `'#f5f5f5'` |
|
|
88
|
+
| `fontFamily` | `'sans-serif'` |
|
|
89
|
+
|
|
90
|
+
### `EmailButton`
|
|
91
|
+
|
|
92
|
+
A styled call-to-action link rendered as an `<a>` tag (for maximum email client compatibility).
|
|
93
|
+
|
|
94
|
+
```jsx
|
|
95
|
+
import { EmailButton } from '@ossy/email'
|
|
96
|
+
|
|
97
|
+
<EmailButton href="https://example.com/action" theme={theme}>
|
|
98
|
+
Click me
|
|
99
|
+
</EmailButton>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Props:**
|
|
103
|
+
|
|
104
|
+
| Prop | Type | Description |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `href` | `string` | Link destination. |
|
|
107
|
+
| `children` | `ReactNode` | Button label. |
|
|
108
|
+
| `theme` | `object` | Same shape as `EmailLayout` theme. |
|
|
109
|
+
|
|
110
|
+
### `EmailText`
|
|
111
|
+
|
|
112
|
+
A body paragraph with sensible line-height and colour defaults.
|
|
113
|
+
|
|
114
|
+
```jsx
|
|
115
|
+
import { EmailText } from '@ossy/email'
|
|
116
|
+
|
|
117
|
+
<EmailText>You have requested to sign in.</EmailText>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Props:**
|
|
121
|
+
|
|
122
|
+
| Prop | Type | Description |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| `children` | `ReactNode` | Paragraph content. |
|
|
125
|
+
| `style` | `CSSProperties` | Additional inline styles (merged with defaults). |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## `EmailRenderer`
|
|
130
|
+
|
|
131
|
+
Server-side renderer. Converts a React email component to HTML and a plain-text fallback.
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
import { EmailRenderer } from '@ossy/email'
|
|
135
|
+
|
|
136
|
+
const { html, text } = EmailRenderer.render(VerifySignInEmail, { token: 'abc', baseUrl: 'https://app.example.com' })
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`render(Component, props)` calls `renderToStaticMarkup` (from `react-dom/server`) and strips HTML tags for the plain-text output. Both strings are suitable for passing directly to the AWS SES `SendEmailCommand`.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## `email.integration.js` — AWS SES integration
|
|
144
|
+
|
|
145
|
+
The `email` integration is an `*.integration.js` primitive that the platform connects at startup. It provides two methods: `send` (raw) and `sendTemplate` (React component).
|
|
146
|
+
|
|
147
|
+
**Required environment variables:**
|
|
148
|
+
|
|
149
|
+
| Variable | Description |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `SES_REGION` | AWS region for SES (e.g. `eu-west-1`) |
|
|
152
|
+
| `AWS_ACCESS_KEY_ID` | AWS access key |
|
|
153
|
+
| `AWS_SECRET_ACCESS_KEY` | AWS secret key |
|
|
154
|
+
|
|
155
|
+
If any variable is missing the integration is skipped with a warning, and `integrations.get('email')` returns `null`.
|
|
156
|
+
|
|
157
|
+
**Using the email client in a task:**
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
// src/send-invite.task.js
|
|
161
|
+
import WorkspaceInvitationEmail from './workspace-invitation.email.jsx'
|
|
162
|
+
|
|
163
|
+
export const metadata = {
|
|
164
|
+
id: 'send-workspace-invitation',
|
|
165
|
+
triggers: [{ aggregateType: 'Workspace', event: 'UserInvited' }],
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export async function run({ event, integrations }) {
|
|
169
|
+
const email = integrations.get('email')
|
|
170
|
+
if (!email) return
|
|
171
|
+
|
|
172
|
+
// Send a raw email
|
|
173
|
+
await email.send({
|
|
174
|
+
to: event.payload.email,
|
|
175
|
+
from: 'noreply@example.com',
|
|
176
|
+
subject: 'You have been invited',
|
|
177
|
+
html: '<p>Click <a href="...">here</a> to accept.</p>',
|
|
178
|
+
text: 'Click the link to accept the invitation.',
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Or send a React template
|
|
182
|
+
await email.sendTemplate(
|
|
183
|
+
WorkspaceInvitationEmail,
|
|
184
|
+
{ inviteUrl: event.payload.inviteUrl, theme: {} },
|
|
185
|
+
{ to: event.payload.email, from: 'noreply@example.com', subject: 'Invitation' },
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Client API:**
|
|
191
|
+
|
|
192
|
+
| Method | Signature | Description |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| `send` | `({ to, from, subject, html, text }) => Promise` | Send a raw HTML/text email via SES. |
|
|
195
|
+
| `sendTemplate` | `(Component, props, { to, from, subject }) => Promise` | Render a React component with `EmailRenderer.render` and send via SES. |
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Using `emailIntegration` directly
|
|
200
|
+
|
|
201
|
+
If you need to connect the integration without the platform's auto-loader:
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
import { emailIntegration } from '@ossy/email'
|
|
205
|
+
import { IntegrationService } from '@ossy/platform'
|
|
206
|
+
|
|
207
|
+
await IntegrationService.load([emailIntegration], process.env)
|
|
208
|
+
const emailClient = IntegrationService.get('email')
|
|
209
|
+
```
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/email",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"module": "./src/index.js",
|
|
@@ -19,5 +19,5 @@
|
|
|
19
19
|
"react": "*",
|
|
20
20
|
"react-dom": "*"
|
|
21
21
|
},
|
|
22
|
-
"gitHead": "
|
|
22
|
+
"gitHead": "6c7724dea1b5eda89e83319dce69703d622aadb1"
|
|
23
23
|
}
|