react-email 4.1.0-canary.9 → 4.1.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.
Files changed (109) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dev/CHANGELOG.md +3 -0
  3. package/dev/index.js +44 -0
  4. package/dev/package.json +13 -0
  5. package/dist/cli/index.mjs +1391 -0
  6. package/dist/index.js +256 -259
  7. package/dist/preview/.next/BUILD_ID +1 -0
  8. package/dist/preview/.next/app-build-manifest.json +44 -0
  9. package/dist/preview/.next/app-path-routes-manifest.json +6 -0
  10. package/dist/preview/.next/build-manifest.json +33 -0
  11. package/dist/preview/.next/diagnostics/build-diagnostics.json +6 -0
  12. package/dist/preview/.next/diagnostics/framework.json +1 -0
  13. package/dist/preview/.next/export-marker.json +6 -0
  14. package/dist/preview/.next/images-manifest.json +57 -0
  15. package/dist/preview/.next/next-minimal-server.js.nft.json +1 -0
  16. package/dist/preview/.next/next-server.js.nft.json +1 -0
  17. package/dist/preview/.next/package.json +1 -0
  18. package/dist/preview/.next/prerender-manifest.json +41 -0
  19. package/dist/preview/.next/react-loadable-manifest.json +1 -0
  20. package/dist/preview/.next/required-server-files.json +311 -0
  21. package/dist/preview/.next/routes-manifest.json +64 -0
  22. package/dist/preview/.next/server/app/_not-found/page.js +1 -0
  23. package/dist/preview/.next/server/app/_not-found/page.js.nft.json +1 -0
  24. package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  25. package/dist/preview/.next/server/app/favicon.ico/route.js +1 -0
  26. package/dist/preview/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  27. package/dist/preview/.next/server/app/favicon.ico.body +0 -0
  28. package/dist/preview/.next/server/app/favicon.ico.meta +1 -0
  29. package/dist/preview/.next/server/app/page.js +1 -0
  30. package/dist/preview/.next/server/app/page.js.nft.json +1 -0
  31. package/dist/preview/.next/server/app/page_client-reference-manifest.js +1 -0
  32. package/dist/preview/.next/server/app/preview/[...slug]/page.js +321 -0
  33. package/dist/preview/.next/server/app/preview/[...slug]/page.js.nft.json +1 -0
  34. package/dist/preview/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -0
  35. package/dist/preview/.next/server/app-paths-manifest.json +6 -0
  36. package/dist/preview/.next/server/chunks/134.js +6 -0
  37. package/dist/preview/.next/server/chunks/235.js +15 -0
  38. package/dist/preview/.next/server/chunks/343.js +20 -0
  39. package/dist/preview/.next/server/chunks/428.js +14 -0
  40. package/dist/preview/.next/server/chunks/934.js +1 -0
  41. package/dist/preview/.next/server/chunks/963.js +1 -0
  42. package/dist/preview/.next/server/functions-config-manifest.json +4 -0
  43. package/dist/preview/.next/server/interception-route-rewrite-manifest.js +1 -0
  44. package/dist/preview/.next/server/middleware-build-manifest.js +1 -0
  45. package/dist/preview/.next/server/middleware-manifest.json +6 -0
  46. package/dist/preview/.next/server/middleware-react-loadable-manifest.js +1 -0
  47. package/dist/preview/.next/server/next-font-manifest.js +1 -0
  48. package/dist/preview/.next/server/next-font-manifest.json +1 -0
  49. package/dist/preview/.next/server/pages/500.html +1 -0
  50. package/dist/preview/.next/server/pages/_app.js +1 -0
  51. package/dist/preview/.next/server/pages/_app.js.nft.json +1 -0
  52. package/dist/preview/.next/server/pages/_document.js +1 -0
  53. package/dist/preview/.next/server/pages/_document.js.nft.json +1 -0
  54. package/dist/preview/.next/server/pages/_error.js +1 -0
  55. package/dist/preview/.next/server/pages/_error.js.nft.json +1 -0
  56. package/dist/preview/.next/server/pages-manifest.json +5 -0
  57. package/dist/preview/.next/server/server-reference-manifest.js +1 -0
  58. package/dist/preview/.next/server/server-reference-manifest.json +1 -0
  59. package/dist/preview/.next/server/webpack-runtime.js +1 -0
  60. package/dist/preview/.next/static/FZEE-q531kq1Juxsda2po/_buildManifest.js +1 -0
  61. package/dist/preview/.next/static/FZEE-q531kq1Juxsda2po/_ssgManifest.js +1 -0
  62. package/dist/preview/.next/static/chunks/107-3043079e7cb8bcae.js +1 -0
  63. package/dist/preview/.next/static/chunks/293-297b1eb2241f9a70.js +1 -0
  64. package/dist/preview/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +1 -0
  65. package/dist/preview/.next/static/chunks/45-1021fac82f766268.js +1 -0
  66. package/dist/preview/.next/static/chunks/484-f5954e7b4b93f109.js +1 -0
  67. package/dist/preview/.next/static/chunks/589-817d8691661d370e.js +1 -0
  68. package/dist/preview/.next/static/chunks/902-c34acb56733e0ce1.js +1 -0
  69. package/dist/preview/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +1 -0
  70. package/dist/preview/.next/static/chunks/app/layout-89c12abbc616c3a1.js +1 -0
  71. package/dist/preview/.next/static/chunks/app/page-0492cd9ce15b7980.js +1 -0
  72. package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-c670410568d530db.js +1 -0
  73. package/dist/preview/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +6 -0
  74. package/dist/preview/.next/static/chunks/framework-b887e9fc751a9906.js +1 -0
  75. package/dist/preview/.next/static/chunks/main-9a03e7ba8acb1900.js +1 -0
  76. package/dist/preview/.next/static/chunks/main-app-951f948d1c44189f.js +1 -0
  77. package/dist/preview/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +1 -0
  78. package/dist/preview/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +1 -0
  79. package/dist/preview/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  80. package/dist/preview/.next/static/chunks/webpack-31c45daa2bd82a7b.js +1 -0
  81. package/dist/preview/.next/static/css/78c81281aa95270f.css +3 -0
  82. package/dist/preview/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
  83. package/dist/preview/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
  84. package/dist/preview/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
  85. package/dist/preview/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
  86. package/dist/preview/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
  87. package/dist/preview/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
  88. package/dist/preview/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  89. package/dist/preview/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
  90. package/dist/preview/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
  91. package/dist/preview/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
  92. package/dist/preview/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  93. package/dist/preview/.next/static/media/e4051546b3043204-s.p.otf +0 -0
  94. package/dist/preview/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  95. package/dist/preview/.next/static/media/logo.2ce2a759.png +0 -0
  96. package/dist/preview/.next/trace +27 -0
  97. package/dist/preview/.next/types/app/layout.ts +84 -0
  98. package/dist/preview/.next/types/app/page.ts +84 -0
  99. package/dist/preview/.next/types/app/preview/[...slug]/page.ts +84 -0
  100. package/dist/preview/.next/types/cache-life.d.ts +141 -0
  101. package/dist/preview/.next/types/package.json +1 -0
  102. package/package.json +3 -3
  103. package/readme.md +16 -0
  104. package/src/actions/email-validation/__snapshots__/check-images.spec.tsx.snap +84 -0
  105. package/src/utils/preview/get-env-variables-for-preview-app.ts +0 -2
  106. package/src/utils/preview/hot-reloading/create-dependency-graph.spec.ts +1 -70
  107. package/src/utils/preview/hot-reloading/create-dependency-graph.ts +2 -5
  108. package/src/utils/preview/serve-static-file.ts +2 -1
  109. package/src/utils/preview/start-dev-server.ts +1 -6
package/dist/index.js CHANGED
@@ -106,7 +106,7 @@ import prompts from "prompts";
106
106
  // package.json
107
107
  var package_default = {
108
108
  name: "react-email",
109
- version: "4.1.0-canary.9",
109
+ version: "4.1.0",
110
110
  description: "A live preview of your emails right in your browser.",
111
111
  bin: {
112
112
  email: "./dist/index.js"
@@ -114,8 +114,8 @@ var package_default = {
114
114
  type: "module",
115
115
  scripts: {
116
116
  build: "tsup-node",
117
+ "build:watch": "tsup-node --watch src",
117
118
  clean: "rm -rf dist",
118
- dev: "tsup-node --watch src",
119
119
  test: "vitest run",
120
120
  "test:watch": "vitest"
121
121
  },
@@ -326,8 +326,8 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
326
326
  const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
327
327
  const slugs = [];
328
328
  emailDirectory.emailFilenames.forEach(
329
- (filename3) => slugs.push(
330
- path3.join(directoryPathRelativeToEmailsDirectory, filename3).split(path3.sep).filter((segment) => segment.length > 0)
329
+ (filename2) => slugs.push(
330
+ path3.join(directoryPathRelativeToEmailsDirectory, filename2).split(path3.sep).filter((segment) => segment.length > 0)
331
331
  )
332
332
  );
333
333
  emailDirectory.subDirectories.forEach((directory) => {
@@ -458,234 +458,14 @@ var build = async ({
458
458
  import fs6 from "node:fs";
459
459
 
460
460
  // src/utils/preview/hot-reloading/setup-hot-reloading.ts
461
- import path9 from "node:path";
461
+ import path6 from "node:path";
462
462
  import { watch } from "chokidar";
463
463
  import debounce from "debounce";
464
464
  import { Server as SocketServer } from "socket.io";
465
465
 
466
466
  // src/utils/preview/hot-reloading/create-dependency-graph.ts
467
- import { existsSync as existsSync2, promises as fs4, statSync } from "node:fs";
468
- import path8 from "node:path";
469
-
470
- // src/utils/preview/start-dev-server.ts
471
- import http from "node:http";
472
- import path6 from "node:path";
473
- import url2 from "node:url";
474
- import chalk from "chalk";
475
- import { createJiti as createJiti2 } from "jiti";
476
- import logSymbols3 from "log-symbols";
477
- import ora2 from "ora";
478
-
479
- // src/utils/preview/get-env-variables-for-preview-app.ts
480
- import path4 from "node:path";
481
- var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
482
- return {
483
- EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
484
- EMAILS_DIR_ABSOLUTE_PATH: path4.resolve(cwd, relativePathToEmailsDirectory),
485
- USER_PROJECT_LOCATION: cwd,
486
- NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT: isDev ? "true" : "false"
487
- };
488
- };
489
-
490
- // src/utils/preview/serve-static-file.ts
491
- import { existsSync, promises as fs3 } from "node:fs";
467
+ import { existsSync, promises as fs3, statSync } from "node:fs";
492
468
  import path5 from "node:path";
493
- import { lookup } from "mime-types";
494
- var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
495
- const pathname = parsedUrl.pathname.replace("/static", "./static");
496
- const ext = path5.parse(pathname).ext;
497
- const staticBaseDir = path5.resolve(process.cwd(), staticDirRelativePath);
498
- const fileAbsolutePath = path5.resolve(staticBaseDir, pathname);
499
- if (!fileAbsolutePath.startsWith(staticBaseDir)) {
500
- res.statusCode = 403;
501
- res.end();
502
- return;
503
- }
504
- try {
505
- const fileHandle = await fs3.open(fileAbsolutePath, "r");
506
- const fileData = await fs3.readFile(fileHandle);
507
- res.setHeader("Content-type", lookup(ext) || "text/plain");
508
- res.end(fileData);
509
- fileHandle.close();
510
- } catch (exception) {
511
- if (!existsSync(fileAbsolutePath)) {
512
- res.statusCode = 404;
513
- res.end();
514
- } else {
515
- const sanitizedFilePath = fileAbsolutePath.replace(/\n|\r/g, "");
516
- console.error(
517
- `Could not read file at ${sanitizedFilePath} to be served, here's the exception:`,
518
- exception
519
- );
520
- res.statusCode = 500;
521
- res.end(
522
- "Could not read file to be served! Check your terminal for more information."
523
- );
524
- }
525
- }
526
- };
527
-
528
- // src/utils/preview/start-dev-server.ts
529
- var devServer;
530
- var safeAsyncServerListen = (server, port) => {
531
- return new Promise((resolve) => {
532
- server.listen(port, () => {
533
- resolve({ portAlreadyInUse: false });
534
- });
535
- server.on("error", (e) => {
536
- if (e.code === "EADDRINUSE") {
537
- resolve({ portAlreadyInUse: true });
538
- }
539
- });
540
- });
541
- };
542
- var filename = url2.fileURLToPath(import.meta.url);
543
- var dirname = path6.dirname(filename);
544
- var isDev = !dirname.includes("dist");
545
- var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
546
- const [majorNodeVersion] = process.versions.node.split(".");
547
- if (majorNodeVersion && Number.parseInt(majorNodeVersion) < 18) {
548
- console.error(
549
- ` ${logSymbols3.error} Node ${majorNodeVersion} is not supported. Please upgrade to Node 18 or higher.`
550
- );
551
- process.exit(1);
552
- }
553
- const previewServerLocation = await getPreviewServerLocation();
554
- const previewServer = createJiti2(previewServerLocation);
555
- const { default: next } = await previewServer.import("next");
556
- devServer = http.createServer((req, res) => {
557
- if (!req.url) {
558
- res.end(404);
559
- return;
560
- }
561
- const parsedUrl = url2.parse(req.url, true);
562
- res.setHeader(
563
- "Cache-Control",
564
- "no-cache, max-age=0, must-revalidate, no-store"
565
- );
566
- res.setHeader("Pragma", "no-cache");
567
- res.setHeader("Expires", "-1");
568
- try {
569
- if (parsedUrl.path?.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
570
- void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
571
- } else if (!isNextReady) {
572
- void nextReadyPromise.then(
573
- () => nextHandleRequest?.(req, res, parsedUrl)
574
- );
575
- } else {
576
- void nextHandleRequest?.(req, res, parsedUrl);
577
- }
578
- } catch (e) {
579
- console.error("caught error", e);
580
- res.writeHead(500);
581
- res.end();
582
- }
583
- });
584
- const { portAlreadyInUse } = await safeAsyncServerListen(devServer, port);
585
- if (!portAlreadyInUse) {
586
- console.log(chalk.greenBright(` React Email ${package_default.version}`));
587
- console.log(` Running preview at: http://localhost:${port}
588
- `);
589
- } else {
590
- const nextPortToTry = port + 1;
591
- console.warn(
592
- ` ${logSymbols3.warning} Port ${port} is already in use, trying ${nextPortToTry}`
593
- );
594
- return startDevServer(
595
- emailsDirRelativePath,
596
- staticBaseDirRelativePath,
597
- nextPortToTry
598
- );
599
- }
600
- devServer.on("close", async () => {
601
- await app.close();
602
- });
603
- devServer.on("error", (e) => {
604
- spinner.stopAndPersist({
605
- symbol: logSymbols3.error,
606
- text: `Preview Server had an error: ${e}`
607
- });
608
- process.exit(1);
609
- });
610
- const spinner = ora2({
611
- text: "Getting react-email preview server ready...\n",
612
- prefixText: " "
613
- }).start();
614
- registerSpinnerAutostopping(spinner);
615
- const timeBeforeNextReady = performance.now();
616
- process.env = {
617
- NODE_ENV: "development",
618
- ...process.env,
619
- ...getEnvVariablesForPreviewApp(
620
- // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
621
- path6.normalize(emailsDirRelativePath),
622
- process.cwd()
623
- )
624
- };
625
- const app = next({
626
- // passing in env here does not get the environment variables there
627
- dev: isDev,
628
- conf: {
629
- images: {
630
- // This is to avoid the warning with sharp
631
- unoptimized: true
632
- }
633
- },
634
- hostname: "localhost",
635
- port,
636
- dir: previewServerLocation
637
- });
638
- let isNextReady = false;
639
- const nextReadyPromise = app.prepare();
640
- try {
641
- await nextReadyPromise;
642
- } catch (exception) {
643
- spinner.stopAndPersist({
644
- symbol: logSymbols3.error,
645
- text: ` Preview Server had an error: ${exception}`
646
- });
647
- process.exit(1);
648
- }
649
- isNextReady = true;
650
- const nextHandleRequest = app.getRequestHandler();
651
- const secondsToNextReady = ((performance.now() - timeBeforeNextReady) / 1e3).toFixed(1);
652
- spinner.stopAndPersist({
653
- text: `Ready in ${secondsToNextReady}s
654
- `,
655
- symbol: logSymbols3.success
656
- });
657
- return devServer;
658
- };
659
- var makeExitHandler = (options) => (codeSignalOrError) => {
660
- if (typeof devServer !== "undefined") {
661
- console.log("\nshutting down dev server");
662
- devServer.close();
663
- devServer = void 0;
664
- }
665
- if (codeSignalOrError instanceof Error) {
666
- console.error(codeSignalOrError);
667
- }
668
- if (options?.shouldKillProcess) {
669
- process.exit(options.killWithErrorCode ? 1 : 0);
670
- }
671
- };
672
- process.on("exit", makeExitHandler());
673
- process.on(
674
- "SIGINT",
675
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
676
- );
677
- process.on(
678
- "SIGUSR1",
679
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
680
- );
681
- process.on(
682
- "SIGUSR2",
683
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
684
- );
685
- process.on(
686
- "uncaughtException",
687
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
688
- );
689
469
 
690
470
  // src/utils/preview/hot-reloading/get-imported-modules.ts
691
471
  import { parse } from "@babel/parser";
@@ -733,7 +513,7 @@ var getImportedModules = (contents) => {
733
513
  };
734
514
 
735
515
  // src/utils/preview/hot-reloading/resolve-path-aliases.ts
736
- import path7 from "node:path";
516
+ import path4 from "node:path";
737
517
  import { createMatchPath, loadConfig } from "tsconfig-paths";
738
518
  var resolvePathAliases = (importPaths, projectPath) => {
739
519
  const configLoadResult = loadConfig(projectPath);
@@ -752,7 +532,7 @@ var resolvePathAliases = (importPaths, projectPath) => {
752
532
  ".mjs"
753
533
  ]);
754
534
  if (unaliasedPath) {
755
- return `./${path7.relative(projectPath, unaliasedPath)}`;
535
+ return `./${path4.relative(projectPath, unaliasedPath)}`;
756
536
  }
757
537
  return importedPath;
758
538
  });
@@ -763,9 +543,9 @@ var resolvePathAliases = (importPaths, projectPath) => {
763
543
  // src/utils/preview/hot-reloading/create-dependency-graph.ts
764
544
  var readAllFilesInsideDirectory = async (directory) => {
765
545
  let allFilePaths = [];
766
- const topLevelDirents = await fs4.readdir(directory, { withFileTypes: true });
546
+ const topLevelDirents = await fs3.readdir(directory, { withFileTypes: true });
767
547
  for await (const dirent of topLevelDirents) {
768
- const pathToDirent = path8.join(directory, dirent.name);
548
+ const pathToDirent = path5.join(directory, dirent.name);
769
549
  if (dirent.isDirectory()) {
770
550
  allFilePaths = allFilePaths.concat(
771
551
  await readAllFilesInsideDirectory(pathToDirent)
@@ -777,26 +557,26 @@ var readAllFilesInsideDirectory = async (directory) => {
777
557
  return allFilePaths;
778
558
  };
779
559
  var isJavascriptModule = (filePath) => {
780
- const extensionName = path8.extname(filePath);
560
+ const extensionName = path5.extname(filePath);
781
561
  return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
782
562
  };
783
563
  var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
784
- if (existsSync2(`${pathWithoutExtension}.ts`)) {
564
+ if (existsSync(`${pathWithoutExtension}.ts`)) {
785
565
  return `${pathWithoutExtension}.ts`;
786
566
  }
787
- if (existsSync2(`${pathWithoutExtension}.tsx`)) {
567
+ if (existsSync(`${pathWithoutExtension}.tsx`)) {
788
568
  return `${pathWithoutExtension}.tsx`;
789
569
  }
790
- if (existsSync2(`${pathWithoutExtension}.js`)) {
570
+ if (existsSync(`${pathWithoutExtension}.js`)) {
791
571
  return `${pathWithoutExtension}.js`;
792
572
  }
793
- if (existsSync2(`${pathWithoutExtension}.jsx`)) {
573
+ if (existsSync(`${pathWithoutExtension}.jsx`)) {
794
574
  return `${pathWithoutExtension}.jsx`;
795
575
  }
796
- if (existsSync2(`${pathWithoutExtension}.mjs`)) {
576
+ if (existsSync(`${pathWithoutExtension}.mjs`)) {
797
577
  return `${pathWithoutExtension}.mjs`;
798
578
  }
799
- if (existsSync2(`${pathWithoutExtension}.cjs`)) {
579
+ if (existsSync(`${pathWithoutExtension}.cjs`)) {
800
580
  return `${pathWithoutExtension}.cjs`;
801
581
  }
802
582
  };
@@ -815,15 +595,15 @@ var createDependencyGraph = async (directory) => {
815
595
  ])
816
596
  );
817
597
  const getDependencyPaths = async (filePath) => {
818
- const contents = await fs4.readFile(filePath, "utf8");
819
- const importedPaths = isJavascriptModule(filePath) ? resolvePathAliases(getImportedModules(contents), path8.dirname(filePath)) : [];
598
+ const contents = await fs3.readFile(filePath, "utf8");
599
+ const importedPaths = isJavascriptModule(filePath) ? resolvePathAliases(getImportedModules(contents), path5.dirname(filePath)) : [];
820
600
  const importedPathsRelativeToDirectory = importedPaths.map(
821
601
  (dependencyPath) => {
822
602
  const isModulePath = !dependencyPath.startsWith(".");
823
- if (isModulePath || path8.isAbsolute(dependencyPath)) {
603
+ if (isModulePath || path5.isAbsolute(dependencyPath)) {
824
604
  return dependencyPath;
825
605
  }
826
- let pathToDependencyFromDirectory = path8.resolve(
606
+ let pathToDependencyFromDirectory = path5.resolve(
827
607
  /*
828
608
  path.resolve resolves paths differently from what imports on javascript do.
829
609
 
@@ -831,7 +611,7 @@ var createDependencyGraph = async (directory) => {
831
611
  would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
832
612
  one the import is meant to go to
833
613
  */
834
- path8.dirname(filePath),
614
+ path5.dirname(filePath),
835
615
  dependencyPath
836
616
  );
837
617
  let isDirectory = false;
@@ -846,15 +626,15 @@ var createDependencyGraph = async (directory) => {
846
626
  );
847
627
  if (pathWithExtension) {
848
628
  pathToDependencyFromDirectory = pathWithExtension;
849
- } else if (isDev) {
629
+ } else {
850
630
  console.warn(
851
631
  `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
852
632
  );
853
633
  }
854
634
  }
855
- const extension = path8.extname(pathToDependencyFromDirectory);
635
+ const extension = path5.extname(pathToDependencyFromDirectory);
856
636
  const pathWithEnsuredExtension = (() => {
857
- if (extension.length > 0 && existsSync2(pathToDependencyFromDirectory)) {
637
+ if (extension.length > 0 && existsSync(pathToDependencyFromDirectory)) {
858
638
  return pathToDependencyFromDirectory;
859
639
  }
860
640
  return checkFileExtensionsUntilItExists(
@@ -863,7 +643,7 @@ var createDependencyGraph = async (directory) => {
863
643
  })();
864
644
  if (pathWithEnsuredExtension) {
865
645
  pathToDependencyFromDirectory = pathWithEnsuredExtension;
866
- } else if (isDev) {
646
+ } else {
867
647
  console.warn(
868
648
  `Could not find file at ${pathToDependencyFromDirectory}`
869
649
  );
@@ -872,10 +652,10 @@ var createDependencyGraph = async (directory) => {
872
652
  }
873
653
  );
874
654
  const moduleDependencies = importedPathsRelativeToDirectory.filter(
875
- (dependencyPath) => !dependencyPath.startsWith(".") && !path8.isAbsolute(dependencyPath)
655
+ (dependencyPath) => !dependencyPath.startsWith(".") && !path5.isAbsolute(dependencyPath)
876
656
  );
877
657
  const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
878
- (dependencyPath) => dependencyPath.startsWith(".") || path8.isAbsolute(dependencyPath)
658
+ (dependencyPath) => dependencyPath.startsWith(".") || path5.isAbsolute(dependencyPath)
879
659
  );
880
660
  return {
881
661
  dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
@@ -1006,14 +786,14 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1006
786
  changes.filter(
1007
787
  (change) => (
1008
788
  // Ensures only changes inside the emails directory are emitted
1009
- path9.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
789
+ path6.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
1010
790
  )
1011
791
  )
1012
792
  );
1013
793
  });
1014
794
  changes = [];
1015
795
  }, 150);
1016
- const absolutePathToEmailsDirectory = path9.resolve(
796
+ const absolutePathToEmailsDirectory = path6.resolve(
1017
797
  process.cwd(),
1018
798
  emailDirRelativePath
1019
799
  );
@@ -1023,7 +803,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1023
803
  cwd: absolutePathToEmailsDirectory
1024
804
  });
1025
805
  const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
1026
- (p) => path9.relative(absolutePathToEmailsDirectory, p).startsWith("..")
806
+ (p) => path6.relative(absolutePathToEmailsDirectory, p).startsWith("..")
1027
807
  );
1028
808
  let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
1029
809
  for (const p of filesOutsideEmailsDirectory) {
@@ -1035,11 +815,11 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1035
815
  process.on("SIGINT", exit);
1036
816
  process.on("uncaughtException", exit);
1037
817
  watcher.on("all", async (event, relativePathToChangeTarget) => {
1038
- const file = relativePathToChangeTarget.split(path9.sep);
818
+ const file = relativePathToChangeTarget.split(path6.sep);
1039
819
  if (file.length === 0) {
1040
820
  return;
1041
821
  }
1042
- const pathToChangeTarget = path9.resolve(
822
+ const pathToChangeTarget = path6.resolve(
1043
823
  absolutePathToEmailsDirectory,
1044
824
  relativePathToChangeTarget
1045
825
  );
@@ -1063,7 +843,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1063
843
  for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
1064
844
  changes.push({
1065
845
  event: "change",
1066
- filename: path9.relative(absolutePathToEmailsDirectory, dependentPath)
846
+ filename: path6.relative(absolutePathToEmailsDirectory, dependentPath)
1067
847
  });
1068
848
  }
1069
849
  reload();
@@ -1071,6 +851,223 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1071
851
  return watcher;
1072
852
  };
1073
853
 
854
+ // src/utils/preview/start-dev-server.ts
855
+ import http from "node:http";
856
+ import path9 from "node:path";
857
+ import url2 from "node:url";
858
+ import chalk from "chalk";
859
+ import { createJiti as createJiti2 } from "jiti";
860
+ import logSymbols3 from "log-symbols";
861
+ import ora2 from "ora";
862
+
863
+ // src/utils/preview/get-env-variables-for-preview-app.ts
864
+ import path7 from "node:path";
865
+ var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
866
+ return {
867
+ EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
868
+ EMAILS_DIR_ABSOLUTE_PATH: path7.resolve(cwd, relativePathToEmailsDirectory),
869
+ USER_PROJECT_LOCATION: cwd
870
+ };
871
+ };
872
+
873
+ // src/utils/preview/serve-static-file.ts
874
+ import { existsSync as existsSync2, promises as fs4 } from "node:fs";
875
+ import path8 from "node:path";
876
+ import { lookup } from "mime-types";
877
+ var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
878
+ const pathname = parsedUrl.pathname.replace("/static", "./static");
879
+ const ext = path8.parse(pathname).ext;
880
+ const staticBaseDir = path8.resolve(process.cwd(), staticDirRelativePath);
881
+ const fileAbsolutePath = path8.resolve(staticBaseDir, pathname);
882
+ if (!fileAbsolutePath.startsWith(staticBaseDir)) {
883
+ res.statusCode = 403;
884
+ res.end();
885
+ return;
886
+ }
887
+ try {
888
+ const fileHandle = await fs4.open(fileAbsolutePath, "r");
889
+ const fileData = await fs4.readFile(fileHandle);
890
+ res.setHeader("Content-type", lookup(ext) || "text/plain");
891
+ res.end(fileData);
892
+ fileHandle.close();
893
+ } catch (exception) {
894
+ if (!existsSync2(fileAbsolutePath)) {
895
+ res.statusCode = 404;
896
+ res.end();
897
+ } else {
898
+ const sanitizedFilePath = fileAbsolutePath.replace(/\n|\r/g, "");
899
+ console.error(
900
+ `Could not read file at %s to be served, here's the exception:`,
901
+ sanitizedFilePath,
902
+ exception
903
+ );
904
+ res.statusCode = 500;
905
+ res.end(
906
+ "Could not read file to be served! Check your terminal for more information."
907
+ );
908
+ }
909
+ }
910
+ };
911
+
912
+ // src/utils/preview/start-dev-server.ts
913
+ var devServer;
914
+ var safeAsyncServerListen = (server, port) => {
915
+ return new Promise((resolve) => {
916
+ server.listen(port, () => {
917
+ resolve({ portAlreadyInUse: false });
918
+ });
919
+ server.on("error", (e) => {
920
+ if (e.code === "EADDRINUSE") {
921
+ resolve({ portAlreadyInUse: true });
922
+ }
923
+ });
924
+ });
925
+ };
926
+ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
927
+ const [majorNodeVersion] = process.versions.node.split(".");
928
+ if (majorNodeVersion && Number.parseInt(majorNodeVersion) < 18) {
929
+ console.error(
930
+ ` ${logSymbols3.error} Node ${majorNodeVersion} is not supported. Please upgrade to Node 18 or higher.`
931
+ );
932
+ process.exit(1);
933
+ }
934
+ const previewServerLocation = await getPreviewServerLocation();
935
+ const previewServer = createJiti2(previewServerLocation);
936
+ const { default: next } = await previewServer.import("next");
937
+ devServer = http.createServer((req, res) => {
938
+ if (!req.url) {
939
+ res.end(404);
940
+ return;
941
+ }
942
+ const parsedUrl = url2.parse(req.url, true);
943
+ res.setHeader(
944
+ "Cache-Control",
945
+ "no-cache, max-age=0, must-revalidate, no-store"
946
+ );
947
+ res.setHeader("Pragma", "no-cache");
948
+ res.setHeader("Expires", "-1");
949
+ try {
950
+ if (parsedUrl.path?.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
951
+ void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
952
+ } else if (!isNextReady) {
953
+ void nextReadyPromise.then(
954
+ () => nextHandleRequest?.(req, res, parsedUrl)
955
+ );
956
+ } else {
957
+ void nextHandleRequest?.(req, res, parsedUrl);
958
+ }
959
+ } catch (e) {
960
+ console.error("caught error", e);
961
+ res.writeHead(500);
962
+ res.end();
963
+ }
964
+ });
965
+ const { portAlreadyInUse } = await safeAsyncServerListen(devServer, port);
966
+ if (!portAlreadyInUse) {
967
+ console.log(chalk.greenBright(` React Email ${package_default.version}`));
968
+ console.log(` Running preview at: http://localhost:${port}
969
+ `);
970
+ } else {
971
+ const nextPortToTry = port + 1;
972
+ console.warn(
973
+ ` ${logSymbols3.warning} Port ${port} is already in use, trying ${nextPortToTry}`
974
+ );
975
+ return startDevServer(
976
+ emailsDirRelativePath,
977
+ staticBaseDirRelativePath,
978
+ nextPortToTry
979
+ );
980
+ }
981
+ devServer.on("close", async () => {
982
+ await app.close();
983
+ });
984
+ devServer.on("error", (e) => {
985
+ spinner.stopAndPersist({
986
+ symbol: logSymbols3.error,
987
+ text: `Preview Server had an error: ${e}`
988
+ });
989
+ process.exit(1);
990
+ });
991
+ const spinner = ora2({
992
+ text: "Getting react-email preview server ready...\n",
993
+ prefixText: " "
994
+ }).start();
995
+ registerSpinnerAutostopping(spinner);
996
+ const timeBeforeNextReady = performance.now();
997
+ process.env = {
998
+ NODE_ENV: "development",
999
+ ...process.env,
1000
+ ...getEnvVariablesForPreviewApp(
1001
+ // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
1002
+ path9.normalize(emailsDirRelativePath),
1003
+ process.cwd()
1004
+ )
1005
+ };
1006
+ const app = next({
1007
+ // passing in env here does not get the environment variables there
1008
+ dev: false,
1009
+ conf: {
1010
+ images: {
1011
+ // This is to avoid the warning with sharp
1012
+ unoptimized: true
1013
+ }
1014
+ },
1015
+ hostname: "localhost",
1016
+ port,
1017
+ dir: previewServerLocation
1018
+ });
1019
+ let isNextReady = false;
1020
+ const nextReadyPromise = app.prepare();
1021
+ try {
1022
+ await nextReadyPromise;
1023
+ } catch (exception) {
1024
+ spinner.stopAndPersist({
1025
+ symbol: logSymbols3.error,
1026
+ text: ` Preview Server had an error: ${exception}`
1027
+ });
1028
+ process.exit(1);
1029
+ }
1030
+ isNextReady = true;
1031
+ const nextHandleRequest = app.getRequestHandler();
1032
+ const secondsToNextReady = ((performance.now() - timeBeforeNextReady) / 1e3).toFixed(1);
1033
+ spinner.stopAndPersist({
1034
+ text: `Ready in ${secondsToNextReady}s
1035
+ `,
1036
+ symbol: logSymbols3.success
1037
+ });
1038
+ return devServer;
1039
+ };
1040
+ var makeExitHandler = (options) => (codeSignalOrError) => {
1041
+ if (typeof devServer !== "undefined") {
1042
+ console.log("\nshutting down dev server");
1043
+ devServer.close();
1044
+ devServer = void 0;
1045
+ }
1046
+ if (codeSignalOrError instanceof Error) {
1047
+ console.error(codeSignalOrError);
1048
+ }
1049
+ if (options?.shouldKillProcess) {
1050
+ process.exit(options.killWithErrorCode ? 1 : 0);
1051
+ }
1052
+ };
1053
+ process.on("exit", makeExitHandler());
1054
+ process.on(
1055
+ "SIGINT",
1056
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
1057
+ );
1058
+ process.on(
1059
+ "SIGUSR1",
1060
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
1061
+ );
1062
+ process.on(
1063
+ "SIGUSR2",
1064
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
1065
+ );
1066
+ process.on(
1067
+ "uncaughtException",
1068
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
1069
+ );
1070
+
1074
1071
  // src/utils/tree.ts
1075
1072
  import { promises as fs5 } from "node:fs";
1076
1073
  import os from "node:os";
@@ -1085,8 +1082,8 @@ var SYMBOLS = {
1085
1082
  var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
1086
1083
  const base = process.cwd();
1087
1084
  const dirFullpath = path10.resolve(base, dirPath);
1088
- const dirname2 = path10.basename(dirFullpath);
1089
- let lines = [dirname2];
1085
+ const dirname = path10.basename(dirFullpath);
1086
+ let lines = [dirname];
1090
1087
  const dirStat = await fs5.stat(dirFullpath);
1091
1088
  if (dirStat.isDirectory() && currentDepth < depth) {
1092
1089
  const childDirents = await fs5.readdir(dirFullpath, { withFileTypes: true });
@@ -1215,15 +1212,15 @@ var renderingUtilitiesExporter = (emailTemplates) => ({
1215
1212
  var getEmailTemplatesFromDirectory = (emailDirectory) => {
1216
1213
  const templatePaths = [];
1217
1214
  emailDirectory.emailFilenames.forEach(
1218
- (filename3) => templatePaths.push(path12.join(emailDirectory.absolutePath, filename3))
1215
+ (filename2) => templatePaths.push(path12.join(emailDirectory.absolutePath, filename2))
1219
1216
  );
1220
1217
  emailDirectory.subDirectories.forEach((directory) => {
1221
1218
  templatePaths.push(...getEmailTemplatesFromDirectory(directory));
1222
1219
  });
1223
1220
  return templatePaths;
1224
1221
  };
1225
- var filename2 = url3.fileURLToPath(import.meta.url);
1226
- var require2 = createRequire(filename2);
1222
+ var filename = url3.fileURLToPath(import.meta.url);
1223
+ var require2 = createRequire(filename);
1227
1224
  var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
1228
1225
  if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
1229
1226
  fs8.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
@@ -0,0 +1 @@
1
+ FZEE-q531kq1Juxsda2po