nuxt-generation-emails 1.4.2 → 1.4.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/README.md CHANGED
@@ -284,6 +284,9 @@ The `components/` directory is reserved — it is skipped during route generatio
284
284
  |----------------------------|-------------------------------|-------------------------------|
285
285
  | `emails/welcome.vue` | `/__emails/welcome` | `POST /api/emails/welcome` |
286
286
  | `emails/v1/order.vue` | `/__emails/v1/order` | `POST /api/emails/v1/order` |
287
+ | `emails/v1/order/index.vue` | `/__emails/v1/order/index` | `POST /api/emails/v1/order` |
288
+
289
+ For API endpoints, nested `index.vue` files are treated as directory index routes, so the trailing `/index` is removed. Root-level `emails/index.vue` keeps the existing endpoint: `POST /api/emails/index`.
287
290
 
288
291
  ---
289
292
 
@@ -199,13 +199,16 @@ function createEmailFiles(targetDir, emailName, emailPath) {
199
199
  const vueFile = join(targetDir, `${emailName}.vue`);
200
200
  const mjmlFile = join(targetDir, `${emailName}.mjml`);
201
201
  checkFileExists(vueFile);
202
- checkFileExists(mjmlFile);
203
202
  const vueTemplate = generateVueTemplate(emailName, emailPath);
204
- const mjmlTemplate = generateMjmlTemplate(emailName);
205
203
  writeFileSync(vueFile, vueTemplate, "utf-8");
206
204
  consola.success(`Created email template: ${vueFile}`);
207
- writeFileSync(mjmlFile, mjmlTemplate, "utf-8");
208
- consola.success(`Created MJML template: ${mjmlFile}`);
205
+ if (!existsSync(mjmlFile)) {
206
+ const mjmlTemplate = generateMjmlTemplate(emailName);
207
+ writeFileSync(mjmlFile, mjmlTemplate, "utf-8");
208
+ consola.success(`Created MJML template: ${mjmlFile}`);
209
+ } else {
210
+ consola.info(`MJML template already exists: ${mjmlFile} \u2014 skipping`);
211
+ }
209
212
  return {
210
213
  emailPath,
211
214
  vueFile,
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=4.0.0"
6
6
  },
7
- "version": "1.4.2",
7
+ "version": "1.4.4",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -144,6 +144,11 @@ ${templateClose}
144
144
  `;
145
145
  }
146
146
 
147
+ function extractMjmlTemplateName(filePath) {
148
+ const source = fs.readFileSync(filePath, "utf-8");
149
+ const match = source.match(/useNgeTemplate\(\s*['"]([^'"]+)['"]\s*[,)]/);
150
+ return match ? match[1] ?? null : null;
151
+ }
147
152
  function extractPropsFromSFC(filePath) {
148
153
  const source = fs.readFileSync(filePath, "utf-8");
149
154
  const { descriptor } = parse(source, { filename: filePath });
@@ -568,7 +573,8 @@ function addEmailPages(dirPath, pages, options, routePrefix = "") {
568
573
  }
569
574
  }
570
575
 
571
- function generateApiRoute(emailName, emailPath, examplePayload = "{}") {
576
+ function generateApiRoute(emailName, emailPath, examplePayload = "{}", mjmlTemplatePath) {
577
+ const mjmlPath = mjmlTemplatePath ?? emailPath;
572
578
  return `/* eslint-disable */
573
579
  // This file is generated by nuxt-generation-emails. Do not modify it manually.
574
580
 
@@ -715,7 +721,7 @@ export default defineEventHandler(async (event) => {
715
721
  try {
716
722
  const { emailsDir } = useRuntimeConfig().nuxtGenEmails as { emailsDir: string }
717
723
  registerMjmlPartials(emailsDir)
718
- const mjmlSource = readFileSync(join(emailsDir, '${emailPath}.mjml'), 'utf-8')
724
+ const mjmlSource = readFileSync(join(emailsDir, '${mjmlPath}.mjml'), 'utf-8')
719
725
  const compiledTemplate = Handlebars.compile(mjmlSource)
720
726
  const mjmlString = compiledTemplate(templateData)
721
727
  const { html, errors } = await mjml2html(mjmlString)
@@ -756,6 +762,13 @@ function sanitizeForOpenApi(value) {
756
762
  }
757
763
  return value;
758
764
  }
765
+ function normalizeApiEmailPath(routePrefix, emailName) {
766
+ const rawPath = `${routePrefix}/${emailName}`.replace(/^\//, "");
767
+ if (emailName === "index" && routePrefix) {
768
+ return routePrefix.replace(/^\//, "");
769
+ }
770
+ return rawPath;
771
+ }
759
772
  function generateServerRoutes(emailsDir, buildDir) {
760
773
  if (!fs.existsSync(emailsDir)) return [];
761
774
  const handlersDir = join(buildDir, "email-handlers");
@@ -775,10 +788,15 @@ function generateServerRoutes(emailsDir, buildDir) {
775
788
  processEmailDirectory(fullPath, `${routePrefix}/${entry}`);
776
789
  } else if (entry.endsWith(".vue")) {
777
790
  const emailName = entry.replace(".vue", "");
778
- const emailPath = `${routePrefix}/${emailName}`.replace(/^\//, "");
779
- const mjmlPath = join(dirPath, `${emailName}.mjml`);
791
+ const emailPath = normalizeApiEmailPath(routePrefix, emailName);
792
+ const mjmlTemplateName = extractMjmlTemplateName(fullPath);
793
+ if (!mjmlTemplateName) {
794
+ console.warn(`[nuxt-generation-emails] Could not find useNgeTemplate() call in ${emailName}.vue \u2014 skipping API route.`);
795
+ continue;
796
+ }
797
+ const mjmlPath = join(emailsDir, `${mjmlTemplateName}.mjml`);
780
798
  if (!fs.existsSync(mjmlPath)) {
781
- console.warn(`[nuxt-generation-emails] Missing co-located MJML file for ${emailName}.vue \u2014 skipping API route. Expected: ${mjmlPath}`);
799
+ console.warn(`[nuxt-generation-emails] MJML template "${mjmlTemplateName}.mjml" referenced by ${emailName}.vue not found \u2014 skipping API route. Expected: ${mjmlPath}`);
782
800
  continue;
783
801
  }
784
802
  const handlerDir = routePrefix ? join(handlersDir, routePrefix.replace(/^\//, "")) : handlersDir;
@@ -790,7 +808,7 @@ function generateServerRoutes(emailsDir, buildDir) {
790
808
  const examplePayload = Object.keys(sanitized).length > 0 ? JSON.stringify(sanitized, null, 2) : "{}";
791
809
  const handlerFileName = `${emailName}.ts`;
792
810
  const handlerFilePath = join(handlerDir, handlerFileName);
793
- const handlerContent = generateApiRoute(emailName, emailPath, examplePayload);
811
+ const handlerContent = generateApiRoute(emailName, emailPath, examplePayload, mjmlTemplateName);
794
812
  fs.writeFileSync(handlerFilePath, handlerContent, "utf-8");
795
813
  console.log(`[nuxt-generation-emails] Generated API handler: ${handlerFilePath}`);
796
814
  handlers.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-generation-emails",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "A Nuxt module for authoring, previewing, and sending transactional email templates with MJML and Handlebars.",
5
5
  "author": "nullcarry@icloud.com",
6
6
  "repository": {