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 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 for authoring, previewing, and sending transactional email templates all from inside your Nuxt app.
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 original request body (includes template props + `to`, `subject`, `from`, etc.)
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. The request body is read and passed as props to the Vue email template
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 }` your plugin handles the actual sending
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
- "customerName": "Jane Doe",
330
- "orderNumber": "ORD-123456",
331
- "orderDate": "February 17, 2026",
332
- "totalAmount": 89.99,
333
- "to": "jane@example.com",
334
- "subject": "Your Order is Confirmed!"
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
- interface NuxtGenEmailsSendPayload {
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
- /** Arbitrary data forwarded from the request body (e.g. `to`, `subject`). */
8
- data: Record<string, unknown>;
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
- interface NuxtGenEmailsSendPayload {
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
- /** Arbitrary data forwarded from the request body (e.g. `to`, `subject`). */
8
- data: Record<string, unknown>;
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
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=4.0.0"
6
6
  },
7
- "version": "0.1.43",
7
+ "version": "0.2.01",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
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
- example: ${examplePayload},
210
- additionalProperties: true,
211
- description: '${emailName} props payload',
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<Record<string, unknown>>(event)
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, body, { pretty: true })
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: body })
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: Record<string, unknown>
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: props.dataObject
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
- ...props.dataObject,
59
- to: lastUsedEmail.value,
60
- subject: `Test email ${Date.now()}`
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
@@ -1,3 +1,3 @@
1
1
  export { default } from './module.mjs'
2
2
 
3
- export { type ModuleOptions, type NuxtGenEmailsSendPayload } from './module.mjs'
3
+ export { type ModuleOptions, type NuxtGenEmailsSendData, type NuxtGenEmailsSendPayload } from './module.mjs'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-generation-emails",
3
- "version": "0.1.43",
3
+ "version": "0.2.01",
4
4
  "description": "A Nuxt module for authoring, previewing, and sending transactional email templates with Vue Email.",
5
5
  "author": "nullcarry@icloud.com",
6
6
  "repository": {