react-email 3.0.6 → 3.0.7-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cli/index.js +762 -766
  3. package/dist/cli/index.mjs +474 -482
  4. package/dist/preview/.next/BUILD_ID +1 -1
  5. package/dist/preview/.next/app-build-manifest.json +6 -6
  6. package/dist/preview/.next/build-manifest.json +2 -2
  7. package/dist/preview/.next/cache/.rscinfo +1 -1
  8. package/dist/preview/.next/cache/webpack/client-production/0.pack +0 -0
  9. package/dist/preview/.next/cache/webpack/client-production/index.pack +0 -0
  10. package/dist/preview/.next/cache/webpack/edge-server-production/index.pack +0 -0
  11. package/dist/preview/.next/cache/webpack/server-production/0.pack +0 -0
  12. package/dist/preview/.next/cache/webpack/server-production/index.pack +0 -0
  13. package/dist/preview/.next/next-minimal-server.js.nft.json +1 -1
  14. package/dist/preview/.next/next-server.js.nft.json +1 -1
  15. package/dist/preview/.next/prerender-manifest.json +1 -1
  16. package/dist/preview/.next/server/app/_not-found/page.js +1 -1
  17. package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/dist/preview/.next/server/app/page.js +1 -1
  19. package/dist/preview/.next/server/app/page.js.nft.json +1 -1
  20. package/dist/preview/.next/server/app/page_client-reference-manifest.js +1 -1
  21. package/dist/preview/.next/server/app/preview/[...slug]/page.js +6 -6
  22. package/dist/preview/.next/server/app/preview/[...slug]/page.js.nft.json +1 -1
  23. package/dist/preview/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -1
  24. package/dist/preview/.next/server/chunks/{391.js → 182.js} +1 -1
  25. package/dist/preview/.next/server/pages/500.html +1 -1
  26. package/dist/preview/.next/server/server-reference-manifest.js +1 -1
  27. package/dist/preview/.next/server/server-reference-manifest.json +1 -1
  28. package/dist/preview/.next/static/chunks/154-a7edfb1cff4e70ad.js +1 -0
  29. package/dist/preview/.next/static/chunks/app/{layout-a2901ed1c2c53661.js → layout-b6c0ec09f1386be1.js} +1 -1
  30. package/dist/preview/.next/static/chunks/app/{page-54a86772095e22e0.js → page-36853df2e13e583f.js} +1 -1
  31. package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-3230db14d341df1e.js +1 -0
  32. package/dist/preview/.next/static/css/{eb0a93282704d7ab.css → a34876a6c565fff8.css} +1 -1
  33. package/dist/preview/.next/trace +21 -21
  34. package/package.json +5 -9
  35. package/postcss.config.js +1 -1
  36. package/src/actions/get-email-path-from-slug.ts +7 -4
  37. package/src/actions/render-email-by-path.tsx +3 -3
  38. package/src/app/layout.tsx +1 -1
  39. package/src/app/page.tsx +1 -1
  40. package/src/app/preview/[...slug]/page.tsx +2 -2
  41. package/src/app/preview/[...slug]/preview.tsx +2 -2
  42. package/src/components/button.tsx +1 -1
  43. package/src/components/code-container.tsx +1 -1
  44. package/src/components/heading.tsx +1 -1
  45. package/src/components/sidebar/sidebar-directory-children.tsx +5 -8
  46. package/src/components/sidebar/sidebar-directory.tsx +2 -2
  47. package/src/components/sidebar/sidebar.tsx +2 -2
  48. package/src/components/text.tsx +1 -1
  49. package/src/components/tooltip-content.tsx +1 -1
  50. package/src/components/tooltip.tsx +1 -1
  51. package/src/components/topbar.tsx +1 -1
  52. package/src/hooks/use-email-rendering-result.ts +2 -2
  53. package/src/utils/cn.ts +1 -1
  54. package/src/utils/esbuild/renderring-utilities-exporter.ts +1 -1
  55. package/src/utils/get-email-component.ts +6 -6
  56. package/src/utils/get-emails-directory-metadata.spec.ts +0 -1
  57. package/src/utils/improve-error-with-sourcemap.ts +1 -1
  58. package/src/utils/static-node-modules-for-vm.ts +6 -6
  59. package/tsconfig.json +1 -6
  60. package/.eslintrc.js +0 -52
  61. package/.prettierignore +0 -3
  62. package/.prettierrc.js +0 -8
  63. package/dist/preview/.next/cache/eslint/.cache_1c3sgg +0 -1
  64. package/dist/preview/.next/static/chunks/154-4202f86af36ccff4.js +0 -1
  65. package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-2bfad134b65ddd79.js +0 -1
  66. /package/dist/preview/.next/static/{Trk1e7GzgKOLunAXBDCy- → kZJA3j5UusCUstgLxRPPH}/_buildManifest.js +0 -0
  67. /package/dist/preview/.next/static/{Trk1e7GzgKOLunAXBDCy- → kZJA3j5UusCUstgLxRPPH}/_ssgManifest.js +0 -0
@@ -13,7 +13,7 @@ import { program } from "commander";
13
13
  // package.json
14
14
  var package_default = {
15
15
  name: "react-email",
16
- version: "3.0.6",
16
+ version: "3.0.7-canary.1",
17
17
  description: "A live preview of your emails right in your browser.",
18
18
  bin: {
19
19
  email: "./dist/cli/index.js"
@@ -23,8 +23,7 @@ var package_default = {
23
23
  dev: "tsup-node --watch",
24
24
  test: "vitest run",
25
25
  "test:watch": "vitest",
26
- clean: "rm -rf dist",
27
- lint: "eslint . && tsc"
26
+ clean: "rm -rf dist"
28
27
  },
29
28
  license: "MIT",
30
29
  repository: {
@@ -32,10 +31,7 @@ var package_default = {
32
31
  url: "https://github.com/resend/react-email.git",
33
32
  directory: "packages/react-email"
34
33
  },
35
- keywords: [
36
- "react",
37
- "email"
38
- ],
34
+ keywords: ["react", "email"],
39
35
  engines: {
40
36
  node: ">=18.0.0"
41
37
  },
@@ -46,14 +42,14 @@ var package_default = {
46
42
  chokidar: "4.0.3",
47
43
  commander: "11.1.0",
48
44
  debounce: "2.0.0",
49
- esbuild: "0.19.11",
45
+ esbuild: "0.23.0",
50
46
  glob: "10.3.4",
51
47
  "log-symbols": "4.1.0",
52
48
  "mime-types": "2.1.35",
53
49
  next: "15.1.2",
54
50
  "normalize-path": "3.0.0",
55
51
  ora: "5.4.1",
56
- "socket.io": "4.8.0"
52
+ "socket.io": "4.8.1"
57
53
  },
58
54
  devDependencies: {
59
55
  "@radix-ui/colors": "1.0.1",
@@ -75,9 +71,6 @@ var package_default = {
75
71
  "@vercel/style-guide": "5.1.0",
76
72
  autoprefixer: "10.4.20",
77
73
  clsx: "2.1.0",
78
- eslint: "8.50.0",
79
- "eslint-config-prettier": "9.0.0",
80
- "eslint-config-turbo": "2.1.0",
81
74
  "framer-motion": "12.0.0-alpha.2",
82
75
  postcss: "8.4.40",
83
76
  "prism-react-renderer": "2.1.0",
@@ -97,13 +90,112 @@ var package_default = {
97
90
  }
98
91
  };
99
92
 
100
- // src/cli/commands/dev.ts
101
- import fs4 from "node:fs";
93
+ // src/cli/commands/build.ts
94
+ import { spawn } from "node:child_process";
95
+ import fs5 from "node:fs";
96
+ import path8 from "node:path";
97
+ import logSymbols3 from "log-symbols";
98
+ import ora2 from "ora";
99
+
100
+ // src/utils/get-emails-directory-metadata.ts
101
+ import fs from "node:fs";
102
+ import path from "node:path";
103
+ var isFileAnEmail = (fullPath) => {
104
+ const stat = fs.statSync(fullPath);
105
+ if (stat.isDirectory())
106
+ return false;
107
+ const { ext } = path.parse(fullPath);
108
+ if (![".js", ".tsx", ".jsx"].includes(ext))
109
+ return false;
110
+ if (!fs.existsSync(fullPath)) {
111
+ return false;
112
+ }
113
+ const fileContents = fs.readFileSync(fullPath, "utf8");
114
+ return /\bexport\s+default\b/gm.test(fileContents);
115
+ };
116
+ var mergeDirectoriesWithSubDirectories = (emailsDirectoryMetadata) => {
117
+ let currentResultingMergedDirectory = emailsDirectoryMetadata;
118
+ while (currentResultingMergedDirectory.emailFilenames.length === 0 && currentResultingMergedDirectory.subDirectories.length === 1) {
119
+ const onlySubDirectory = currentResultingMergedDirectory.subDirectories[0];
120
+ currentResultingMergedDirectory = {
121
+ ...onlySubDirectory,
122
+ directoryName: path.join(
123
+ currentResultingMergedDirectory.directoryName,
124
+ onlySubDirectory.directoryName
125
+ )
126
+ };
127
+ }
128
+ return currentResultingMergedDirectory;
129
+ };
130
+ var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToEmailsDirectory) => {
131
+ if (!fs.existsSync(absolutePathToEmailsDirectory))
132
+ return;
133
+ const dirents = await fs.promises.readdir(absolutePathToEmailsDirectory, {
134
+ withFileTypes: true
135
+ });
136
+ const emailFilenames = dirents.filter(
137
+ (dirent) => isFileAnEmail(path.join(absolutePathToEmailsDirectory, dirent.name))
138
+ ).map(
139
+ (dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path.extname(dirent.name), "")
140
+ );
141
+ const subDirectories = await Promise.all(
142
+ dirents.filter(
143
+ (dirent) => dirent.isDirectory() && !dirent.name.startsWith("_") && dirent.name !== "static"
144
+ ).map((dirent) => {
145
+ const direntAbsolutePath = path.join(
146
+ absolutePathToEmailsDirectory,
147
+ dirent.name
148
+ );
149
+ return getEmailsDirectoryMetadata(
150
+ direntAbsolutePath,
151
+ keepFileExtensions,
152
+ true,
153
+ baseDirectoryPath
154
+ );
155
+ })
156
+ );
157
+ const emailsMetadata = {
158
+ absolutePath: absolutePathToEmailsDirectory,
159
+ relativePath: path.relative(
160
+ baseDirectoryPath,
161
+ absolutePathToEmailsDirectory
162
+ ),
163
+ directoryName: absolutePathToEmailsDirectory.split(path.sep).pop(),
164
+ emailFilenames,
165
+ subDirectories
166
+ };
167
+ return isSubDirectory ? mergeDirectoriesWithSubDirectories(emailsMetadata) : emailsMetadata;
168
+ };
169
+
170
+ // src/utils/register-spinner-autostopping.ts
171
+ import logSymbols from "log-symbols";
172
+ var spinners = /* @__PURE__ */ new Set();
173
+ process.on("SIGINT", () => {
174
+ spinners.forEach((spinner) => {
175
+ if (spinner.isSpinning) {
176
+ spinner.stop();
177
+ }
178
+ });
179
+ });
180
+ process.on("exit", (code) => {
181
+ if (code !== 0) {
182
+ spinners.forEach((spinner) => {
183
+ if (spinner.isSpinning) {
184
+ spinner.stopAndPersist({
185
+ symbol: logSymbols.error
186
+ });
187
+ }
188
+ });
189
+ }
190
+ });
191
+ var registerSpinnerAutostopping = (spinner) => {
192
+ spinners.add(spinner);
193
+ };
102
194
 
103
195
  // src/cli/utils/tree.ts
104
- import { promises as fs } from "node:fs";
196
+ import { promises as fs2 } from "node:fs";
105
197
  import os from "node:os";
106
- import path from "node:path";
198
+ import path2 from "node:path";
107
199
  var SYMBOLS = {
108
200
  BRANCH: "\u251C\u2500\u2500 ",
109
201
  EMPTY: "",
@@ -113,12 +205,12 @@ var SYMBOLS = {
113
205
  };
114
206
  var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
115
207
  const base = process.cwd();
116
- const dirFullpath = path.resolve(base, dirPath);
117
- const dirname = path.basename(dirFullpath);
208
+ const dirFullpath = path2.resolve(base, dirPath);
209
+ const dirname = path2.basename(dirFullpath);
118
210
  let lines = [dirname];
119
- const dirStat = await fs.stat(dirFullpath);
211
+ const dirStat = await fs2.stat(dirFullpath);
120
212
  if (dirStat.isDirectory() && currentDepth < depth) {
121
- const childDirents = await fs.readdir(dirFullpath, { withFileTypes: true });
213
+ const childDirents = await fs2.readdir(dirFullpath, { withFileTypes: true });
122
214
  childDirents.sort((a, b) => {
123
215
  if (a.isDirectory() && b.isFile()) {
124
216
  return -1;
@@ -136,7 +228,7 @@ var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
136
228
  if (dirent.isFile()) {
137
229
  lines.push(`${branchingSymbol}${dirent.name}`);
138
230
  } else {
139
- const pathToDirectory = path.join(dirFullpath, dirent.name);
231
+ const pathToDirectory = path2.join(dirFullpath, dirent.name);
140
232
  const treeLinesForSubDirectory = await getTreeLines(
141
233
  pathToDirectory,
142
234
  depth,
@@ -158,98 +250,46 @@ var tree = async (dirPath, depth) => {
158
250
  };
159
251
 
160
252
  // src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts
161
- import path6 from "node:path";
162
- import { Server as SocketServer } from "socket.io";
253
+ import path7 from "node:path";
163
254
  import { watch } from "chokidar";
164
255
  import debounce from "debounce";
256
+ import { Server as SocketServer } from "socket.io";
165
257
 
166
258
  // src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
167
- import path5 from "node:path";
168
- import { existsSync, promises as fs3, statSync } from "node:fs";
169
-
170
- // src/cli/utils/preview/hot-reloading/get-imported-modules.ts
171
- import { traverse } from "@babel/core";
172
- import { parse } from "@babel/parser";
173
- var getImportedModules = (contents) => {
174
- const importedPaths = [];
175
- const parsedContents = parse(contents, {
176
- sourceType: "unambiguous",
177
- strictMode: false,
178
- errorRecovery: true,
179
- plugins: ["jsx", "typescript", "decorators"]
180
- });
181
- traverse(parsedContents, {
182
- ImportDeclaration({ node }) {
183
- importedPaths.push(node.source.value);
184
- },
185
- ExportAllDeclaration({ node }) {
186
- importedPaths.push(node.source.value);
187
- },
188
- ExportNamedDeclaration({ node }) {
189
- if (node.source) {
190
- importedPaths.push(node.source.value);
191
- }
192
- },
193
- CallExpression({ node }) {
194
- if ("name" in node.callee && node.callee.name === "require") {
195
- if (node.arguments.length === 1) {
196
- const importPathNode = node.arguments[0];
197
- if (importPathNode.type === "StringLiteral") {
198
- importedPaths.push(importPathNode.value);
199
- }
200
- }
201
- }
202
- }
203
- });
204
- return importedPaths;
205
- };
259
+ import { promises as fs4, existsSync, statSync } from "node:fs";
260
+ import path6 from "node:path";
206
261
 
207
262
  // src/cli/utils/preview/start-dev-server.ts
208
- import path4 from "node:path";
209
263
  import http from "node:http";
264
+ import path5 from "node:path";
210
265
  import url from "node:url";
266
+ import chalk from "chalk";
267
+ import logSymbols2 from "log-symbols";
211
268
  import next from "next";
212
269
  import ora from "ora";
213
- import logSymbols2 from "log-symbols";
214
- import chalk from "chalk";
215
270
 
216
- // src/utils/register-spinner-autostopping.ts
217
- import logSymbols from "log-symbols";
218
- var spinners = /* @__PURE__ */ new Set();
219
- process.on("SIGINT", () => {
220
- spinners.forEach((spinner) => {
221
- if (spinner.isSpinning) {
222
- spinner.stop();
223
- }
224
- });
225
- });
226
- process.on("exit", (code) => {
227
- if (code !== 0) {
228
- spinners.forEach((spinner) => {
229
- if (spinner.isSpinning) {
230
- spinner.stopAndPersist({
231
- symbol: logSymbols.error
232
- });
233
- }
234
- });
235
- }
236
- });
237
- var registerSpinnerAutostopping = (spinner) => {
238
- spinners.add(spinner);
271
+ // src/cli/utils/preview/get-env-variables-for-preview-app.ts
272
+ import path3 from "node:path";
273
+ var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
274
+ return {
275
+ EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
276
+ EMAILS_DIR_ABSOLUTE_PATH: path3.resolve(cwd, relativePathToEmailsDirectory),
277
+ USER_PROJECT_LOCATION: cwd
278
+ };
239
279
  };
240
280
 
241
281
  // src/cli/utils/preview/serve-static-file.ts
242
- import path2 from "node:path";
243
- import { promises as fs2 } from "node:fs";
282
+ import { promises as fs3 } from "node:fs";
283
+ import path4 from "node:path";
244
284
  import { lookup } from "mime-types";
245
285
  var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
246
- const staticBaseDir = path2.join(process.cwd(), staticDirRelativePath);
286
+ const staticBaseDir = path4.join(process.cwd(), staticDirRelativePath);
247
287
  const pathname = parsedUrl.pathname;
248
- const ext = path2.parse(pathname).ext;
249
- let fileAbsolutePath = path2.join(staticBaseDir, pathname);
250
- const fileHandle = await fs2.open(fileAbsolutePath, "r");
288
+ const ext = path4.parse(pathname).ext;
289
+ const fileAbsolutePath = path4.join(staticBaseDir, pathname);
290
+ const fileHandle = await fs3.open(fileAbsolutePath, "r");
251
291
  try {
252
- const fileData = await fs2.readFile(fileHandle);
292
+ const fileData = await fs3.readFile(fileHandle);
253
293
  res.setHeader("Content-type", lookup(ext) || "text/plain");
254
294
  res.end(fileData);
255
295
  } catch (exception) {
@@ -266,16 +306,6 @@ var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
266
306
  }
267
307
  };
268
308
 
269
- // src/cli/utils/preview/get-env-variables-for-preview-app.ts
270
- import path3 from "node:path";
271
- var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
272
- return {
273
- EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
274
- EMAILS_DIR_ABSOLUTE_PATH: path3.resolve(cwd, relativePathToEmailsDirectory),
275
- USER_PROJECT_LOCATION: cwd
276
- };
277
- };
278
-
279
309
  // src/cli/utils/preview/start-dev-server.ts
280
310
  var devServer;
281
311
  var safeAsyncServerListen = (server, port) => {
@@ -290,9 +320,9 @@ var safeAsyncServerListen = (server, port) => {
290
320
  });
291
321
  });
292
322
  };
293
- var isDev = !__filename.endsWith(path4.join("cli", "index.js"));
294
- var cliPacakgeLocation = isDev ? path4.resolve(__dirname, "../../../..") : path4.resolve(__dirname, "../..");
295
- var previewServerLocation = isDev ? path4.resolve(__dirname, "../../../..") : path4.resolve(__dirname, "../preview");
323
+ var isDev = !__filename.endsWith(path5.join("cli", "index.js"));
324
+ var cliPacakgeLocation = isDev ? path5.resolve(__dirname, "../../../..") : path5.resolve(__dirname, "../..");
325
+ var previewServerLocation = isDev ? path5.resolve(__dirname, "../../../..") : path5.resolve(__dirname, "../preview");
296
326
  var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
297
327
  devServer = http.createServer((req, res) => {
298
328
  if (!req.url) {
@@ -307,7 +337,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
307
337
  res.setHeader("Pragma", "no-cache");
308
338
  res.setHeader("Expires", "-1");
309
339
  try {
310
- if (parsedUrl.path && parsedUrl.path.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
340
+ if (parsedUrl.path?.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
311
341
  void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
312
342
  } else if (!isNextReady) {
313
343
  void nextReadyPromise.then(
@@ -355,11 +385,11 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
355
385
  registerSpinnerAutostopping(spinner);
356
386
  const timeBeforeNextReady = performance.now();
357
387
  process.env = {
358
- ...process.env,
359
388
  NODE_ENV: "development",
389
+ ...process.env,
360
390
  ...getEnvVariablesForPreviewApp(
361
391
  // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
362
- path4.normalize(emailsDirRelativePath),
392
+ path5.normalize(emailsDirRelativePath),
363
393
  process.cwd()
364
394
  )
365
395
  };
@@ -417,12 +447,49 @@ process.on(
417
447
  makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
418
448
  );
419
449
 
450
+ // src/cli/utils/preview/hot-reloading/get-imported-modules.ts
451
+ import { traverse } from "@babel/core";
452
+ import { parse } from "@babel/parser";
453
+ var getImportedModules = (contents) => {
454
+ const importedPaths = [];
455
+ const parsedContents = parse(contents, {
456
+ sourceType: "unambiguous",
457
+ strictMode: false,
458
+ errorRecovery: true,
459
+ plugins: ["jsx", "typescript", "decorators"]
460
+ });
461
+ traverse(parsedContents, {
462
+ ImportDeclaration({ node }) {
463
+ importedPaths.push(node.source.value);
464
+ },
465
+ ExportAllDeclaration({ node }) {
466
+ importedPaths.push(node.source.value);
467
+ },
468
+ ExportNamedDeclaration({ node }) {
469
+ if (node.source) {
470
+ importedPaths.push(node.source.value);
471
+ }
472
+ },
473
+ CallExpression({ node }) {
474
+ if ("name" in node.callee && node.callee.name === "require") {
475
+ if (node.arguments.length === 1) {
476
+ const importPathNode = node.arguments[0];
477
+ if (importPathNode.type === "StringLiteral") {
478
+ importedPaths.push(importPathNode.value);
479
+ }
480
+ }
481
+ }
482
+ }
483
+ });
484
+ return importedPaths;
485
+ };
486
+
420
487
  // src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
421
488
  var readAllFilesInsideDirectory = async (directory) => {
422
489
  let allFilePaths = [];
423
- const topLevelDirents = await fs3.readdir(directory, { withFileTypes: true });
490
+ const topLevelDirents = await fs4.readdir(directory, { withFileTypes: true });
424
491
  for await (const dirent of topLevelDirents) {
425
- const pathToDirent = path5.join(directory, dirent.name);
492
+ const pathToDirent = path6.join(directory, dirent.name);
426
493
  if (dirent.isDirectory()) {
427
494
  allFilePaths = allFilePaths.concat(
428
495
  await readAllFilesInsideDirectory(pathToDirent)
@@ -434,7 +501,7 @@ var readAllFilesInsideDirectory = async (directory) => {
434
501
  return allFilePaths;
435
502
  };
436
503
  var isJavascriptModule = (filePath) => {
437
- const extensionName = path5.extname(filePath);
504
+ const extensionName = path6.extname(filePath);
438
505
  return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
439
506
  };
440
507
  var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
@@ -472,64 +539,63 @@ var createDependencyGraph = async (directory) => {
472
539
  ])
473
540
  );
474
541
  const getDependencyPaths = async (filePath) => {
475
- const contents = await fs3.readFile(filePath, "utf8");
542
+ const contents = await fs4.readFile(filePath, "utf8");
476
543
  const importedPaths = getImportedModules(contents);
477
544
  const importedPathsRelativeToDirectory = importedPaths.map(
478
545
  (dependencyPath) => {
479
546
  const isModulePath = !dependencyPath.startsWith(".");
480
- if (!isModulePath && !path5.isAbsolute(dependencyPath)) {
481
- let pathToDependencyFromDirectory = path5.resolve(
482
- /*
483
- path.resolve resolves paths differently from what imports on javascript do.
484
-
485
- So if we wouldn't do this, for an email at "/path/to/email.tsx" with a dependecy path of "./other-email"
486
- would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
487
- one the import is meant to go to
488
- */
489
- path5.dirname(filePath),
490
- dependencyPath
547
+ if (isModulePath || path6.isAbsolute(dependencyPath)) {
548
+ return dependencyPath;
549
+ }
550
+ let pathToDependencyFromDirectory = path6.resolve(
551
+ /*
552
+ path.resolve resolves paths differently from what imports on javascript do.
553
+
554
+ So if we wouldn't do this, for an email at "/path/to/email.tsx" with a dependecy path of "./other-email"
555
+ would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
556
+ one the import is meant to go to
557
+ */
558
+ path6.dirname(filePath),
559
+ dependencyPath
560
+ );
561
+ let isDirectory = false;
562
+ try {
563
+ isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
564
+ } catch (_) {
565
+ }
566
+ if (isDirectory) {
567
+ const pathToSubDirectory = pathToDependencyFromDirectory;
568
+ const pathWithExtension = checkFileExtensionsUntilItExists(
569
+ `${pathToSubDirectory}/index`
491
570
  );
492
- let isDirectory = false;
493
- try {
494
- isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
495
- } catch (_) {
496
- }
497
- if (isDirectory) {
498
- const pathToSubDirectory = pathToDependencyFromDirectory;
499
- const pathWithExtension = checkFileExtensionsUntilItExists(
500
- `${pathToSubDirectory}/index`
571
+ if (pathWithExtension) {
572
+ pathToDependencyFromDirectory = pathWithExtension;
573
+ } else if (isDev) {
574
+ console.warn(
575
+ `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
501
576
  );
502
- if (pathWithExtension) {
503
- pathToDependencyFromDirectory = pathWithExtension;
504
- } else if (isDev) {
505
- console.warn(
506
- `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
507
- );
508
- }
509
577
  }
510
- if (!isJavascriptModule(pathToDependencyFromDirectory)) {
511
- const pathWithExtension = checkFileExtensionsUntilItExists(
512
- pathToDependencyFromDirectory
578
+ }
579
+ if (!isJavascriptModule(pathToDependencyFromDirectory)) {
580
+ const pathWithExtension = checkFileExtensionsUntilItExists(
581
+ pathToDependencyFromDirectory
582
+ );
583
+ if (pathWithExtension) {
584
+ pathToDependencyFromDirectory = pathWithExtension;
585
+ } else if (isDev) {
586
+ console.warn(
587
+ `Could not determine the file extension for the file at ${pathToDependencyFromDirectory}`
513
588
  );
514
- if (pathWithExtension) {
515
- pathToDependencyFromDirectory = pathWithExtension;
516
- } else if (isDev) {
517
- console.warn(
518
- `Could not determine the file extension for the file at ${pathToDependencyFromDirectory}`
519
- );
520
- }
521
589
  }
522
- return pathToDependencyFromDirectory;
523
- } else {
524
- return dependencyPath;
525
590
  }
591
+ return pathToDependencyFromDirectory;
526
592
  }
527
593
  );
528
594
  const moduleDependencies = importedPathsRelativeToDirectory.filter(
529
- (dependencyPath) => !dependencyPath.startsWith(".") && !path5.isAbsolute(dependencyPath)
595
+ (dependencyPath) => !dependencyPath.startsWith(".") && !path6.isAbsolute(dependencyPath)
530
596
  );
531
597
  const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
532
- (dependencyPath) => dependencyPath.startsWith(".") || path5.isAbsolute(dependencyPath)
598
+ (dependencyPath) => dependencyPath.startsWith(".") || path6.isAbsolute(dependencyPath)
533
599
  );
534
600
  return {
535
601
  dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
@@ -658,7 +724,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
658
724
  });
659
725
  changes = [];
660
726
  }, 150);
661
- const absolutePathToEmailsDirectory = path6.resolve(
727
+ const absolutePathToEmailsDirectory = path7.resolve(
662
728
  process.cwd(),
663
729
  emailDirRelativePath
664
730
  );
@@ -668,7 +734,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
668
734
  cwd: absolutePathToEmailsDirectory
669
735
  });
670
736
  const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
671
- (p) => path6.relative(absolutePathToEmailsDirectory, p).startsWith("..")
737
+ (p) => path7.relative(absolutePathToEmailsDirectory, p).startsWith("..")
672
738
  );
673
739
  let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
674
740
  for (const p of filesOutsideEmailsDirectory) {
@@ -680,11 +746,11 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
680
746
  process.on("SIGINT", exit);
681
747
  process.on("uncaughtException", exit);
682
748
  watcher.on("all", async (event, relativePathToChangeTarget) => {
683
- const file = relativePathToChangeTarget.split(path6.sep);
749
+ const file = relativePathToChangeTarget.split(path7.sep);
684
750
  if (file.length === 0) {
685
751
  return;
686
752
  }
687
- const pathToChangeTarget = path6.resolve(
753
+ const pathToChangeTarget = path7.resolve(
688
754
  absolutePathToEmailsDirectory,
689
755
  relativePathToChangeTarget
690
756
  );
@@ -708,7 +774,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
708
774
  for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
709
775
  changes.push({
710
776
  event: "change",
711
- filename: path6.relative(absolutePathToEmailsDirectory, dependentPath)
777
+ filename: path7.relative(absolutePathToEmailsDirectory, dependentPath)
712
778
  });
713
779
  }
714
780
  reload();
@@ -716,300 +782,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
716
782
  return watcher;
717
783
  };
718
784
 
719
- // src/cli/commands/dev.ts
720
- var dev = async ({ dir: emailsDirRelativePath, port }) => {
721
- try {
722
- if (!fs4.existsSync(emailsDirRelativePath)) {
723
- console.error(`Missing ${emailsDirRelativePath} folder`);
724
- process.exit(1);
725
- }
726
- const devServer2 = await startDevServer(
727
- emailsDirRelativePath,
728
- emailsDirRelativePath,
729
- // defaults to ./emails/static for the static files that are served to the preview
730
- Number.parseInt(port)
731
- );
732
- await setupHotreloading(devServer2, emailsDirRelativePath);
733
- } catch (error) {
734
- console.log(error);
735
- process.exit(1);
736
- }
737
- };
738
-
739
- // src/cli/commands/export.ts
740
- import fs7, { unlinkSync, writeFileSync } from "node:fs";
741
- import path9 from "node:path";
742
- import { glob } from "glob";
743
- import { build } from "esbuild";
744
- import ora2 from "ora";
745
- import logSymbols3 from "log-symbols";
746
- import normalize from "normalize-path";
747
-
748
- // src/utils/get-emails-directory-metadata.ts
749
- import fs5 from "node:fs";
750
- import path7 from "node:path";
751
- var isFileAnEmail = (fullPath) => {
752
- const stat = fs5.statSync(fullPath);
753
- if (stat.isDirectory())
754
- return false;
755
- const { ext } = path7.parse(fullPath);
756
- if (![".js", ".tsx", ".jsx"].includes(ext))
757
- return false;
758
- if (!fs5.existsSync(fullPath)) {
759
- return false;
760
- }
761
- const fileContents = fs5.readFileSync(fullPath, "utf8");
762
- return /\bexport\s+default\b/gm.test(fileContents);
763
- };
764
- var mergeDirectoriesWithSubDirectories = (emailsDirectoryMetadata) => {
765
- let currentResultingMergedDirectory = emailsDirectoryMetadata;
766
- while (currentResultingMergedDirectory.emailFilenames.length === 0 && currentResultingMergedDirectory.subDirectories.length === 1) {
767
- const onlySubDirectory = currentResultingMergedDirectory.subDirectories[0];
768
- currentResultingMergedDirectory = {
769
- ...onlySubDirectory,
770
- directoryName: path7.join(
771
- currentResultingMergedDirectory.directoryName,
772
- onlySubDirectory.directoryName
773
- )
774
- };
775
- }
776
- return currentResultingMergedDirectory;
777
- };
778
- var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileExtensions = false, isSubDirectory = false, baseDirectoryPath = absolutePathToEmailsDirectory) => {
779
- if (!fs5.existsSync(absolutePathToEmailsDirectory))
780
- return;
781
- const dirents = await fs5.promises.readdir(absolutePathToEmailsDirectory, {
782
- withFileTypes: true
783
- });
784
- const emailFilenames = dirents.filter(
785
- (dirent) => isFileAnEmail(path7.join(absolutePathToEmailsDirectory, dirent.name))
786
- ).map(
787
- (dirent) => keepFileExtensions ? dirent.name : dirent.name.replace(path7.extname(dirent.name), "")
788
- );
789
- const subDirectories = await Promise.all(
790
- dirents.filter(
791
- (dirent) => dirent.isDirectory() && !dirent.name.startsWith("_") && dirent.name !== "static"
792
- ).map((dirent) => {
793
- const direntAbsolutePath = path7.join(
794
- absolutePathToEmailsDirectory,
795
- dirent.name
796
- );
797
- return getEmailsDirectoryMetadata(
798
- direntAbsolutePath,
799
- keepFileExtensions,
800
- true,
801
- baseDirectoryPath
802
- );
803
- })
804
- );
805
- const emailsMetadata = {
806
- absolutePath: absolutePathToEmailsDirectory,
807
- relativePath: path7.relative(
808
- baseDirectoryPath,
809
- absolutePathToEmailsDirectory
810
- ),
811
- directoryName: absolutePathToEmailsDirectory.split(path7.sep).pop(),
812
- emailFilenames,
813
- subDirectories
814
- };
815
- return isSubDirectory ? mergeDirectoriesWithSubDirectories(emailsMetadata) : emailsMetadata;
816
- };
817
-
818
- // src/utils/esbuild/renderring-utilities-exporter.ts
819
- import path8 from "node:path";
820
- import { promises as fs6 } from "node:fs";
821
-
822
- // src/utils/esbuild/escape-string-for-regex.ts
823
- function escapeStringForRegex(string) {
824
- return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
825
- }
826
-
827
- // src/utils/esbuild/renderring-utilities-exporter.ts
828
- var renderingUtilitiesExporter = (emailTemplates) => ({
829
- name: "rendering-utilities-exporter",
830
- setup: (b) => {
831
- b.onLoad(
832
- {
833
- filter: new RegExp(
834
- emailTemplates.map((emailPath) => escapeStringForRegex(emailPath)).join("|")
835
- )
836
- },
837
- async ({ path: pathToFile }) => {
838
- return {
839
- contents: `${await fs6.readFile(pathToFile, "utf8")};
840
- export { render } from 'react-email-module-that-will-export-render'
841
- export { createElement as reactEmailCreateReactElement } from 'react';
842
- `,
843
- loader: path8.extname(pathToFile).slice(1)
844
- };
845
- }
846
- );
847
- b.onResolve(
848
- { filter: /^react-email-module-that-will-export-render$/ },
849
- async (args) => {
850
- const options = {
851
- kind: "import-statement",
852
- importer: args.importer,
853
- resolveDir: args.resolveDir,
854
- namespace: args.namespace
855
- };
856
- let result = await b.resolve("@react-email/render", options);
857
- if (result.errors.length === 0) {
858
- return result;
859
- }
860
- result = await b.resolve("@react-email/components", options);
861
- if (result.errors.length > 0 && result.errors[0]) {
862
- result.errors[0].text = "Failed trying to import `render` from either `@react-email/render` or `@react-email/components` to be able to render your email template.\n Maybe you don't have either of them installed?";
863
- }
864
- return result;
865
- }
866
- );
867
- }
868
- });
869
-
870
- // src/cli/commands/export.ts
871
- var getEmailTemplatesFromDirectory = (emailDirectory) => {
872
- const templatePaths = [];
873
- emailDirectory.emailFilenames.forEach(
874
- (filename) => templatePaths.push(path9.join(emailDirectory.absolutePath, filename))
875
- );
876
- emailDirectory.subDirectories.forEach((directory) => {
877
- templatePaths.push(...getEmailTemplatesFromDirectory(directory));
878
- });
879
- return templatePaths;
880
- };
881
- var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
882
- if (fs7.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
883
- fs7.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
884
- }
885
- let spinner;
886
- if (!options.silent) {
887
- spinner = ora2("Preparing files...\n").start();
888
- registerSpinnerAutostopping(spinner);
889
- }
890
- const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
891
- path9.resolve(process.cwd(), emailsDirectoryPath),
892
- true
893
- );
894
- if (typeof emailsDirectoryMetadata === "undefined") {
895
- if (spinner) {
896
- spinner.stopAndPersist({
897
- symbol: logSymbols3.error,
898
- text: `Could not find the directory at ${emailsDirectoryPath}`
899
- });
900
- }
901
- return;
902
- }
903
- const allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
904
- try {
905
- await build({
906
- bundle: true,
907
- entryPoints: allTemplates,
908
- plugins: [renderingUtilitiesExporter(allTemplates)],
909
- platform: "node",
910
- format: "cjs",
911
- loader: { ".js": "jsx" },
912
- outExtension: { ".js": ".cjs" },
913
- jsx: "transform",
914
- write: true,
915
- outdir: pathToWhereEmailMarkupShouldBeDumped
916
- });
917
- } catch (exception) {
918
- const buildFailure = exception;
919
- if (spinner) {
920
- spinner.stopAndPersist({
921
- symbol: logSymbols3.error,
922
- text: "Failed to build emails"
923
- });
924
- }
925
- process.exit(1);
926
- }
927
- if (spinner) {
928
- spinner.succeed();
929
- }
930
- const allBuiltTemplates = glob.sync(
931
- normalize(`${pathToWhereEmailMarkupShouldBeDumped}/**/*.cjs`),
932
- {
933
- absolute: true
934
- }
935
- );
936
- for await (const template of allBuiltTemplates) {
937
- try {
938
- if (spinner) {
939
- spinner.text = `rendering ${template.split("/").pop()}`;
940
- spinner.render();
941
- }
942
- delete __require.cache[template];
943
- const emailModule = __require(template);
944
- const rendered = await emailModule.render(
945
- emailModule.reactEmailCreateReactElement(emailModule.default, {}),
946
- options
947
- );
948
- const htmlPath = template.replace(
949
- ".cjs",
950
- options.plainText ? ".txt" : ".html"
951
- );
952
- writeFileSync(htmlPath, rendered);
953
- unlinkSync(template);
954
- } catch (exception) {
955
- if (spinner) {
956
- spinner.stopAndPersist({
957
- symbol: logSymbols3.error,
958
- text: `failed when rendering ${template.split("/").pop()}`
959
- });
960
- }
961
- console.error(exception);
962
- process.exit(1);
963
- }
964
- }
965
- if (spinner) {
966
- spinner.succeed("Rendered all files");
967
- spinner.text = "Copying static files";
968
- spinner.render();
969
- }
970
- const staticDirectoryPath = path9.join(emailsDirectoryPath, "static");
971
- if (fs7.existsSync(staticDirectoryPath)) {
972
- const pathToDumpStaticFilesInto = path9.join(
973
- pathToWhereEmailMarkupShouldBeDumped,
974
- "static"
975
- );
976
- if (fs7.existsSync(pathToDumpStaticFilesInto))
977
- await fs7.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
978
- try {
979
- await fs7.promises.cp(staticDirectoryPath, pathToDumpStaticFilesInto, {
980
- recursive: true
981
- });
982
- } catch (exception) {
983
- console.error(exception);
984
- if (spinner) {
985
- spinner.stopAndPersist({
986
- symbol: logSymbols3.error,
987
- text: "Failed to copy static files"
988
- });
989
- }
990
- console.error(
991
- `Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${exception}`
992
- );
993
- process.exit(1);
994
- }
995
- }
996
- if (spinner && !options.silent) {
997
- spinner.succeed();
998
- const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
999
- console.log(fileTree);
1000
- spinner.stopAndPersist({
1001
- symbol: logSymbols3.success,
1002
- text: "Successfully exported emails"
1003
- });
1004
- }
1005
- };
1006
-
1007
785
  // src/cli/commands/build.ts
1008
- import fs8 from "node:fs";
1009
- import path10 from "node:path";
1010
- import ora3 from "ora";
1011
- import { spawn } from "node:child_process";
1012
- import logSymbols4 from "log-symbols";
1013
786
  var buildPreviewApp = (absoluteDirectory) => {
1014
787
  return new Promise((resolve, reject) => {
1015
788
  const nextBuild = spawn("npm", ["run", "build"], {
@@ -1066,8 +839,8 @@ module.exports = {
1066
839
  webpackBuildWorker: true
1067
840
  },
1068
841
  }`;
1069
- await fs8.promises.writeFile(
1070
- path10.resolve(builtPreviewAppPath, "./next.config.js"),
842
+ await fs5.promises.writeFile(
843
+ path8.resolve(builtPreviewAppPath, "./next.config.js"),
1071
844
  nextConfigContents,
1072
845
  "utf8"
1073
846
  );
@@ -1077,7 +850,7 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
1077
850
  const slugs = [];
1078
851
  emailDirectory.emailFilenames.forEach(
1079
852
  (filename) => slugs.push(
1080
- path10.join(directoryPathRelativeToEmailsDirectory, filename).split(path10.sep).filter((segment) => segment.length > 0)
853
+ path8.join(directoryPathRelativeToEmailsDirectory, filename).split(path8.sep).filter((segment) => segment.length > 0)
1081
854
  )
1082
855
  );
1083
856
  emailDirectory.subDirectories.forEach((directory) => {
@@ -1100,21 +873,21 @@ var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
1100
873
  emailsDirPath
1101
874
  ).map((slug) => ({ slug }));
1102
875
  const removeForceDynamic = async (filePath) => {
1103
- const contents = await fs8.promises.readFile(filePath, "utf8");
1104
- await fs8.promises.writeFile(
876
+ const contents = await fs5.promises.readFile(filePath, "utf8");
877
+ await fs5.promises.writeFile(
1105
878
  filePath,
1106
879
  contents.replace("export const dynamic = 'force-dynamic';", ""),
1107
880
  "utf8"
1108
881
  );
1109
882
  };
1110
883
  await removeForceDynamic(
1111
- path10.resolve(builtPreviewAppPath, "./src/app/layout.tsx")
884
+ path8.resolve(builtPreviewAppPath, "./src/app/layout.tsx")
1112
885
  );
1113
886
  await removeForceDynamic(
1114
- path10.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx")
887
+ path8.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx")
1115
888
  );
1116
- await fs8.promises.appendFile(
1117
- path10.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
889
+ await fs5.promises.appendFile(
890
+ path8.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
1118
891
  `
1119
892
 
1120
893
  export function generateStaticParams() {
@@ -1126,16 +899,16 @@ export function generateStaticParams() {
1126
899
  );
1127
900
  };
1128
901
  var updatePackageJson = async (builtPreviewAppPath) => {
1129
- const packageJsonPath = path10.resolve(builtPreviewAppPath, "./package.json");
902
+ const packageJsonPath = path8.resolve(builtPreviewAppPath, "./package.json");
1130
903
  const packageJson = JSON.parse(
1131
- await fs8.promises.readFile(packageJsonPath, "utf8")
904
+ await fs5.promises.readFile(packageJsonPath, "utf8")
1132
905
  );
1133
906
  packageJson.scripts.build = "next build";
1134
907
  packageJson.scripts.start = "next start";
1135
908
  packageJson.name = "preview-server";
1136
909
  delete packageJson.devDependencies["@react-email/render"];
1137
910
  delete packageJson.devDependencies["@react-email/components"];
1138
- await fs8.promises.writeFile(
911
+ await fs5.promises.writeFile(
1139
912
  packageJsonPath,
1140
913
  JSON.stringify(packageJson),
1141
914
  "utf8"
@@ -1166,41 +939,41 @@ var npmInstall = async (builtPreviewAppPath, packageManager) => {
1166
939
  });
1167
940
  });
1168
941
  };
1169
- var build2 = async ({
942
+ var build = async ({
1170
943
  dir: emailsDirRelativePath,
1171
944
  packageManager
1172
945
  }) => {
1173
946
  try {
1174
- const spinner = ora3({
947
+ const spinner = ora2({
1175
948
  text: "Starting build process...",
1176
949
  prefixText: " "
1177
950
  }).start();
1178
951
  registerSpinnerAutostopping(spinner);
1179
952
  spinner.text = `Checking if ${emailsDirRelativePath} folder exists`;
1180
- if (!fs8.existsSync(emailsDirRelativePath)) {
953
+ if (!fs5.existsSync(emailsDirRelativePath)) {
1181
954
  process.exit(1);
1182
955
  }
1183
- const emailsDirPath = path10.join(process.cwd(), emailsDirRelativePath);
1184
- const staticPath = path10.join(emailsDirPath, "static");
1185
- const builtPreviewAppPath = path10.join(process.cwd(), ".react-email");
1186
- if (fs8.existsSync(builtPreviewAppPath)) {
956
+ const emailsDirPath = path8.join(process.cwd(), emailsDirRelativePath);
957
+ const staticPath = path8.join(emailsDirPath, "static");
958
+ const builtPreviewAppPath = path8.join(process.cwd(), ".react-email");
959
+ if (fs5.existsSync(builtPreviewAppPath)) {
1187
960
  spinner.text = "Deleting pre-existing `.react-email` folder";
1188
- await fs8.promises.rm(builtPreviewAppPath, { recursive: true });
961
+ await fs5.promises.rm(builtPreviewAppPath, { recursive: true });
1189
962
  }
1190
963
  spinner.text = "Copying preview app from CLI to `.react-email`";
1191
- await fs8.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
964
+ await fs5.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
1192
965
  recursive: true,
1193
966
  filter: (source) => {
1194
967
  return !/(\/|\\)cli(\/|\\)?/.test(source) && !/(\/|\\)\.next(\/|\\)?/.test(source) && !/(\/|\\)\.turbo(\/|\\)?/.test(source) && !/(\/|\\)node_modules(\/|\\)?$/.test(source);
1195
968
  }
1196
969
  });
1197
- if (fs8.existsSync(staticPath)) {
970
+ if (fs5.existsSync(staticPath)) {
1198
971
  spinner.text = "Copying `static` folder into `.react-email/public/static`";
1199
- const builtStaticDirectory = path10.resolve(
972
+ const builtStaticDirectory = path8.resolve(
1200
973
  builtPreviewAppPath,
1201
974
  "./public/static"
1202
975
  );
1203
- await fs8.promises.cp(staticPath, builtStaticDirectory, {
976
+ await fs5.promises.cp(staticPath, builtStaticDirectory, {
1204
977
  recursive: true
1205
978
  });
1206
979
  }
@@ -1217,7 +990,7 @@ var build2 = async ({
1217
990
  await npmInstall(builtPreviewAppPath, packageManager);
1218
991
  spinner.stopAndPersist({
1219
992
  text: "Successfully prepared `.react-email` for `next build`",
1220
- symbol: logSymbols4.success
993
+ symbol: logSymbols3.success
1221
994
  });
1222
995
  await buildPreviewApp(builtPreviewAppPath);
1223
996
  } catch (error) {
@@ -1226,10 +999,229 @@ var build2 = async ({
1226
999
  }
1227
1000
  };
1228
1001
 
1002
+ // src/cli/commands/dev.ts
1003
+ import fs6 from "node:fs";
1004
+ var dev = async ({ dir: emailsDirRelativePath, port }) => {
1005
+ try {
1006
+ if (!fs6.existsSync(emailsDirRelativePath)) {
1007
+ console.error(`Missing ${emailsDirRelativePath} folder`);
1008
+ process.exit(1);
1009
+ }
1010
+ const devServer2 = await startDevServer(
1011
+ emailsDirRelativePath,
1012
+ emailsDirRelativePath,
1013
+ // defaults to ./emails/static for the static files that are served to the preview
1014
+ Number.parseInt(port)
1015
+ );
1016
+ await setupHotreloading(devServer2, emailsDirRelativePath);
1017
+ } catch (error) {
1018
+ console.log(error);
1019
+ process.exit(1);
1020
+ }
1021
+ };
1022
+
1023
+ // src/cli/commands/export.ts
1024
+ import fs8, { unlinkSync, writeFileSync } from "node:fs";
1025
+ import path10 from "node:path";
1026
+ import { build as build2 } from "esbuild";
1027
+ import { glob } from "glob";
1028
+ import logSymbols4 from "log-symbols";
1029
+ import normalize from "normalize-path";
1030
+ import ora3 from "ora";
1031
+
1032
+ // src/utils/esbuild/renderring-utilities-exporter.ts
1033
+ import { promises as fs7 } from "node:fs";
1034
+ import path9 from "node:path";
1035
+
1036
+ // src/utils/esbuild/escape-string-for-regex.ts
1037
+ function escapeStringForRegex(string) {
1038
+ return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
1039
+ }
1040
+
1041
+ // src/utils/esbuild/renderring-utilities-exporter.ts
1042
+ var renderingUtilitiesExporter = (emailTemplates) => ({
1043
+ name: "rendering-utilities-exporter",
1044
+ setup: (b) => {
1045
+ b.onLoad(
1046
+ {
1047
+ filter: new RegExp(
1048
+ emailTemplates.map((emailPath) => escapeStringForRegex(emailPath)).join("|")
1049
+ )
1050
+ },
1051
+ async ({ path: pathToFile }) => {
1052
+ return {
1053
+ contents: `${await fs7.readFile(pathToFile, "utf8")};
1054
+ export { render } from 'react-email-module-that-will-export-render'
1055
+ export { createElement as reactEmailCreateReactElement } from 'react';
1056
+ `,
1057
+ loader: path9.extname(pathToFile).slice(1)
1058
+ };
1059
+ }
1060
+ );
1061
+ b.onResolve(
1062
+ { filter: /^react-email-module-that-will-export-render$/ },
1063
+ async (args) => {
1064
+ const options = {
1065
+ kind: "import-statement",
1066
+ importer: args.importer,
1067
+ resolveDir: args.resolveDir,
1068
+ namespace: args.namespace
1069
+ };
1070
+ let result = await b.resolve("@react-email/render", options);
1071
+ if (result.errors.length === 0) {
1072
+ return result;
1073
+ }
1074
+ result = await b.resolve("@react-email/components", options);
1075
+ if (result.errors.length > 0 && result.errors[0]) {
1076
+ result.errors[0].text = "Failed trying to import `render` from either `@react-email/render` or `@react-email/components` to be able to render your email template.\n Maybe you don't have either of them installed?";
1077
+ }
1078
+ return result;
1079
+ }
1080
+ );
1081
+ }
1082
+ });
1083
+
1084
+ // src/cli/commands/export.ts
1085
+ var getEmailTemplatesFromDirectory = (emailDirectory) => {
1086
+ const templatePaths = [];
1087
+ emailDirectory.emailFilenames.forEach(
1088
+ (filename) => templatePaths.push(path10.join(emailDirectory.absolutePath, filename))
1089
+ );
1090
+ emailDirectory.subDirectories.forEach((directory) => {
1091
+ templatePaths.push(...getEmailTemplatesFromDirectory(directory));
1092
+ });
1093
+ return templatePaths;
1094
+ };
1095
+ var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
1096
+ if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
1097
+ fs8.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
1098
+ }
1099
+ let spinner;
1100
+ if (!options.silent) {
1101
+ spinner = ora3("Preparing files...\n").start();
1102
+ registerSpinnerAutostopping(spinner);
1103
+ }
1104
+ const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
1105
+ path10.resolve(process.cwd(), emailsDirectoryPath),
1106
+ true
1107
+ );
1108
+ if (typeof emailsDirectoryMetadata === "undefined") {
1109
+ if (spinner) {
1110
+ spinner.stopAndPersist({
1111
+ symbol: logSymbols4.error,
1112
+ text: `Could not find the directory at ${emailsDirectoryPath}`
1113
+ });
1114
+ }
1115
+ return;
1116
+ }
1117
+ const allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
1118
+ try {
1119
+ await build2({
1120
+ bundle: true,
1121
+ entryPoints: allTemplates,
1122
+ plugins: [renderingUtilitiesExporter(allTemplates)],
1123
+ platform: "node",
1124
+ format: "cjs",
1125
+ loader: { ".js": "jsx" },
1126
+ outExtension: { ".js": ".cjs" },
1127
+ jsx: "transform",
1128
+ write: true,
1129
+ outdir: pathToWhereEmailMarkupShouldBeDumped
1130
+ });
1131
+ } catch (exception) {
1132
+ const buildFailure = exception;
1133
+ if (spinner) {
1134
+ spinner.stopAndPersist({
1135
+ symbol: logSymbols4.error,
1136
+ text: "Failed to build emails"
1137
+ });
1138
+ }
1139
+ process.exit(1);
1140
+ }
1141
+ if (spinner) {
1142
+ spinner.succeed();
1143
+ }
1144
+ const allBuiltTemplates = glob.sync(
1145
+ normalize(`${pathToWhereEmailMarkupShouldBeDumped}/**/*.cjs`),
1146
+ {
1147
+ absolute: true
1148
+ }
1149
+ );
1150
+ for await (const template of allBuiltTemplates) {
1151
+ try {
1152
+ if (spinner) {
1153
+ spinner.text = `rendering ${template.split("/").pop()}`;
1154
+ spinner.render();
1155
+ }
1156
+ delete __require.cache[template];
1157
+ const emailModule = __require(template);
1158
+ const rendered = await emailModule.render(
1159
+ emailModule.reactEmailCreateReactElement(emailModule.default, {}),
1160
+ options
1161
+ );
1162
+ const htmlPath = template.replace(
1163
+ ".cjs",
1164
+ options.plainText ? ".txt" : ".html"
1165
+ );
1166
+ writeFileSync(htmlPath, rendered);
1167
+ unlinkSync(template);
1168
+ } catch (exception) {
1169
+ if (spinner) {
1170
+ spinner.stopAndPersist({
1171
+ symbol: logSymbols4.error,
1172
+ text: `failed when rendering ${template.split("/").pop()}`
1173
+ });
1174
+ }
1175
+ console.error(exception);
1176
+ process.exit(1);
1177
+ }
1178
+ }
1179
+ if (spinner) {
1180
+ spinner.succeed("Rendered all files");
1181
+ spinner.text = "Copying static files";
1182
+ spinner.render();
1183
+ }
1184
+ const staticDirectoryPath = path10.join(emailsDirectoryPath, "static");
1185
+ if (fs8.existsSync(staticDirectoryPath)) {
1186
+ const pathToDumpStaticFilesInto = path10.join(
1187
+ pathToWhereEmailMarkupShouldBeDumped,
1188
+ "static"
1189
+ );
1190
+ if (fs8.existsSync(pathToDumpStaticFilesInto))
1191
+ await fs8.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
1192
+ try {
1193
+ await fs8.promises.cp(staticDirectoryPath, pathToDumpStaticFilesInto, {
1194
+ recursive: true
1195
+ });
1196
+ } catch (exception) {
1197
+ console.error(exception);
1198
+ if (spinner) {
1199
+ spinner.stopAndPersist({
1200
+ symbol: logSymbols4.error,
1201
+ text: "Failed to copy static files"
1202
+ });
1203
+ }
1204
+ console.error(
1205
+ `Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${exception}`
1206
+ );
1207
+ process.exit(1);
1208
+ }
1209
+ }
1210
+ if (spinner && !options.silent) {
1211
+ spinner.succeed();
1212
+ const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
1213
+ console.log(fileTree);
1214
+ spinner.stopAndPersist({
1215
+ symbol: logSymbols4.success,
1216
+ text: "Successfully exported emails"
1217
+ });
1218
+ }
1219
+ };
1220
+
1229
1221
  // src/cli/commands/start.ts
1222
+ import { spawn as spawn2 } from "node:child_process";
1230
1223
  import fs9 from "node:fs";
1231
1224
  import path11 from "node:path";
1232
- import { spawn as spawn2 } from "node:child_process";
1233
1225
  var start = async () => {
1234
1226
  try {
1235
1227
  const usersProjectLocation = process.cwd();
@@ -1267,7 +1259,7 @@ program.command("build").description("Copies the preview app for onto .react-ema
1267
1259
  "-p --packageManager <name>",
1268
1260
  "Package name to use on installation on `.react-email`",
1269
1261
  "npm"
1270
- ).action(build2);
1262
+ ).action(build);
1271
1263
  program.command("start").description('Runs the built preview app that is inside of ".react-email"').action(start);
1272
1264
  program.command("export").description("Build the templates to the `out` directory").option("--outDir <path>", "Output directory", "out").option("-p, --pretty", "Pretty print the output", false).option("-t, --plainText", "Set output format as plain text", false).option("-d, --dir <path>", "Directory with your email templates", "./emails").option(
1273
1265
  "-s, --silent",