nuxt-generation-emails 0.2.4 → 0.2.6
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 +73 -6
- package/dist/module.d.mts +2 -0
- package/dist/module.d.ts +2 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +13 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ export default defineNuxtConfig({
|
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
-
##
|
|
59
|
+
## 🛠️ 2. Adding Templates with the CLI
|
|
60
60
|
|
|
61
61
|
The fastest way to create a new email template:
|
|
62
62
|
|
|
@@ -174,7 +174,27 @@ The directory structure maps directly to routes:
|
|
|
174
174
|
|
|
175
175
|
## ✍️ 4. Writing Email Templates
|
|
176
176
|
|
|
177
|
-
Templates are standard Vue SFCs
|
|
177
|
+
Templates are standard Vue SFCs built with [`@vue-email/components`](https://vuemail.net/) — a set of unstyled, email-safe Vue components that produce clean, cross-client HTML. Instead of wrestling with `<table>` layouts and inline styles, you use components like `<Container>`, `<Section>`, `<Text>`, `<Button>`, and `<Heading>` that compile down to battle-tested email markup. The `<Tailwind>` wrapper lets you style with Tailwind CSS utility classes that get inlined automatically at render time.
|
|
178
|
+
|
|
179
|
+
Key components from `@vue-email/components`:
|
|
180
|
+
|
|
181
|
+
| Component | Purpose |
|
|
182
|
+
|----------------|-------------------------------------------------------------------------|
|
|
183
|
+
| `<Html>` | Root email wrapper with `lang` attribute |
|
|
184
|
+
| `<Head>` | Email `<head>` — inject fonts, meta tags |
|
|
185
|
+
| `<Body>` | Email body element |
|
|
186
|
+
| `<Container>` | Centered, max-width content wrapper (replaces `<table>` centering hacks)|
|
|
187
|
+
| `<Section>` | Groups content into rows |
|
|
188
|
+
| `<Text>` | Paragraph text with sensible email defaults |
|
|
189
|
+
| `<Heading>` | `<h1>`–`<h6>` headings |
|
|
190
|
+
| `<Button>` | Call-to-action link styled as a button |
|
|
191
|
+
| `<Hr>` | Horizontal rule |
|
|
192
|
+
| `<Link>` | Anchor tag |
|
|
193
|
+
| `<Preview>` | Invisible preheader text shown in inbox previews |
|
|
194
|
+
| `<Font>` | Web font loading via `@font-face` |
|
|
195
|
+
| `<Tailwind>` | Wraps the template to enable Tailwind CSS utility classes |
|
|
196
|
+
|
|
197
|
+
Define your template's dynamic data using `defineProps` with `withDefaults`:
|
|
178
198
|
|
|
179
199
|
```vue
|
|
180
200
|
<script setup lang="ts">
|
|
@@ -359,12 +379,22 @@ curl -X POST http://localhost:3000/api/emails/v1/order-confirmation \
|
|
|
359
379
|
|
|
360
380
|
## 🔧 7. Module Options
|
|
361
381
|
|
|
362
|
-
| Option
|
|
363
|
-
|
|
364
|
-
| `emailDir`
|
|
382
|
+
| Option | Type | Default | Description |
|
|
383
|
+
|-----------------------|------------|------------|--------------------------------------------------------------------|
|
|
384
|
+
| `emailDir` | `string` | `'emails'` | Directory containing email templates (relative to `srcDir`) |
|
|
385
|
+
| `disablePreviewInProd` | `boolean` | `true` | When `true`, the `/__emails/` preview UI is not registered in production builds. API routes are unaffected. |
|
|
365
386
|
|
|
366
387
|
Full config key: `nuxtGenerationEmails`
|
|
367
388
|
|
|
389
|
+
```ts
|
|
390
|
+
export default defineNuxtConfig({
|
|
391
|
+
nuxtGenerationEmails: {
|
|
392
|
+
emailDir: 'emails',
|
|
393
|
+
disablePreviewInProd: true, // default — preview pages are dev-only
|
|
394
|
+
},
|
|
395
|
+
})
|
|
396
|
+
```
|
|
397
|
+
|
|
368
398
|
### Nitro hook
|
|
369
399
|
|
|
370
400
|
| Hook | Payload | Description |
|
|
@@ -373,7 +403,44 @@ Full config key: `nuxtGenerationEmails`
|
|
|
373
403
|
|
|
374
404
|
---
|
|
375
405
|
|
|
376
|
-
##
|
|
406
|
+
## 🔒 8. Securing API Endpoints
|
|
407
|
+
|
|
408
|
+
The generated `POST /api/emails/...` endpoints are registered in all environments (dev and production). In production, you should protect them with server middleware to prevent unauthorized access.
|
|
409
|
+
|
|
410
|
+
### Using Nuxt server middleware
|
|
411
|
+
|
|
412
|
+
Create a server middleware file that gates access to the email API routes:
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
// server/middleware/protect-emails.ts
|
|
416
|
+
import { defineEventHandler, createError, getHeader } from 'h3'
|
|
417
|
+
|
|
418
|
+
export default defineEventHandler((event) => {
|
|
419
|
+
// Only apply to email API routes
|
|
420
|
+
if (!event.path?.startsWith('/api/emails/')) return
|
|
421
|
+
|
|
422
|
+
const apiKey = getHeader(event, 'x-api-key')
|
|
423
|
+
|
|
424
|
+
if (apiKey !== process.env.EMAIL_API_KEY) {
|
|
425
|
+
throw createError({ statusCode: 401, statusMessage: 'Unauthorized' })
|
|
426
|
+
}
|
|
427
|
+
})
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Then set `EMAIL_API_KEY` in your environment and include the header in requests:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
curl -X POST http://localhost:3000/api/emails/v1/order-confirmation \
|
|
434
|
+
-H "Content-Type: application/json" \
|
|
435
|
+
-H "x-api-key: your-secret-key" \
|
|
436
|
+
-d '{ "templateData": {}, "sendData": {} }'
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
You can also use session-based auth, JWT validation, or any other pattern — the middleware runs before the generated route handler so you have full control.
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 🧩 9. Auto-Imports
|
|
377
444
|
|
|
378
445
|
The module auto-imports these utilities for convenience:
|
|
379
446
|
|
package/dist/module.d.mts
CHANGED
|
@@ -19,6 +19,8 @@ interface NuxtGenEmailsSendPayload<TSendData extends Record<string, unknown> = N
|
|
|
19
19
|
interface ModuleOptions {
|
|
20
20
|
/** Directory containing email templates; resolved from srcDir when relative. */
|
|
21
21
|
emailDir?: string;
|
|
22
|
+
/** When true, the `/__emails/` preview UI pages are not registered in production builds. API routes are unaffected. Defaults to `true`. */
|
|
23
|
+
disablePreviewInProd?: boolean;
|
|
22
24
|
}
|
|
23
25
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
24
26
|
|
package/dist/module.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ interface NuxtGenEmailsSendPayload<TSendData extends Record<string, unknown> = N
|
|
|
19
19
|
interface ModuleOptions {
|
|
20
20
|
/** Directory containing email templates; resolved from srcDir when relative. */
|
|
21
21
|
emailDir?: string;
|
|
22
|
+
/** When true, the `/__emails/` preview UI pages are not registered in production builds. API routes are unaffected. Defaults to `true`. */
|
|
23
|
+
disablePreviewInProd?: boolean;
|
|
22
24
|
}
|
|
23
25
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
24
26
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -421,7 +421,8 @@ const module$1 = defineNuxtModule({
|
|
|
421
421
|
}
|
|
422
422
|
},
|
|
423
423
|
defaults: {
|
|
424
|
-
emailDir: "emails"
|
|
424
|
+
emailDir: "emails",
|
|
425
|
+
disablePreviewInProd: true
|
|
425
426
|
},
|
|
426
427
|
async setup(options, nuxt) {
|
|
427
428
|
const resolver = createResolver(import.meta.url);
|
|
@@ -480,15 +481,18 @@ declare module 'nitropack/types' {
|
|
|
480
481
|
from: resolver.resolve("./runtime/utils/url-params")
|
|
481
482
|
}
|
|
482
483
|
]);
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
484
|
+
const shouldRegisterPreview = nuxt.options.dev || !options.disablePreviewInProd;
|
|
485
|
+
if (shouldRegisterPreview) {
|
|
486
|
+
extendPages((pages) => {
|
|
487
|
+
if (!fs.existsSync(emailsDir)) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
addEmailPages(emailsDir, pages, {
|
|
491
|
+
buildDir: nuxt.options.buildDir,
|
|
492
|
+
emailTemplateComponentPath: resolver.resolve("./runtime/pages/__emails.vue")
|
|
493
|
+
});
|
|
490
494
|
});
|
|
491
|
-
}
|
|
495
|
+
}
|
|
492
496
|
const handlers = generateServerRoutes(emailsDir, nuxt.options.buildDir);
|
|
493
497
|
for (const handler of handlers) {
|
|
494
498
|
addServerHandler({
|
package/package.json
CHANGED