react-email 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/index.mjs CHANGED
@@ -13,7 +13,7 @@ import { program } from "commander";
13
13
  // package.json
14
14
  var package_default = {
15
15
  name: "react-email",
16
- version: "2.1.3",
16
+ version: "2.1.4",
17
17
  description: "A live preview of your emails right in your browser.",
18
18
  bin: {
19
19
  email: "./cli/index.js"
@@ -40,7 +40,8 @@ var package_default = {
40
40
  node: ">=18.0.0"
41
41
  },
42
42
  dependencies: {
43
- "@babel/parser": "7.24.1",
43
+ "@babel/core": "7.24.5",
44
+ "@babel/parser": "7.24.5",
44
45
  "@radix-ui/colors": "1.0.1",
45
46
  "@radix-ui/react-collapsible": "1.0.3",
46
47
  "@radix-ui/react-popover": "1.0.7",
@@ -52,7 +53,6 @@ var package_default = {
52
53
  "@types/react-dom": "^18.2.0",
53
54
  "@types/webpack": "5.28.5",
54
55
  autoprefixer: "10.4.14",
55
- "babel-walk": "3.0.0",
56
56
  chalk: "4.1.2",
57
57
  chokidar: "3.5.3",
58
58
  clsx: "2.1.0",
@@ -83,8 +83,9 @@ var package_default = {
83
83
  typescript: "5.1.6"
84
84
  },
85
85
  devDependencies: {
86
- "@react-email/components": "0.0.18",
87
- "@react-email/render": "0.0.14",
86
+ "@react-email/components": "0.0.19",
87
+ "@react-email/render": "0.0.15",
88
+ "@types/babel__core": "7.20.5",
88
89
  "@types/fs-extra": "11.0.1",
89
90
  "@types/mime-types": "2.1.4",
90
91
  "@types/node": "18.0.0",
@@ -158,33 +159,18 @@ var tree = async (dirPath, depth) => {
158
159
  };
159
160
 
160
161
  // src/cli/utils/preview/hot-reloading/setup-hot-reloading.ts
161
- import path3 from "path";
162
+ import path6 from "path";
162
163
  import { Server as SocketServer } from "socket.io";
163
164
  import { watch } from "chokidar";
164
165
  import debounce from "debounce";
165
166
 
166
167
  // src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
167
- import path2 from "path";
168
- import { promises as fs2 } from "fs";
168
+ import path5 from "path";
169
+ import { existsSync, promises as fs3, statSync } from "fs";
169
170
 
170
171
  // src/cli/utils/preview/hot-reloading/get-imported-modules.ts
172
+ import { traverse } from "@babel/core";
171
173
  import { parse } from "@babel/parser";
172
- import * as walk from "babel-walk";
173
- var importVisitor = walk.simple({
174
- ImportDeclaration(node, importedPaths) {
175
- importedPaths.push(node.source.value);
176
- },
177
- CallExpression(node, importedPaths) {
178
- if ("name" in node.callee && node.callee.name === "require") {
179
- if (node.arguments.length === 1) {
180
- const importPathNode = node.arguments[0];
181
- if (importPathNode.type === "StringLiteral") {
182
- importedPaths.push(importPathNode.value);
183
- }
184
- }
185
- }
186
- }
187
- });
188
174
  var getImportedModules = (contents) => {
189
175
  const importedPaths = [];
190
176
  const parsedContents = parse(contents, {
@@ -193,16 +179,227 @@ var getImportedModules = (contents) => {
193
179
  errorRecovery: true,
194
180
  plugins: ["jsx", "typescript"]
195
181
  });
196
- importVisitor(parsedContents, importedPaths);
182
+ traverse(parsedContents, {
183
+ ImportDeclaration({ node }) {
184
+ importedPaths.push(node.source.value);
185
+ },
186
+ ExportAllDeclaration({ node }) {
187
+ importedPaths.push(node.source.value);
188
+ },
189
+ ExportNamedDeclaration({ node }) {
190
+ if (node.source) {
191
+ importedPaths.push(node.source.value);
192
+ }
193
+ },
194
+ CallExpression({ node }) {
195
+ if ("name" in node.callee && node.callee.name === "require") {
196
+ if (node.arguments.length === 1) {
197
+ const importPathNode = node.arguments[0];
198
+ if (importPathNode.type === "StringLiteral") {
199
+ importedPaths.push(importPathNode.value);
200
+ }
201
+ }
202
+ }
203
+ }
204
+ });
197
205
  return importedPaths;
198
206
  };
199
207
 
208
+ // src/cli/utils/preview/start-dev-server.ts
209
+ import path4 from "path";
210
+ import http from "http";
211
+ import url from "url";
212
+ import next from "next";
213
+ import ora from "ora";
214
+ import logSymbols from "log-symbols";
215
+ import chalk from "chalk";
216
+
217
+ // src/cli/utils/close-ora-on-sigint.ts
218
+ var closeOraOnSIGNIT = (spinner) => {
219
+ process.on("SIGINT", () => {
220
+ spinner.stop();
221
+ });
222
+ };
223
+
224
+ // src/cli/utils/preview/serve-static-file.ts
225
+ import path2 from "path";
226
+ import { promises as fs2 } from "fs";
227
+ import { lookup } from "mime-types";
228
+ var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
229
+ const staticBaseDir = path2.join(process.cwd(), staticDirRelativePath);
230
+ const pathname = parsedUrl.pathname;
231
+ const ext = path2.parse(pathname).ext;
232
+ let fileAbsolutePath = path2.join(staticBaseDir, pathname);
233
+ const fileHandle = await fs2.open(fileAbsolutePath, "r");
234
+ try {
235
+ const fileData = await fs2.readFile(fileHandle);
236
+ res.setHeader("Content-type", lookup(ext) || "text/plain");
237
+ res.end(fileData);
238
+ } catch (exception) {
239
+ console.error(
240
+ `Could not read file at ${fileAbsolutePath} to be served, here's the exception:`,
241
+ exception
242
+ );
243
+ res.statusCode = 500;
244
+ res.end(
245
+ `Could not read file to be served! Check your terminal for more information.`
246
+ );
247
+ } finally {
248
+ fileHandle.close();
249
+ }
250
+ };
251
+
252
+ // src/cli/utils/preview/get-env-variables-for-preview-app.ts
253
+ import path3 from "path";
254
+ var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cliPackageLocation, cwd) => {
255
+ return {
256
+ NEXT_PUBLIC_EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
257
+ NEXT_PUBLIC_CLI_PACKAGE_LOCATION: cliPackageLocation,
258
+ NEXT_PUBLIC_OS_PATH_SEPARATOR: path3.sep,
259
+ NEXT_PUBLIC_USER_PROJECT_LOCATION: cwd
260
+ };
261
+ };
262
+
263
+ // src/cli/utils/preview/start-dev-server.ts
264
+ var devServer;
265
+ var safeAsyncServerListen = (server, port) => {
266
+ return new Promise((resolve) => {
267
+ server.listen(port, () => {
268
+ resolve({ portAlreadyInUse: false });
269
+ });
270
+ server.on("error", (e) => {
271
+ if (e.code === "EADDRINUSE") {
272
+ resolve({ portAlreadyInUse: true });
273
+ }
274
+ });
275
+ });
276
+ };
277
+ var isRunningBuilt = __filename.endsWith(path4.join("cli", "index.js"));
278
+ var cliPacakgeLocation = isRunningBuilt ? path4.resolve(__dirname, "..") : path4.resolve(__dirname, "../../../..");
279
+ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
280
+ devServer = http.createServer((req, res) => {
281
+ if (!req.url) {
282
+ res.end(404);
283
+ return;
284
+ }
285
+ const parsedUrl = url.parse(req.url, true);
286
+ res.setHeader(
287
+ "Cache-Control",
288
+ "no-cache, max-age=0, must-revalidate, no-store"
289
+ );
290
+ res.setHeader("Pragma", "no-cache");
291
+ res.setHeader("Expires", "-1");
292
+ try {
293
+ if (parsedUrl.path && parsedUrl.path.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
294
+ void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
295
+ } else if (!isNextReady) {
296
+ void nextReadyPromise.then(
297
+ () => nextHandleRequest?.(req, res, parsedUrl)
298
+ );
299
+ } else {
300
+ void nextHandleRequest?.(req, res, parsedUrl);
301
+ }
302
+ } catch (e) {
303
+ console.error("caught error", e);
304
+ res.writeHead(500);
305
+ res.end();
306
+ }
307
+ });
308
+ const { portAlreadyInUse } = await safeAsyncServerListen(devServer, port);
309
+ if (!portAlreadyInUse) {
310
+ console.log(chalk.greenBright(` React Email ${package_default.version}`));
311
+ console.log(` Running preview at: http://localhost:${port}
312
+ `);
313
+ } else {
314
+ const nextPortToTry = port + 1;
315
+ console.warn(
316
+ ` ${logSymbols.warning} Port ${port} is already in use, trying ${nextPortToTry}`
317
+ );
318
+ return startDevServer(
319
+ emailsDirRelativePath,
320
+ staticBaseDirRelativePath,
321
+ nextPortToTry
322
+ );
323
+ }
324
+ devServer.on("close", async () => {
325
+ await app.close();
326
+ });
327
+ devServer.on("error", (e) => {
328
+ console.error(
329
+ ` ${logSymbols.error} preview server error: `,
330
+ JSON.stringify(e)
331
+ );
332
+ process.exit(1);
333
+ });
334
+ const spinner = ora({
335
+ text: "Getting react-email preview server ready...\n",
336
+ prefixText: " "
337
+ }).start();
338
+ closeOraOnSIGNIT(spinner);
339
+ const timeBeforeNextReady = performance.now();
340
+ process.env = {
341
+ ...process.env,
342
+ ...getEnvVariablesForPreviewApp(
343
+ // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
344
+ path4.normalize(emailsDirRelativePath),
345
+ cliPacakgeLocation,
346
+ process.cwd()
347
+ )
348
+ };
349
+ const app = next({
350
+ // passing in env here does not get the environment variables there
351
+ dev: true,
352
+ hostname: "localhost",
353
+ port,
354
+ dir: cliPacakgeLocation
355
+ });
356
+ let isNextReady = false;
357
+ const nextReadyPromise = app.prepare();
358
+ await nextReadyPromise;
359
+ isNextReady = true;
360
+ const nextHandleRequest = app.getRequestHandler();
361
+ const secondsToNextReady = ((performance.now() - timeBeforeNextReady) / 1e3).toFixed(1);
362
+ spinner.stopAndPersist({
363
+ text: `Ready in ${secondsToNextReady}s
364
+ `,
365
+ symbol: logSymbols.success
366
+ });
367
+ return devServer;
368
+ };
369
+ var makeExitHandler = (options) => (_codeOrSignal) => {
370
+ if (typeof devServer !== "undefined") {
371
+ console.log("\nshutting down dev server");
372
+ devServer.close();
373
+ devServer = void 0;
374
+ }
375
+ if (options?.shouldKillProcess) {
376
+ process.exit(options.killWithErrorCode ? 1 : 0);
377
+ }
378
+ };
379
+ process.on("exit", makeExitHandler());
380
+ process.on(
381
+ "SIGINT",
382
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
383
+ );
384
+ process.on(
385
+ "SIGUSR1",
386
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
387
+ );
388
+ process.on(
389
+ "SIGUSR2",
390
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
391
+ );
392
+ process.on(
393
+ "uncaughtException",
394
+ makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
395
+ );
396
+
200
397
  // src/cli/utils/preview/hot-reloading/create-dependency-graph.ts
201
398
  var readAllFilesInsideDirectory = async (directory) => {
202
399
  let allFilePaths = [];
203
- const topLevelDirents = await fs2.readdir(directory, { withFileTypes: true });
400
+ const topLevelDirents = await fs3.readdir(directory, { withFileTypes: true });
204
401
  for await (const dirent of topLevelDirents) {
205
- const pathToDirent = path2.join(directory, dirent.name);
402
+ const pathToDirent = path5.join(directory, dirent.name);
206
403
  if (dirent.isDirectory()) {
207
404
  allFilePaths = allFilePaths.concat(
208
405
  await readAllFilesInsideDirectory(pathToDirent)
@@ -214,9 +411,24 @@ var readAllFilesInsideDirectory = async (directory) => {
214
411
  return allFilePaths;
215
412
  };
216
413
  var isJavascriptModule = (filePath) => {
217
- const extensionName = path2.extname(filePath);
414
+ const extensionName = path5.extname(filePath);
218
415
  return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
219
416
  };
417
+ var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
418
+ if (existsSync(`${pathWithoutExtension}.ts`)) {
419
+ return `${pathWithoutExtension}.ts`;
420
+ } else if (existsSync(`${pathWithoutExtension}.tsx`)) {
421
+ return `${pathWithoutExtension}.tsx`;
422
+ } else if (existsSync(`${pathWithoutExtension}.js`)) {
423
+ return `${pathWithoutExtension}.js`;
424
+ } else if (existsSync(`${pathWithoutExtension}.jsx`)) {
425
+ return `${pathWithoutExtension}.jsx`;
426
+ } else if (existsSync(`${pathWithoutExtension}.mjs`)) {
427
+ return `${pathWithoutExtension}.mjs`;
428
+ } else if (existsSync(`${pathWithoutExtension}.cjs`)) {
429
+ return `${pathWithoutExtension}.cjs`;
430
+ }
431
+ };
220
432
  var createDependencyGraph = async (directory) => {
221
433
  const filePaths = await readAllFilesInsideDirectory(directory);
222
434
  const modulePaths = filePaths.filter(isJavascriptModule);
@@ -232,13 +444,13 @@ var createDependencyGraph = async (directory) => {
232
444
  ])
233
445
  );
234
446
  const getDependencyPaths = async (filePath) => {
235
- const contents = await fs2.readFile(filePath, "utf8");
447
+ const contents = await fs3.readFile(filePath, "utf8");
236
448
  const importedPaths = getImportedModules(contents);
237
449
  const importedPathsRelativeToDirectory = importedPaths.map(
238
450
  (dependencyPath) => {
239
451
  const isModulePath = !dependencyPath.startsWith(".");
240
- if (!isModulePath && !path2.isAbsolute(dependencyPath)) {
241
- let pathToDependencyFromDirectory = path2.resolve(
452
+ if (!isModulePath && !path5.isAbsolute(dependencyPath)) {
453
+ let pathToDependencyFromDirectory = path5.resolve(
242
454
  /*
243
455
  path.resolve resolves paths differently from what imports on javascript do.
244
456
 
@@ -246,13 +458,38 @@ var createDependencyGraph = async (directory) => {
246
458
  would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
247
459
  one the import is meant to go to
248
460
  */
249
- path2.dirname(filePath),
461
+ path5.dirname(filePath),
250
462
  dependencyPath
251
463
  );
464
+ let isDirectory = false;
465
+ try {
466
+ isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
467
+ } catch (_) {
468
+ }
469
+ if (isDirectory) {
470
+ const pathToSubDirectory = pathToDependencyFromDirectory;
471
+ const pathWithExtension = checkFileExtensionsUntilItExists(
472
+ `${pathToSubDirectory}/index`
473
+ );
474
+ if (pathWithExtension) {
475
+ pathToDependencyFromDirectory = pathWithExtension;
476
+ } else if (!isRunningBuilt) {
477
+ console.warn(
478
+ `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`
479
+ );
480
+ }
481
+ }
252
482
  if (!isJavascriptModule(pathToDependencyFromDirectory)) {
253
- pathToDependencyFromDirectory = `${pathToDependencyFromDirectory}${path2.extname(
254
- filePath
255
- )}`;
483
+ const pathWithExtension = checkFileExtensionsUntilItExists(
484
+ pathToDependencyFromDirectory
485
+ );
486
+ if (pathWithExtension) {
487
+ pathToDependencyFromDirectory = pathWithExtension;
488
+ } else if (!isRunningBuilt) {
489
+ console.warn(
490
+ `Could not determine the file extension for the file at ${pathWithExtension}`
491
+ );
492
+ }
256
493
  }
257
494
  return pathToDependencyFromDirectory;
258
495
  } else {
@@ -261,10 +498,10 @@ var createDependencyGraph = async (directory) => {
261
498
  }
262
499
  );
263
500
  const moduleDependencies = importedPathsRelativeToDirectory.filter(
264
- (dependencyPath) => !dependencyPath.startsWith(".") && !path2.isAbsolute(dependencyPath)
501
+ (dependencyPath) => !dependencyPath.startsWith(".") && !path5.isAbsolute(dependencyPath)
265
502
  );
266
503
  const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
267
- (dependencyPath) => dependencyPath.startsWith(".") || path2.isAbsolute(dependencyPath)
504
+ (dependencyPath) => dependencyPath.startsWith(".") || path5.isAbsolute(dependencyPath)
268
505
  );
269
506
  return {
270
507
  dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
@@ -375,7 +612,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
375
612
  });
376
613
  const watcher = watch(emailDirRelativePath, {
377
614
  ignoreInitial: true,
378
- cwd: path3.resolve(process.cwd()),
615
+ cwd: path6.resolve(process.cwd()),
379
616
  // eslint-disable-next-line prefer-named-capture-group
380
617
  ignored: /(^|[/\\])\../
381
618
  });
@@ -391,19 +628,31 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
391
628
  });
392
629
  changes = [];
393
630
  }, 150);
394
- const absolutePathToEmailsDirectory = path3.resolve(
631
+ const absolutePathToEmailsDirectory = path6.resolve(
395
632
  process.cwd(),
396
633
  emailDirRelativePath
397
634
  );
398
635
  const [dependencyGraph, updateDependencyGraph] = await createDependencyGraph(
399
636
  absolutePathToEmailsDirectory
400
637
  );
638
+ const resolveDependentsOf = (pathToChangeTarget) => {
639
+ const moduleEntry = dependencyGraph[pathToChangeTarget];
640
+ const dependentPaths = [];
641
+ if (moduleEntry) {
642
+ for (const dependentPath of moduleEntry.dependentPaths) {
643
+ const dependentsOfDependent = resolveDependentsOf(dependentPath);
644
+ dependentPaths.push(...dependentsOfDependent);
645
+ dependentPaths.push(dependentPath);
646
+ }
647
+ }
648
+ return dependentPaths;
649
+ };
401
650
  watcher.on("all", async (event, relativePathToChangeTarget) => {
402
- const file = relativePathToChangeTarget.split(path3.sep);
651
+ const file = relativePathToChangeTarget.split(path6.sep);
403
652
  if (file.length === 0) {
404
653
  return;
405
654
  }
406
- const pathToChangeTarget = path3.resolve(
655
+ const pathToChangeTarget = path6.resolve(
407
656
  process.cwd(),
408
657
  relativePathToChangeTarget
409
658
  );
@@ -412,208 +661,17 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
412
661
  event,
413
662
  filename: relativePathToChangeTarget
414
663
  });
415
- changes.push(
416
- ...(dependencyGraph[pathToChangeTarget]?.dependentPaths ?? []).map(
417
- (dependentPath) => ({
418
- event: "change",
419
- filename: path3.relative(absolutePathToEmailsDirectory, dependentPath)
420
- })
421
- )
422
- );
664
+ for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
665
+ changes.push({
666
+ event: "change",
667
+ filename: path6.relative(absolutePathToEmailsDirectory, dependentPath)
668
+ });
669
+ }
423
670
  reload();
424
671
  });
425
672
  return watcher;
426
673
  };
427
674
 
428
- // src/cli/utils/preview/start-dev-server.ts
429
- import path6 from "path";
430
- import http from "http";
431
- import url from "url";
432
- import next from "next";
433
- import ora from "ora";
434
- import logSymbols from "log-symbols";
435
- import chalk from "chalk";
436
-
437
- // src/cli/utils/close-ora-on-sigint.ts
438
- var closeOraOnSIGNIT = (spinner) => {
439
- process.on("SIGINT", () => {
440
- spinner.stop();
441
- });
442
- };
443
-
444
- // src/cli/utils/preview/serve-static-file.ts
445
- import path4 from "path";
446
- import { promises as fs3 } from "fs";
447
- import { lookup } from "mime-types";
448
- var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
449
- const staticBaseDir = path4.join(process.cwd(), staticDirRelativePath);
450
- const pathname = parsedUrl.pathname;
451
- const ext = path4.parse(pathname).ext;
452
- let fileAbsolutePath = path4.join(staticBaseDir, pathname);
453
- const fileHandle = await fs3.open(fileAbsolutePath, "r");
454
- try {
455
- const fileData = await fs3.readFile(fileHandle);
456
- res.setHeader("Content-type", lookup(ext) || "text/plain");
457
- res.end(fileData);
458
- } catch (exception) {
459
- console.error(
460
- `Could not read file at ${fileAbsolutePath} to be served, here's the exception:`,
461
- exception
462
- );
463
- res.statusCode = 500;
464
- res.end(
465
- `Could not read file to be served! Check your terminal for more information.`
466
- );
467
- } finally {
468
- fileHandle.close();
469
- }
470
- };
471
-
472
- // src/cli/utils/preview/get-env-variables-for-preview-app.ts
473
- import path5 from "path";
474
- var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cliPackageLocation, cwd) => {
475
- return {
476
- NEXT_PUBLIC_EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
477
- NEXT_PUBLIC_CLI_PACKAGE_LOCATION: cliPackageLocation,
478
- NEXT_PUBLIC_OS_PATH_SEPARATOR: path5.sep,
479
- NEXT_PUBLIC_USER_PROJECT_LOCATION: cwd
480
- };
481
- };
482
-
483
- // src/cli/utils/preview/start-dev-server.ts
484
- var devServer;
485
- var safeAsyncServerListen = (server, port) => {
486
- return new Promise((resolve) => {
487
- server.listen(port, () => {
488
- resolve({ portAlreadyInUse: false });
489
- });
490
- server.on("error", (e) => {
491
- if (e.code === "EADDRINUSE") {
492
- resolve({ portAlreadyInUse: true });
493
- }
494
- });
495
- });
496
- };
497
- var isRunningBuilt = __filename.endsWith(path6.join("cli", "index.js"));
498
- var cliPacakgeLocation = isRunningBuilt ? path6.resolve(__dirname, "..") : path6.resolve(__dirname, "../../../..");
499
- var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
500
- devServer = http.createServer((req, res) => {
501
- if (!req.url) {
502
- res.end(404);
503
- return;
504
- }
505
- const parsedUrl = url.parse(req.url, true);
506
- res.setHeader(
507
- "Cache-Control",
508
- "no-cache, max-age=0, must-revalidate, no-store"
509
- );
510
- res.setHeader("Pragma", "no-cache");
511
- res.setHeader("Expires", "-1");
512
- try {
513
- if (parsedUrl.path && parsedUrl.path.includes("static/") && !parsedUrl.path.includes("_next/static/")) {
514
- void serveStaticFile(res, parsedUrl, staticBaseDirRelativePath);
515
- } else if (!isNextReady) {
516
- void nextReadyPromise.then(
517
- () => nextHandleRequest?.(req, res, parsedUrl)
518
- );
519
- } else {
520
- void nextHandleRequest?.(req, res, parsedUrl);
521
- }
522
- } catch (e) {
523
- console.error("caught error", e);
524
- res.writeHead(500);
525
- res.end();
526
- }
527
- });
528
- const { portAlreadyInUse } = await safeAsyncServerListen(devServer, port);
529
- if (!portAlreadyInUse) {
530
- console.log(chalk.greenBright(` React Email ${package_default.version}`));
531
- console.log(` Running preview at: http://localhost:${port}
532
- `);
533
- } else {
534
- const nextPortToTry = port + 1;
535
- console.warn(
536
- ` ${logSymbols.warning} Port ${port} is already in use, trying ${nextPortToTry}`
537
- );
538
- return startDevServer(
539
- emailsDirRelativePath,
540
- staticBaseDirRelativePath,
541
- nextPortToTry
542
- );
543
- }
544
- devServer.on("close", async () => {
545
- await app.close();
546
- });
547
- devServer.on("error", (e) => {
548
- console.error(
549
- ` ${logSymbols.error} preview server error: `,
550
- JSON.stringify(e)
551
- );
552
- process.exit(1);
553
- });
554
- const spinner = ora({
555
- text: "Getting react-email preview server ready...\n",
556
- prefixText: " "
557
- }).start();
558
- closeOraOnSIGNIT(spinner);
559
- const timeBeforeNextReady = performance.now();
560
- process.env = {
561
- ...process.env,
562
- ...getEnvVariablesForPreviewApp(
563
- // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
564
- path6.normalize(emailsDirRelativePath),
565
- cliPacakgeLocation,
566
- process.cwd()
567
- )
568
- };
569
- const app = next({
570
- // passing in env here does not get the environment variables there
571
- dev: true,
572
- hostname: "localhost",
573
- port,
574
- dir: cliPacakgeLocation
575
- });
576
- let isNextReady = false;
577
- const nextReadyPromise = app.prepare();
578
- await nextReadyPromise;
579
- isNextReady = true;
580
- const nextHandleRequest = app.getRequestHandler();
581
- const secondsToNextReady = ((performance.now() - timeBeforeNextReady) / 1e3).toFixed(1);
582
- spinner.stopAndPersist({
583
- text: `Ready in ${secondsToNextReady}s
584
- `,
585
- symbol: logSymbols.success
586
- });
587
- return devServer;
588
- };
589
- var makeExitHandler = (options) => (_codeOrSignal) => {
590
- if (typeof devServer !== "undefined") {
591
- console.log("\nshutting down dev server");
592
- devServer.close();
593
- devServer = void 0;
594
- }
595
- if (options?.shouldKillProcess) {
596
- process.exit(options.killWithErrorCode ? 1 : 0);
597
- }
598
- };
599
- process.on("exit", makeExitHandler());
600
- process.on(
601
- "SIGINT",
602
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
603
- );
604
- process.on(
605
- "SIGUSR1",
606
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
607
- );
608
- process.on(
609
- "SIGUSR2",
610
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: false })
611
- );
612
- process.on(
613
- "uncaughtException",
614
- makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
615
- );
616
-
617
675
  // src/cli/commands/dev.ts
618
676
  var dev = async ({ dir: emailsDirRelativePath, port }) => {
619
677
  try {
@@ -704,11 +762,18 @@ var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory) => {
704
762
  // src/utils/render-resolver-esbuild-plugin.ts
705
763
  import path8 from "path";
706
764
  import { promises as fs6 } from "fs";
765
+ function escapeStringForRegex(string) {
766
+ return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
767
+ }
707
768
  var renderResolver = (emailTemplates) => ({
708
769
  name: "render-resolver",
709
770
  setup: (b) => {
710
771
  b.onLoad(
711
- { filter: new RegExp(emailTemplates.join("|")) },
772
+ {
773
+ filter: new RegExp(
774
+ emailTemplates.map((emailPath) => escapeStringForRegex(emailPath)).join("|")
775
+ )
776
+ },
712
777
  async ({ path: pathToFile }) => {
713
778
  return {
714
779
  contents: `${await fs6.readFile(pathToFile, "utf8")};