nuxt-generation-emails 0.1.43 → 0.2.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/README.md +33 -13
- package/dist/module.d.mts +13 -4
- package/dist/module.d.ts +13 -4
- package/dist/module.json +1 -1
- package/dist/module.mjs +55 -7
- package/dist/runtime/components/ApiTester.vue +9 -4
- package/dist/types.d.mts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[![License][license-src]][license-href]
|
|
4
4
|
[![Nuxt][nuxt-src]][nuxt-href]
|
|
5
5
|
|
|
6
|
-
A Nuxt module
|
|
6
|
+
A production-ready Nuxt module that turns your app into a complete email workflow: build Vue-powered templates, preview them live, auto-generate typed API endpoints, and optionally deliver through providers like SendGrid via a Nitro hook. From local development to real sends, everything stays in one place.
|
|
7
7
|
|
|
8
8
|
## ✨ Features
|
|
9
9
|
|
|
@@ -254,13 +254,23 @@ The module generates `POST` endpoints for every template that render the email H
|
|
|
254
254
|
|
|
255
255
|
Create a file at `server/plugins/gen-emails.ts` in your project:
|
|
256
256
|
|
|
257
|
+
`data` in the hook payload uses this shape:
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
type NuxtGenEmailsSendData<TAdditional extends Record<string, unknown> = Record<string, unknown>> = {
|
|
261
|
+
to?: string
|
|
262
|
+
from?: string
|
|
263
|
+
subject?: string
|
|
264
|
+
} & TAdditional
|
|
265
|
+
```
|
|
266
|
+
|
|
257
267
|
```ts
|
|
258
268
|
// server/plugins/gen-emails.ts
|
|
259
269
|
export default defineNitroPlugin((nitro) => {
|
|
260
|
-
nitro.hooks.hook('nuxt-gen-emails:send', async ({ html, data }: { html: string, data: Record<string, unknown> }) => {
|
|
270
|
+
nitro.hooks.hook('nuxt-gen-emails:send', async ({ html, data }: { html: string, data: { to?: string, from?: string, subject?: string } & Record<string, unknown> }) => {
|
|
261
271
|
// Your email sending logic here.
|
|
262
272
|
// `html` is the fully rendered email HTML string.
|
|
263
|
-
// `data` is the
|
|
273
|
+
// `data` is `sendData` from the request body.
|
|
264
274
|
console.log('Sending email to:', data.to)
|
|
265
275
|
})
|
|
266
276
|
})
|
|
@@ -289,7 +299,7 @@ import sgMail from '@sendgrid/mail'
|
|
|
289
299
|
export default defineNitroPlugin((nitro) => {
|
|
290
300
|
sgMail.setApiKey(process.env.SENDGRID_API_KEY!)
|
|
291
301
|
|
|
292
|
-
nitro.hooks.hook('nuxt-gen-emails:send', async ({ html, data }: { html: string, data: Record<string, unknown> }) => {
|
|
302
|
+
nitro.hooks.hook('nuxt-gen-emails:send', async ({ html, data }: { html: string, data: { to?: string, from?: string, subject?: string } & Record<string, unknown> }) => {
|
|
293
303
|
const msg = {
|
|
294
304
|
to: data.to as string,
|
|
295
305
|
from: (data.from as string) || 'noreply@yourdomain.com',
|
|
@@ -315,23 +325,33 @@ export default defineNitroPlugin((nitro) => {
|
|
|
315
325
|
|
|
316
326
|
When a `POST` request hits an email endpoint (e.g., `/api/emails/v1/order-confirmation`):
|
|
317
327
|
|
|
318
|
-
1.
|
|
328
|
+
1. `templateData` from the request body is passed as props to the Vue email template
|
|
319
329
|
2. `@vue-email/render` renders the template to an HTML string
|
|
320
|
-
3. The Nitro hook `nuxt-gen-emails:send` is called with `{ html, data }`
|
|
330
|
+
3. The Nitro hook `nuxt-gen-emails:send` is called with `{ html, data }` where `data` is `sendData`
|
|
321
331
|
4. The response always returns `{ success: true, html: "..." }` so you can inspect the rendered output
|
|
322
332
|
|
|
333
|
+
### Sending behavior
|
|
334
|
+
|
|
335
|
+
- If you configure a Nitro plugin that listens to `nuxt-gen-emails:send`, the module passes your `sendData` to that hook and your plugin can send the email through your provider (SendGrid, SES, etc.).
|
|
336
|
+
- If you do not configure that Nitro hook plugin, the endpoint still renders the email template and returns the rendered HTML in the `POST` response.
|
|
337
|
+
- In both cases, the API response includes the rendered `html` so you can preview/debug the final output.
|
|
338
|
+
|
|
323
339
|
### Example API call
|
|
324
340
|
|
|
325
341
|
```bash
|
|
326
342
|
curl -X POST http://localhost:3000/api/emails/v1/order-confirmation \
|
|
327
343
|
-H "Content-Type: application/json" \
|
|
328
344
|
-d '{
|
|
329
|
-
"
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
345
|
+
"templateData": {
|
|
346
|
+
"customerName": "Jane Doe",
|
|
347
|
+
"orderNumber": "ORD-123456",
|
|
348
|
+
"orderDate": "February 17, 2026",
|
|
349
|
+
"totalAmount": 89.99
|
|
350
|
+
},
|
|
351
|
+
"sendData": {
|
|
352
|
+
"to": "jane@example.com",
|
|
353
|
+
"subject": "Your Order is Confirmed!"
|
|
354
|
+
}
|
|
335
355
|
}'
|
|
336
356
|
```
|
|
337
357
|
|
|
@@ -349,7 +369,7 @@ Full config key: `nuxtGenerationEmails`
|
|
|
349
369
|
|
|
350
370
|
| Hook | Payload | Description |
|
|
351
371
|
|---------------------------|-----------------------------------------------|----------------------------------------------|
|
|
352
|
-
| `nuxt-gen-emails:send` | `{ html: string, data: Record<string, unknown> }` | Called after rendering; wire your send logic here |
|
|
372
|
+
| `nuxt-gen-emails:send` | `{ html: string, data: { to?: string, from?: string, subject?: string } & Record<string, unknown> }` | Called after rendering; wire your send logic here |
|
|
353
373
|
|
|
354
374
|
---
|
|
355
375
|
|
package/dist/module.d.mts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
|
|
3
3
|
/** Payload passed to the `nuxt-gen-emails:send` Nitro runtime hook. */
|
|
4
|
-
|
|
4
|
+
type NuxtGenEmailsSendData<TAdditional extends Record<string, unknown> = Record<string, unknown>> = {
|
|
5
|
+
/** Recipient email address. */
|
|
6
|
+
to?: string;
|
|
7
|
+
/** Sender email address. */
|
|
8
|
+
from?: string;
|
|
9
|
+
/** Email subject line. */
|
|
10
|
+
subject?: string;
|
|
11
|
+
} & TAdditional;
|
|
12
|
+
/** Payload passed to the `nuxt-gen-emails:send` Nitro runtime hook. */
|
|
13
|
+
interface NuxtGenEmailsSendPayload<TSendData extends Record<string, unknown> = NuxtGenEmailsSendData> {
|
|
5
14
|
/** The rendered HTML string of the email template. */
|
|
6
15
|
html: string;
|
|
7
|
-
/**
|
|
8
|
-
data:
|
|
16
|
+
/** Send data forwarded from `sendData` in the request body (e.g. `to`, `subject`). */
|
|
17
|
+
data: TSendData;
|
|
9
18
|
}
|
|
10
19
|
interface ModuleOptions {
|
|
11
20
|
/** Directory containing email templates; resolved from srcDir when relative. */
|
|
@@ -14,4 +23,4 @@ interface ModuleOptions {
|
|
|
14
23
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
15
24
|
|
|
16
25
|
export { _default as default };
|
|
17
|
-
export type { ModuleOptions, NuxtGenEmailsSendPayload };
|
|
26
|
+
export type { ModuleOptions, NuxtGenEmailsSendData, NuxtGenEmailsSendPayload };
|
package/dist/module.d.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
|
|
3
3
|
/** Payload passed to the `nuxt-gen-emails:send` Nitro runtime hook. */
|
|
4
|
-
|
|
4
|
+
type NuxtGenEmailsSendData<TAdditional extends Record<string, unknown> = Record<string, unknown>> = {
|
|
5
|
+
/** Recipient email address. */
|
|
6
|
+
to?: string;
|
|
7
|
+
/** Sender email address. */
|
|
8
|
+
from?: string;
|
|
9
|
+
/** Email subject line. */
|
|
10
|
+
subject?: string;
|
|
11
|
+
} & TAdditional;
|
|
12
|
+
/** Payload passed to the `nuxt-gen-emails:send` Nitro runtime hook. */
|
|
13
|
+
interface NuxtGenEmailsSendPayload<TSendData extends Record<string, unknown> = NuxtGenEmailsSendData> {
|
|
5
14
|
/** The rendered HTML string of the email template. */
|
|
6
15
|
html: string;
|
|
7
|
-
/**
|
|
8
|
-
data:
|
|
16
|
+
/** Send data forwarded from `sendData` in the request body (e.g. `to`, `subject`). */
|
|
17
|
+
data: TSendData;
|
|
9
18
|
}
|
|
10
19
|
interface ModuleOptions {
|
|
11
20
|
/** Directory containing email templates; resolved from srcDir when relative. */
|
|
@@ -14,4 +23,4 @@ interface ModuleOptions {
|
|
|
14
23
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
15
24
|
|
|
16
25
|
export { _default as default };
|
|
17
|
-
export type { ModuleOptions, NuxtGenEmailsSendPayload };
|
|
26
|
+
export type { ModuleOptions, NuxtGenEmailsSendData, NuxtGenEmailsSendPayload };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -195,6 +195,20 @@ import { useNitroApp } from '#imports'
|
|
|
195
195
|
import { render } from '@vue-email/render'
|
|
196
196
|
import EmailTemplate from '~/emails/${emailPath}.vue'
|
|
197
197
|
|
|
198
|
+
type SendData<TAdditional extends Record<string, unknown> = Record<string, unknown>> = {
|
|
199
|
+
to?: string
|
|
200
|
+
from?: string
|
|
201
|
+
subject?: string
|
|
202
|
+
} & TAdditional
|
|
203
|
+
|
|
204
|
+
type NuxtGenEmailsApiBody<
|
|
205
|
+
TTemplateData extends Record<string, unknown> = Record<string, unknown>,
|
|
206
|
+
TSendData extends Record<string, unknown> = SendData,
|
|
207
|
+
> = {
|
|
208
|
+
templateData: TTemplateData
|
|
209
|
+
sendData: TSendData
|
|
210
|
+
}
|
|
211
|
+
|
|
198
212
|
defineRouteMeta({
|
|
199
213
|
openAPI: {
|
|
200
214
|
tags: ['nuxt-generation-emails'],
|
|
@@ -206,9 +220,26 @@ defineRouteMeta({
|
|
|
206
220
|
'application/json': {
|
|
207
221
|
schema: {
|
|
208
222
|
type: 'object',
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
223
|
+
description: '${emailName} request payload',
|
|
224
|
+
properties: {
|
|
225
|
+
templateData: {
|
|
226
|
+
type: 'object',
|
|
227
|
+
description: '${emailName} props payload',
|
|
228
|
+
additionalProperties: true,
|
|
229
|
+
example: ${examplePayload},
|
|
230
|
+
},
|
|
231
|
+
sendData: {
|
|
232
|
+
type: 'object',
|
|
233
|
+
description: 'Send provider metadata (to/from/subject and any additional fields)',
|
|
234
|
+
additionalProperties: true,
|
|
235
|
+
properties: {
|
|
236
|
+
to: { type: 'string', example: 'test@example.com' },
|
|
237
|
+
from: { type: 'string', example: 'test@example.com' },
|
|
238
|
+
subject: { type: 'string', example: 'Sending with Twilio SendGrid is Fun' },
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
required: ['templateData', 'sendData'],
|
|
212
243
|
},
|
|
213
244
|
},
|
|
214
245
|
},
|
|
@@ -250,14 +281,17 @@ defineRouteMeta({
|
|
|
250
281
|
})
|
|
251
282
|
|
|
252
283
|
export default defineEventHandler(async (event) => {
|
|
253
|
-
const body = await readBody<
|
|
284
|
+
const body = await readBody<NuxtGenEmailsApiBody>(event)
|
|
285
|
+
|
|
286
|
+
const templateData = body?.templateData ?? {}
|
|
287
|
+
const sendData = body?.sendData ?? {}
|
|
254
288
|
|
|
255
289
|
try {
|
|
256
|
-
const html = await render(EmailTemplate,
|
|
290
|
+
const html = await render(EmailTemplate, templateData, { pretty: true })
|
|
257
291
|
|
|
258
292
|
const nitro = useNitroApp()
|
|
259
293
|
// @ts-ignore - custom hook
|
|
260
|
-
await nitro.hooks.callHook('nuxt-gen-emails:send', { html, data:
|
|
294
|
+
await nitro.hooks.callHook('nuxt-gen-emails:send', { html, data: sendData })
|
|
261
295
|
|
|
262
296
|
return { success: true, message: 'Email rendered successfully', html }
|
|
263
297
|
}
|
|
@@ -328,7 +362,21 @@ const module$1 = defineNuxtModule({
|
|
|
328
362
|
getContents: () => `
|
|
329
363
|
export interface NuxtGenEmailsSendPayload {
|
|
330
364
|
html: string
|
|
331
|
-
data:
|
|
365
|
+
data: NuxtGenEmailsSendData
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export type NuxtGenEmailsSendData<TAdditional extends Record<string, unknown> = Record<string, unknown>> = {
|
|
369
|
+
to?: string
|
|
370
|
+
from?: string
|
|
371
|
+
subject?: string
|
|
372
|
+
} & TAdditional
|
|
373
|
+
|
|
374
|
+
export interface NuxtGenEmailsApiBody<
|
|
375
|
+
TTemplateData extends Record<string, unknown> = Record<string, unknown>,
|
|
376
|
+
TSendData extends Record<string, unknown> = NuxtGenEmailsSendData,
|
|
377
|
+
> {
|
|
378
|
+
templateData: TTemplateData
|
|
379
|
+
sendData: TSendData
|
|
332
380
|
}
|
|
333
381
|
|
|
334
382
|
declare module 'nitropack' {
|
|
@@ -35,7 +35,10 @@ async function testApi() {
|
|
|
35
35
|
try {
|
|
36
36
|
const result = await $fetch(apiEndpoint.value, {
|
|
37
37
|
method: "POST",
|
|
38
|
-
body:
|
|
38
|
+
body: {
|
|
39
|
+
templateData: props.dataObject,
|
|
40
|
+
sendData: {}
|
|
41
|
+
}
|
|
39
42
|
});
|
|
40
43
|
responseData.value = result;
|
|
41
44
|
response.value = JSON.stringify(result, null, 2);
|
|
@@ -55,9 +58,11 @@ async function sendTestEmail() {
|
|
|
55
58
|
}
|
|
56
59
|
lastUsedEmail.value = testEmailTo.value.trim();
|
|
57
60
|
const payload = {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
templateData: props.dataObject,
|
|
62
|
+
sendData: {
|
|
63
|
+
to: lastUsedEmail.value,
|
|
64
|
+
subject: `Test email ${Date.now()}`
|
|
65
|
+
}
|
|
61
66
|
};
|
|
62
67
|
isLoading.value = true;
|
|
63
68
|
sendStatus.value = "sending";
|
package/dist/types.d.mts
CHANGED
package/package.json
CHANGED