react-email 4.1.0-canary.8 → 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 (110) hide show
  1. package/CHANGELOG.md +44 -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 +378 -366
  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 +4 -4
  103. package/readme.md +16 -0
  104. package/src/actions/email-validation/__snapshots__/check-images.spec.tsx.snap +84 -0
  105. package/src/utils/get-preview-server-location.ts +34 -15
  106. package/src/utils/preview/get-env-variables-for-preview-app.ts +0 -2
  107. package/src/utils/preview/hot-reloading/create-dependency-graph.spec.ts +1 -70
  108. package/src/utils/preview/hot-reloading/create-dependency-graph.ts +2 -5
  109. package/src/utils/preview/serve-static-file.ts +2 -1
  110. package/src/utils/preview/start-dev-server.ts +1 -6
package/dist/index.js CHANGED
@@ -102,6 +102,88 @@ import url from "node:url";
102
102
  import { createJiti } from "jiti";
103
103
  import { addDevDependency } from "nypm";
104
104
  import prompts from "prompts";
105
+
106
+ // package.json
107
+ var package_default = {
108
+ name: "react-email",
109
+ version: "4.1.0",
110
+ description: "A live preview of your emails right in your browser.",
111
+ bin: {
112
+ email: "./dist/index.js"
113
+ },
114
+ type: "module",
115
+ scripts: {
116
+ build: "tsup-node",
117
+ "build:watch": "tsup-node --watch src",
118
+ clean: "rm -rf dist",
119
+ test: "vitest run",
120
+ "test:watch": "vitest"
121
+ },
122
+ license: "MIT",
123
+ repository: {
124
+ type: "git",
125
+ url: "https://github.com/resend/react-email.git",
126
+ directory: "packages/react-email"
127
+ },
128
+ keywords: [
129
+ "react",
130
+ "email"
131
+ ],
132
+ engines: {
133
+ node: ">=18.0.0"
134
+ },
135
+ dependencies: {
136
+ "@babel/parser": "^7.27.0",
137
+ "@babel/traverse": "^7.27.0",
138
+ chalk: "^5.0.0",
139
+ chokidar: "^4.0.3",
140
+ commander: "^13.0.0",
141
+ debounce: "^2.0.0",
142
+ esbuild: "^0.25.0",
143
+ glob: "^11.0.0",
144
+ jiti: "2.4.2",
145
+ "log-symbols": "^7.0.0",
146
+ "mime-types": "^3.0.0",
147
+ "normalize-path": "^3.0.0",
148
+ nypm: "0.6.0",
149
+ ora: "^8.0.0",
150
+ prompts: "2.4.2",
151
+ "socket.io": "^4.8.1",
152
+ "tsconfig-paths": "4.2.0"
153
+ },
154
+ devDependencies: {
155
+ "@react-email/components": "workspace:*",
156
+ "@types/babel__core": "7.20.5",
157
+ "@types/babel__traverse": "7.20.7",
158
+ "@types/mime-types": "2.1.4",
159
+ "@types/prompts": "2.4.9",
160
+ next: "^15.3.2",
161
+ react: "19.0.0",
162
+ "react-dom": "19.0.0",
163
+ tsup: "8.4.0",
164
+ tsx: "4.19.3",
165
+ typescript: "5.8.3"
166
+ }
167
+ };
168
+
169
+ // src/utils/get-preview-server-location.ts
170
+ var ensurePreviewServerInstalled = async (message) => {
171
+ const response = await prompts({
172
+ type: "confirm",
173
+ name: "installPreviewServer",
174
+ message,
175
+ initial: true
176
+ });
177
+ if (response.installPreviewServer) {
178
+ console.log('Installing "@react-email/preview-server"');
179
+ await addDevDependency(
180
+ `@react-email/preview-server@${package_default.version}`
181
+ );
182
+ process.exit(0);
183
+ } else {
184
+ process.exit(0);
185
+ }
186
+ };
105
187
  var getPreviewServerLocation = async () => {
106
188
  const usersProject = createJiti(process.cwd());
107
189
  let previewServerLocation;
@@ -109,20 +191,16 @@ var getPreviewServerLocation = async () => {
109
191
  previewServerLocation = path2.dirname(
110
192
  url.parse(usersProject.esmResolve("@react-email/preview-server"), true).path
111
193
  );
112
- } catch (exception) {
113
- const response = await prompts({
114
- type: "confirm",
115
- name: "installPreviewServer",
116
- message: 'To run the preview server, the pacakge "@react-email/preview-server" must be installed. Would you like to install it?',
117
- initial: true
118
- });
119
- if (response.installPreviewServer) {
120
- console.log('Installing "@react-email/preview-server"');
121
- await addDevDependency("@react-email/preview-server");
122
- process.exit(0);
123
- } else {
124
- process.exit(0);
125
- }
194
+ } catch (_exception) {
195
+ await ensurePreviewServerInstalled(
196
+ 'To run the preview server, the package "@react-email/preview-server" must be installed. Would you like to install it?'
197
+ );
198
+ }
199
+ const { version } = await usersProject.import("@react-email/preview-server");
200
+ if (version !== package_default.version) {
201
+ await ensurePreviewServerInstalled(
202
+ `To run the preview server, the version of "@react-email/preview-server" must match the version of "react-email" (${package_default.version}). Would you like to install it?`
203
+ );
126
204
  }
127
205
  return previewServerLocation;
128
206
  };
@@ -248,8 +326,8 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
248
326
  const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
249
327
  const slugs = [];
250
328
  emailDirectory.emailFilenames.forEach(
251
- (filename3) => slugs.push(
252
- 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)
253
331
  )
254
332
  );
255
333
  emailDirectory.subDirectories.forEach((directory) => {
@@ -352,325 +430,42 @@ var build = async ({
352
430
  );
353
431
  await fs2.promises.cp(staticPath, builtStaticDirectory, {
354
432
  recursive: true
355
- });
356
- }
357
- spinner.text = "Setting Next environment variables for preview app to work properly";
358
- await setNextEnvironmentVariablesForBuild(
359
- emailsDirRelativePath,
360
- builtPreviewAppPath
361
- );
362
- spinner.text = "Setting server side generation for the email preview pages";
363
- await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
364
- spinner.text = "Updating package.json's build and start scripts";
365
- await updatePackageJson(builtPreviewAppPath);
366
- spinner.text = "Installing dependencies on `.react-email`";
367
- await npmInstall(builtPreviewAppPath, packageManager);
368
- spinner.stopAndPersist({
369
- text: "Successfully prepared `.react-email` for `next build`",
370
- symbol: logSymbols2.success
371
- });
372
- await buildPreviewApp(builtPreviewAppPath);
373
- } catch (error) {
374
- console.log(error);
375
- process.exit(1);
376
- }
377
- };
378
-
379
- // src/commands/dev.ts
380
- import fs6 from "node:fs";
381
-
382
- // src/utils/preview/hot-reloading/setup-hot-reloading.ts
383
- import path9 from "node:path";
384
- import { watch } from "chokidar";
385
- import debounce from "debounce";
386
- import { Server as SocketServer } from "socket.io";
387
-
388
- // src/utils/preview/hot-reloading/create-dependency-graph.ts
389
- import { existsSync as existsSync2, promises as fs4, statSync } from "node:fs";
390
- import path8 from "node:path";
391
-
392
- // src/utils/preview/start-dev-server.ts
393
- import http from "node:http";
394
- import path6 from "node:path";
395
- import url2 from "node:url";
396
- import chalk from "chalk";
397
- import { createJiti as createJiti2 } from "jiti";
398
- import logSymbols3 from "log-symbols";
399
- import ora2 from "ora";
400
-
401
- // package.json
402
- var package_default = {
403
- name: "react-email",
404
- version: "4.1.0-canary.8",
405
- description: "A live preview of your emails right in your browser.",
406
- bin: {
407
- email: "./dist/index.js"
408
- },
409
- type: "module",
410
- scripts: {
411
- build: "tsup-node",
412
- clean: "rm -rf dist",
413
- dev: "tsup-node --watch src",
414
- test: "vitest run",
415
- "test:watch": "vitest"
416
- },
417
- license: "MIT",
418
- repository: {
419
- type: "git",
420
- url: "https://github.com/resend/react-email.git",
421
- directory: "packages/react-email"
422
- },
423
- keywords: [
424
- "react",
425
- "email"
426
- ],
427
- engines: {
428
- node: ">=18.0.0"
429
- },
430
- dependencies: {
431
- "@babel/parser": "^7.27.0",
432
- "@babel/traverse": "^7.27.0",
433
- chalk: "^5.0.0",
434
- chokidar: "^4.0.3",
435
- commander: "^13.0.0",
436
- debounce: "^2.0.0",
437
- esbuild: "^0.25.0",
438
- glob: "^11.0.0",
439
- jiti: "2.4.2",
440
- "log-symbols": "^7.0.0",
441
- "mime-types": "^3.0.0",
442
- "normalize-path": "^3.0.0",
443
- nypm: "0.6.0",
444
- ora: "^8.0.0",
445
- prompts: "2.4.2",
446
- "socket.io": "^4.8.1",
447
- "tsconfig-paths": "4.2.0"
448
- },
449
- devDependencies: {
450
- "@react-email/components": "workspace:*",
451
- "@types/babel__core": "7.20.5",
452
- "@types/babel__traverse": "7.20.7",
453
- "@types/mime-types": "2.1.4",
454
- "@types/prompts": "2.4.9",
455
- next: "^15.3.1",
456
- react: "19.0.0",
457
- "react-dom": "19.0.0",
458
- tsup: "8.4.0",
459
- tsx: "4.19.3",
460
- typescript: "5.8.3"
461
- }
462
- };
463
-
464
- // src/utils/preview/get-env-variables-for-preview-app.ts
465
- import path4 from "node:path";
466
- var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
467
- return {
468
- EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
469
- EMAILS_DIR_ABSOLUTE_PATH: path4.resolve(cwd, relativePathToEmailsDirectory),
470
- USER_PROJECT_LOCATION: cwd,
471
- NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT: isDev ? "true" : "false"
472
- };
473
- };
474
-
475
- // src/utils/preview/serve-static-file.ts
476
- import { existsSync, promises as fs3 } from "node:fs";
477
- import path5 from "node:path";
478
- import { lookup } from "mime-types";
479
- var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
480
- const pathname = parsedUrl.pathname.replace("/static", "./static");
481
- const ext = path5.parse(pathname).ext;
482
- const staticBaseDir = path5.resolve(process.cwd(), staticDirRelativePath);
483
- const fileAbsolutePath = path5.resolve(staticBaseDir, pathname);
484
- if (!fileAbsolutePath.startsWith(staticBaseDir)) {
485
- res.statusCode = 403;
486
- res.end();
487
- return;
488
- }
489
- try {
490
- const fileHandle = await fs3.open(fileAbsolutePath, "r");
491
- const fileData = await fs3.readFile(fileHandle);
492
- res.setHeader("Content-type", lookup(ext) || "text/plain");
493
- res.end(fileData);
494
- fileHandle.close();
495
- } catch (exception) {
496
- if (!existsSync(fileAbsolutePath)) {
497
- res.statusCode = 404;
498
- res.end();
499
- } else {
500
- const sanitizedFilePath = fileAbsolutePath.replace(/\n|\r/g, "");
501
- console.error(
502
- `Could not read file at ${sanitizedFilePath} to be served, here's the exception:`,
503
- exception
504
- );
505
- res.statusCode = 500;
506
- res.end(
507
- "Could not read file to be served! Check your terminal for more information."
508
- );
509
- }
510
- }
511
- };
512
-
513
- // src/utils/preview/start-dev-server.ts
514
- var devServer;
515
- var safeAsyncServerListen = (server, port) => {
516
- return new Promise((resolve) => {
517
- server.listen(port, () => {
518
- resolve({ portAlreadyInUse: false });
519
- });
520
- server.on("error", (e) => {
521
- if (e.code === "EADDRINUSE") {
522
- resolve({ portAlreadyInUse: true });
523
- }
524
- });
525
- });
526
- };
527
- var filename = url2.fileURLToPath(import.meta.url);
528
- var dirname = path6.dirname(filename);
529
- var isDev = !dirname.includes("dist");
530
- var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
531
- const [majorNodeVersion] = process.versions.node.split(".");
532
- if (majorNodeVersion && Number.parseInt(majorNodeVersion) < 18) {
533
- console.error(
534
- ` ${logSymbols3.error} Node ${majorNodeVersion} is not supported. Please upgrade to Node 18 or higher.`
535
- );
536
- process.exit(1);
537
- }
538
- const previewServerLocation = await getPreviewServerLocation();
539
- const previewServer = createJiti2(previewServerLocation);
540
- const { default: next } = await previewServer.import("next");
541
- devServer = http.createServer((req, res) => {
542
- if (!req.url) {
543
- res.end(404);
544
- return;
545
- }
546
- const parsedUrl = url2.parse(req.url, true);
547
- res.setHeader(
548
- "Cache-Control",
549
- "no-cache, max-age=0, must-revalidate, no-store"
550
- );
551
- res.setHeader("Pragma", "no-cache");
552
- res.setHeader("Expires", "-1");
553
- try {
554
- if (parsedUrl.path?.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
555
- void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
556
- } else if (!isNextReady) {
557
- void nextReadyPromise.then(
558
- () => nextHandleRequest?.(req, res, parsedUrl)
559
- );
560
- } else {
561
- void nextHandleRequest?.(req, res, parsedUrl);
562
- }
563
- } catch (e) {
564
- console.error("caught error", e);
565
- res.writeHead(500);
566
- res.end();
567
- }
568
- });
569
- const { portAlreadyInUse } = await safeAsyncServerListen(devServer, port);
570
- if (!portAlreadyInUse) {
571
- console.log(chalk.greenBright(` React Email ${package_default.version}`));
572
- console.log(` Running preview at: http://localhost:${port}
573
- `);
574
- } else {
575
- const nextPortToTry = port + 1;
576
- console.warn(
577
- ` ${logSymbols3.warning} Port ${port} is already in use, trying ${nextPortToTry}`
578
- );
579
- return startDevServer(
580
- emailsDirRelativePath,
581
- staticBaseDirRelativePath,
582
- nextPortToTry
583
- );
584
- }
585
- devServer.on("close", async () => {
586
- await app.close();
587
- });
588
- devServer.on("error", (e) => {
589
- spinner.stopAndPersist({
590
- symbol: logSymbols3.error,
591
- text: `Preview Server had an error: ${e}`
592
- });
593
- process.exit(1);
594
- });
595
- const spinner = ora2({
596
- text: "Getting react-email preview server ready...\n",
597
- prefixText: " "
598
- }).start();
599
- registerSpinnerAutostopping(spinner);
600
- const timeBeforeNextReady = performance.now();
601
- process.env = {
602
- NODE_ENV: "development",
603
- ...process.env,
604
- ...getEnvVariablesForPreviewApp(
605
- // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
606
- path6.normalize(emailsDirRelativePath),
607
- process.cwd()
608
- )
609
- };
610
- const app = next({
611
- // passing in env here does not get the environment variables there
612
- dev: isDev,
613
- conf: {
614
- images: {
615
- // This is to avoid the warning with sharp
616
- unoptimized: true
617
- }
618
- },
619
- hostname: "localhost",
620
- port,
621
- dir: previewServerLocation
622
- });
623
- let isNextReady = false;
624
- const nextReadyPromise = app.prepare();
625
- try {
626
- await nextReadyPromise;
627
- } catch (exception) {
628
- spinner.stopAndPersist({
629
- symbol: logSymbols3.error,
630
- text: ` Preview Server had an error: ${exception}`
631
- });
632
- process.exit(1);
633
- }
634
- isNextReady = true;
635
- const nextHandleRequest = app.getRequestHandler();
636
- const secondsToNextReady = ((performance.now() - timeBeforeNextReady) / 1e3).toFixed(1);
637
- spinner.stopAndPersist({
638
- text: `Ready in ${secondsToNextReady}s
639
- `,
640
- symbol: logSymbols3.success
641
- });
642
- return devServer;
643
- };
644
- var makeExitHandler = (options) => (codeSignalOrError) => {
645
- if (typeof devServer !== "undefined") {
646
- console.log("\nshutting down dev server");
647
- devServer.close();
648
- devServer = void 0;
649
- }
650
- if (codeSignalOrError instanceof Error) {
651
- console.error(codeSignalOrError);
652
- }
653
- if (options?.shouldKillProcess) {
654
- process.exit(options.killWithErrorCode ? 1 : 0);
433
+ });
434
+ }
435
+ spinner.text = "Setting Next environment variables for preview app to work properly";
436
+ await setNextEnvironmentVariablesForBuild(
437
+ emailsDirRelativePath,
438
+ builtPreviewAppPath
439
+ );
440
+ spinner.text = "Setting server side generation for the email preview pages";
441
+ await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
442
+ spinner.text = "Updating package.json's build and start scripts";
443
+ await updatePackageJson(builtPreviewAppPath);
444
+ spinner.text = "Installing dependencies on `.react-email`";
445
+ await npmInstall(builtPreviewAppPath, packageManager);
446
+ spinner.stopAndPersist({
447
+ text: "Successfully prepared `.react-email` for `next build`",
448
+ symbol: logSymbols2.success
449
+ });
450
+ await buildPreviewApp(builtPreviewAppPath);
451
+ } catch (error) {
452
+ console.log(error);
453
+ process.exit(1);
655
454
  }
656
455
  };
657
- process.on("exit", makeExitHandler());
658
- process.on(
659
- "SIGINT",
660
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
661
- );
662
- process.on(
663
- "SIGUSR1",
664
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
665
- );
666
- process.on(
667
- "SIGUSR2",
668
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
669
- );
670
- process.on(
671
- "uncaughtException",
672
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
673
- );
456
+
457
+ // src/commands/dev.ts
458
+ import fs6 from "node:fs";
459
+
460
+ // src/utils/preview/hot-reloading/setup-hot-reloading.ts
461
+ import path6 from "node:path";
462
+ import { watch } from "chokidar";
463
+ import debounce from "debounce";
464
+ import { Server as SocketServer } from "socket.io";
465
+
466
+ // src/utils/preview/hot-reloading/create-dependency-graph.ts
467
+ import { existsSync, promises as fs3, statSync } from "node:fs";
468
+ import path5 from "node:path";
674
469
 
675
470
  // src/utils/preview/hot-reloading/get-imported-modules.ts
676
471
  import { parse } from "@babel/parser";
@@ -718,7 +513,7 @@ var getImportedModules = (contents) => {
718
513
  };
719
514
 
720
515
  // src/utils/preview/hot-reloading/resolve-path-aliases.ts
721
- import path7 from "node:path";
516
+ import path4 from "node:path";
722
517
  import { createMatchPath, loadConfig } from "tsconfig-paths";
723
518
  var resolvePathAliases = (importPaths, projectPath) => {
724
519
  const configLoadResult = loadConfig(projectPath);
@@ -737,7 +532,7 @@ var resolvePathAliases = (importPaths, projectPath) => {
737
532
  ".mjs"
738
533
  ]);
739
534
  if (unaliasedPath) {
740
- return `./${path7.relative(projectPath, unaliasedPath)}`;
535
+ return `./${path4.relative(projectPath, unaliasedPath)}`;
741
536
  }
742
537
  return importedPath;
743
538
  });
@@ -748,9 +543,9 @@ var resolvePathAliases = (importPaths, projectPath) => {
748
543
  // src/utils/preview/hot-reloading/create-dependency-graph.ts
749
544
  var readAllFilesInsideDirectory = async (directory) => {
750
545
  let allFilePaths = [];
751
- const topLevelDirents = await fs4.readdir(directory, { withFileTypes: true });
546
+ const topLevelDirents = await fs3.readdir(directory, { withFileTypes: true });
752
547
  for await (const dirent of topLevelDirents) {
753
- const pathToDirent = path8.join(directory, dirent.name);
548
+ const pathToDirent = path5.join(directory, dirent.name);
754
549
  if (dirent.isDirectory()) {
755
550
  allFilePaths = allFilePaths.concat(
756
551
  await readAllFilesInsideDirectory(pathToDirent)
@@ -762,26 +557,26 @@ var readAllFilesInsideDirectory = async (directory) => {
762
557
  return allFilePaths;
763
558
  };
764
559
  var isJavascriptModule = (filePath) => {
765
- const extensionName = path8.extname(filePath);
560
+ const extensionName = path5.extname(filePath);
766
561
  return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
767
562
  };
768
563
  var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
769
- if (existsSync2(`${pathWithoutExtension}.ts`)) {
564
+ if (existsSync(`${pathWithoutExtension}.ts`)) {
770
565
  return `${pathWithoutExtension}.ts`;
771
566
  }
772
- if (existsSync2(`${pathWithoutExtension}.tsx`)) {
567
+ if (existsSync(`${pathWithoutExtension}.tsx`)) {
773
568
  return `${pathWithoutExtension}.tsx`;
774
569
  }
775
- if (existsSync2(`${pathWithoutExtension}.js`)) {
570
+ if (existsSync(`${pathWithoutExtension}.js`)) {
776
571
  return `${pathWithoutExtension}.js`;
777
572
  }
778
- if (existsSync2(`${pathWithoutExtension}.jsx`)) {
573
+ if (existsSync(`${pathWithoutExtension}.jsx`)) {
779
574
  return `${pathWithoutExtension}.jsx`;
780
575
  }
781
- if (existsSync2(`${pathWithoutExtension}.mjs`)) {
576
+ if (existsSync(`${pathWithoutExtension}.mjs`)) {
782
577
  return `${pathWithoutExtension}.mjs`;
783
578
  }
784
- if (existsSync2(`${pathWithoutExtension}.cjs`)) {
579
+ if (existsSync(`${pathWithoutExtension}.cjs`)) {
785
580
  return `${pathWithoutExtension}.cjs`;
786
581
  }
787
582
  };
@@ -800,15 +595,15 @@ var createDependencyGraph = async (directory) => {
800
595
  ])
801
596
  );
802
597
  const getDependencyPaths = async (filePath) => {
803
- const contents = await fs4.readFile(filePath, "utf8");
804
- 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)) : [];
805
600
  const importedPathsRelativeToDirectory = importedPaths.map(
806
601
  (dependencyPath) => {
807
602
  const isModulePath = !dependencyPath.startsWith(".");
808
- if (isModulePath || path8.isAbsolute(dependencyPath)) {
603
+ if (isModulePath || path5.isAbsolute(dependencyPath)) {
809
604
  return dependencyPath;
810
605
  }
811
- let pathToDependencyFromDirectory = path8.resolve(
606
+ let pathToDependencyFromDirectory = path5.resolve(
812
607
  /*
813
608
  path.resolve resolves paths differently from what imports on javascript do.
814
609
 
@@ -816,7 +611,7 @@ var createDependencyGraph = async (directory) => {
816
611
  would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
817
612
  one the import is meant to go to
818
613
  */
819
- path8.dirname(filePath),
614
+ path5.dirname(filePath),
820
615
  dependencyPath
821
616
  );
822
617
  let isDirectory = false;
@@ -831,15 +626,15 @@ var createDependencyGraph = async (directory) => {
831
626
  );
832
627
  if (pathWithExtension) {
833
628
  pathToDependencyFromDirectory = pathWithExtension;
834
- } else if (isDev) {
629
+ } else {
835
630
  console.warn(
836
631
  `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
837
632
  );
838
633
  }
839
634
  }
840
- const extension = path8.extname(pathToDependencyFromDirectory);
635
+ const extension = path5.extname(pathToDependencyFromDirectory);
841
636
  const pathWithEnsuredExtension = (() => {
842
- if (extension.length > 0 && existsSync2(pathToDependencyFromDirectory)) {
637
+ if (extension.length > 0 && existsSync(pathToDependencyFromDirectory)) {
843
638
  return pathToDependencyFromDirectory;
844
639
  }
845
640
  return checkFileExtensionsUntilItExists(
@@ -848,7 +643,7 @@ var createDependencyGraph = async (directory) => {
848
643
  })();
849
644
  if (pathWithEnsuredExtension) {
850
645
  pathToDependencyFromDirectory = pathWithEnsuredExtension;
851
- } else if (isDev) {
646
+ } else {
852
647
  console.warn(
853
648
  `Could not find file at ${pathToDependencyFromDirectory}`
854
649
  );
@@ -857,10 +652,10 @@ var createDependencyGraph = async (directory) => {
857
652
  }
858
653
  );
859
654
  const moduleDependencies = importedPathsRelativeToDirectory.filter(
860
- (dependencyPath) => !dependencyPath.startsWith(".") && !path8.isAbsolute(dependencyPath)
655
+ (dependencyPath) => !dependencyPath.startsWith(".") && !path5.isAbsolute(dependencyPath)
861
656
  );
862
657
  const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
863
- (dependencyPath) => dependencyPath.startsWith(".") || path8.isAbsolute(dependencyPath)
658
+ (dependencyPath) => dependencyPath.startsWith(".") || path5.isAbsolute(dependencyPath)
864
659
  );
865
660
  return {
866
661
  dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
@@ -991,14 +786,14 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
991
786
  changes.filter(
992
787
  (change) => (
993
788
  // Ensures only changes inside the emails directory are emitted
994
- path9.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
789
+ path6.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
995
790
  )
996
791
  )
997
792
  );
998
793
  });
999
794
  changes = [];
1000
795
  }, 150);
1001
- const absolutePathToEmailsDirectory = path9.resolve(
796
+ const absolutePathToEmailsDirectory = path6.resolve(
1002
797
  process.cwd(),
1003
798
  emailDirRelativePath
1004
799
  );
@@ -1008,7 +803,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1008
803
  cwd: absolutePathToEmailsDirectory
1009
804
  });
1010
805
  const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
1011
- (p) => path9.relative(absolutePathToEmailsDirectory, p).startsWith("..")
806
+ (p) => path6.relative(absolutePathToEmailsDirectory, p).startsWith("..")
1012
807
  );
1013
808
  let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
1014
809
  for (const p of filesOutsideEmailsDirectory) {
@@ -1020,11 +815,11 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1020
815
  process.on("SIGINT", exit);
1021
816
  process.on("uncaughtException", exit);
1022
817
  watcher.on("all", async (event, relativePathToChangeTarget) => {
1023
- const file = relativePathToChangeTarget.split(path9.sep);
818
+ const file = relativePathToChangeTarget.split(path6.sep);
1024
819
  if (file.length === 0) {
1025
820
  return;
1026
821
  }
1027
- const pathToChangeTarget = path9.resolve(
822
+ const pathToChangeTarget = path6.resolve(
1028
823
  absolutePathToEmailsDirectory,
1029
824
  relativePathToChangeTarget
1030
825
  );
@@ -1048,7 +843,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1048
843
  for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
1049
844
  changes.push({
1050
845
  event: "change",
1051
- filename: path9.relative(absolutePathToEmailsDirectory, dependentPath)
846
+ filename: path6.relative(absolutePathToEmailsDirectory, dependentPath)
1052
847
  });
1053
848
  }
1054
849
  reload();
@@ -1056,6 +851,223 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
1056
851
  return watcher;
1057
852
  };
1058
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
+
1059
1071
  // src/utils/tree.ts
1060
1072
  import { promises as fs5 } from "node:fs";
1061
1073
  import os from "node:os";
@@ -1070,8 +1082,8 @@ var SYMBOLS = {
1070
1082
  var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
1071
1083
  const base = process.cwd();
1072
1084
  const dirFullpath = path10.resolve(base, dirPath);
1073
- const dirname2 = path10.basename(dirFullpath);
1074
- let lines = [dirname2];
1085
+ const dirname = path10.basename(dirFullpath);
1086
+ let lines = [dirname];
1075
1087
  const dirStat = await fs5.stat(dirFullpath);
1076
1088
  if (dirStat.isDirectory() && currentDepth < depth) {
1077
1089
  const childDirents = await fs5.readdir(dirFullpath, { withFileTypes: true });
@@ -1200,15 +1212,15 @@ var renderingUtilitiesExporter = (emailTemplates) => ({
1200
1212
  var getEmailTemplatesFromDirectory = (emailDirectory) => {
1201
1213
  const templatePaths = [];
1202
1214
  emailDirectory.emailFilenames.forEach(
1203
- (filename3) => templatePaths.push(path12.join(emailDirectory.absolutePath, filename3))
1215
+ (filename2) => templatePaths.push(path12.join(emailDirectory.absolutePath, filename2))
1204
1216
  );
1205
1217
  emailDirectory.subDirectories.forEach((directory) => {
1206
1218
  templatePaths.push(...getEmailTemplatesFromDirectory(directory));
1207
1219
  });
1208
1220
  return templatePaths;
1209
1221
  };
1210
- var filename2 = url3.fileURLToPath(import.meta.url);
1211
- var require2 = createRequire(filename2);
1222
+ var filename = url3.fileURLToPath(import.meta.url);
1223
+ var require2 = createRequire(filename);
1212
1224
  var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
1213
1225
  if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
1214
1226
  fs8.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });