react-email 2.1.3-canary.1 → 2.1.3

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.js CHANGED
@@ -340,7 +340,7 @@ var import_commander = require("commander");
340
340
  // package.json
341
341
  var package_default = {
342
342
  name: "react-email",
343
- version: "2.1.3-canary.1",
343
+ version: "2.1.3",
344
344
  description: "A live preview of your emails right in your browser.",
345
345
  bin: {
346
346
  email: "./cli/index.js"
@@ -374,7 +374,6 @@ var package_default = {
374
374
  "@radix-ui/react-slot": "1.0.2",
375
375
  "@radix-ui/react-toggle-group": "1.0.4",
376
376
  "@radix-ui/react-tooltip": "1.0.7",
377
- "@react-email/render": "0.0.14-canary.0",
378
377
  "@swc/core": "1.3.101",
379
378
  "@types/react": "^18.2.0",
380
379
  "@types/react-dom": "^18.2.0",
@@ -411,6 +410,8 @@ var package_default = {
411
410
  typescript: "5.1.6"
412
411
  },
413
412
  devDependencies: {
413
+ "@react-email/components": "0.0.18",
414
+ "@react-email/render": "0.0.14",
414
415
  "@types/fs-extra": "11.0.1",
415
416
  "@types/mime-types": "2.1.4",
416
417
  "@types/node": "18.0.0",
@@ -757,11 +758,11 @@ var createDependencyGraph = function() {
757
758
  case 1:
758
759
  filePaths = _state.sent();
759
760
  modulePaths = filePaths.filter(isJavascriptModule);
760
- graph = Object.fromEntries(modulePaths.map(function(path11) {
761
+ graph = Object.fromEntries(modulePaths.map(function(path12) {
761
762
  return [
762
- path11,
763
+ path12,
763
764
  {
764
- path: path11,
765
+ path: path12,
765
766
  dependencyPaths: [],
766
767
  dependentPaths: [],
767
768
  moduleDependencies: []
@@ -1686,13 +1687,12 @@ var dev = function() {
1686
1687
  };
1687
1688
  }();
1688
1689
  // src/cli/commands/export.ts
1689
- var import_node_fs6 = __toESM(require("fs"));
1690
- var import_node_path7 = __toESM(require("path"));
1690
+ var import_node_fs7 = __toESM(require("fs"));
1691
+ var import_node_path8 = __toESM(require("path"));
1691
1692
  var import_glob = require("glob");
1692
1693
  var import_esbuild = require("esbuild");
1693
1694
  var import_ora2 = __toESM(require("ora"));
1694
1695
  var import_log_symbols2 = __toESM(require("log-symbols"));
1695
- var import_render = require("@react-email/render");
1696
1696
  var import_normalize_path = __toESM(require("normalize-path"));
1697
1697
  var import_shelljs = require("shelljs");
1698
1698
  // src/actions/get-emails-directory-metadata.ts
@@ -1774,11 +1774,98 @@ var getEmailsDirectoryMetadata = function() {
1774
1774
  return _ref.apply(this, arguments);
1775
1775
  };
1776
1776
  }();
1777
+ // src/utils/render-resolver-esbuild-plugin.ts
1778
+ var import_node_path7 = __toESM(require("path"));
1779
+ var import_node_fs6 = require("fs");
1780
+ var renderResolver = function(emailTemplates) {
1781
+ return {
1782
+ name: "render-resolver",
1783
+ setup: function(b) {
1784
+ b.onLoad({
1785
+ filter: new RegExp(emailTemplates.join("|"))
1786
+ }, function() {
1787
+ var _ref = _async_to_generator(function(param) {
1788
+ var pathToFile, _tmp, _, _1;
1789
+ return _ts_generator(this, function(_state) {
1790
+ switch(_state.label){
1791
+ case 0:
1792
+ pathToFile = param.path;
1793
+ _tmp = {};
1794
+ _1 = (_ = "").concat;
1795
+ return [
1796
+ 4,
1797
+ import_node_fs6.promises.readFile(pathToFile, "utf8")
1798
+ ];
1799
+ case 1:
1800
+ return [
1801
+ 2,
1802
+ (_tmp.contents = _1.apply(_, [
1803
+ _state.sent(),
1804
+ ";\n export { renderAsync } from 'react-email-module-that-will-export-render'\n "
1805
+ ]), _tmp.loader = import_node_path7.default.extname(pathToFile).slice(1), _tmp)
1806
+ ];
1807
+ }
1808
+ });
1809
+ });
1810
+ return function(_) {
1811
+ return _ref.apply(this, arguments);
1812
+ };
1813
+ }());
1814
+ b.onResolve({
1815
+ filter: /^react-email-module-that-will-export-render$/
1816
+ }, function() {
1817
+ var _ref = _async_to_generator(function(args) {
1818
+ var options, result;
1819
+ return _ts_generator(this, function(_state) {
1820
+ switch(_state.label){
1821
+ case 0:
1822
+ options = {
1823
+ kind: "import-statement",
1824
+ importer: args.importer,
1825
+ resolveDir: args.resolveDir,
1826
+ namespace: args.namespace
1827
+ };
1828
+ return [
1829
+ 4,
1830
+ b.resolve("@react-email/render", options)
1831
+ ];
1832
+ case 1:
1833
+ result = _state.sent();
1834
+ if (result.errors.length === 0) {
1835
+ return [
1836
+ 2,
1837
+ result
1838
+ ];
1839
+ }
1840
+ return [
1841
+ 4,
1842
+ b.resolve("@react-email/components", options)
1843
+ ];
1844
+ case 2:
1845
+ result = _state.sent();
1846
+ if (result.errors.length > 0 && result.errors[0]) {
1847
+ result.errors[0].text = "Failed trying to import `renderAsync` 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?";
1848
+ }
1849
+ return [
1850
+ 2,
1851
+ result
1852
+ ];
1853
+ }
1854
+ });
1855
+ });
1856
+ return function(args) {
1857
+ return _ref.apply(this, arguments);
1858
+ };
1859
+ }());
1860
+ }
1861
+ };
1862
+ };
1777
1863
  // src/cli/commands/export.ts
1864
+ var import_react = require("react");
1778
1865
  var getEmailTemplatesFromDirectory = function(emailDirectory) {
1779
1866
  var templatePaths = [];
1780
1867
  emailDirectory.emailFilenames.forEach(function(filename) {
1781
- return templatePaths.push(import_node_path7.default.join(emailDirectory.absolutePath, filename));
1868
+ return templatePaths.push(import_node_path8.default.join(emailDirectory.absolutePath, filename));
1782
1869
  });
1783
1870
  emailDirectory.subDirectories.forEach(function(directory) {
1784
1871
  var _templatePaths;
@@ -1788,147 +1875,235 @@ var getEmailTemplatesFromDirectory = function(emailDirectory) {
1788
1875
  };
1789
1876
  var exportTemplates = function() {
1790
1877
  var _ref = _async_to_generator(function(pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) {
1791
- var spinner, emailsDirectoryMetadata, allTemplates, buildResult, allBuiltTemplates, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, template, component, rendered, htmlPath, staticDirectoryPath, pathToDumpStaticFilesInto, result, fileTree;
1878
+ var spinner, emailsDirectoryMetadata, allTemplates, exception, buildFailure, allBuiltTemplates, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, template, emailModule, rendered, htmlPath, exception1, err, staticDirectoryPath, pathToDumpStaticFilesInto, result, fileTree;
1792
1879
  return _ts_generator(this, function(_state) {
1793
1880
  switch(_state.label){
1794
1881
  case 0:
1795
- if (import_node_fs6.default.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
1796
- import_node_fs6.default.rmSync(pathToWhereEmailMarkupShouldBeDumped, {
1882
+ if (import_node_fs7.default.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
1883
+ import_node_fs7.default.rmSync(pathToWhereEmailMarkupShouldBeDumped, {
1797
1884
  recursive: true
1798
1885
  });
1799
1886
  }
1800
- spinner = (0, import_ora2.default)("Preparing files...\n").start();
1801
- closeOraOnSIGNIT(spinner);
1887
+ if (!options.silent) {
1888
+ spinner = (0, import_ora2.default)("Preparing files...\n").start();
1889
+ closeOraOnSIGNIT(spinner);
1890
+ }
1802
1891
  return [
1803
1892
  4,
1804
- getEmailsDirectoryMetadata(import_node_path7.default.join(process.cwd(), emailsDirectoryPath))
1893
+ getEmailsDirectoryMetadata(import_node_path8.default.resolve(process.cwd(), emailsDirectoryPath))
1805
1894
  ];
1806
1895
  case 1:
1807
1896
  emailsDirectoryMetadata = _state.sent();
1808
1897
  if (typeof emailsDirectoryMetadata === "undefined") {
1809
- spinner.stopAndPersist({
1810
- symbol: import_log_symbols2.default.error,
1811
- text: "Could not find the directory at ".concat(emailsDirectoryPath)
1812
- });
1898
+ if (spinner) {
1899
+ spinner.stopAndPersist({
1900
+ symbol: import_log_symbols2.default.error,
1901
+ text: "Could not find the directory at ".concat(emailsDirectoryPath)
1902
+ });
1903
+ }
1813
1904
  return [
1814
1905
  2
1815
1906
  ];
1816
1907
  }
1817
1908
  allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
1818
- buildResult = (0, import_esbuild.buildSync)({
1819
- bundle: true,
1820
- entryPoints: allTemplates,
1821
- platform: "node",
1822
- format: "cjs",
1823
- loader: {
1824
- ".js": "jsx"
1825
- },
1826
- outExtension: {
1827
- ".js": ".cjs"
1828
- },
1829
- jsx: "transform",
1830
- write: true,
1831
- outdir: pathToWhereEmailMarkupShouldBeDumped
1832
- });
1833
- if (buildResult.warnings.length > 0) {
1834
- console.warn(buildResult.warnings);
1835
- }
1836
- if (buildResult.errors.length > 0) {
1909
+ _state.label = 2;
1910
+ case 2:
1911
+ _state.trys.push([
1912
+ 2,
1913
+ 4,
1914
+ ,
1915
+ 5
1916
+ ]);
1917
+ return [
1918
+ 4,
1919
+ (0, import_esbuild.build)({
1920
+ bundle: true,
1921
+ entryPoints: allTemplates,
1922
+ plugins: [
1923
+ renderResolver(allTemplates)
1924
+ ],
1925
+ platform: "node",
1926
+ format: "cjs",
1927
+ loader: {
1928
+ ".js": "jsx"
1929
+ },
1930
+ outExtension: {
1931
+ ".js": ".cjs"
1932
+ },
1933
+ jsx: "transform",
1934
+ write: true,
1935
+ outdir: pathToWhereEmailMarkupShouldBeDumped
1936
+ })
1937
+ ];
1938
+ case 3:
1939
+ _state.sent();
1940
+ return [
1941
+ 3,
1942
+ 5
1943
+ ];
1944
+ case 4:
1945
+ exception = _state.sent();
1946
+ buildFailure = exception;
1947
+ if (spinner) {
1837
1948
  spinner.stopAndPersist({
1838
1949
  symbol: import_log_symbols2.default.error,
1839
1950
  text: "Failed to build emails"
1840
1951
  });
1841
- console.error(buildResult.errors);
1842
- throw new Error("esbuild bundling process for email templates:\n".concat(allTemplates.map(function(p) {
1843
- return "- ".concat(p);
1844
- }).join("\n")));
1845
1952
  }
1846
- spinner.succeed();
1953
+ console.warn(buildFailure.warnings);
1954
+ console.error(buildFailure.errors);
1955
+ throw new Error("esbuild bundling process for email templates failed:\n".concat(allTemplates.map(function(p) {
1956
+ return "- ".concat(p);
1957
+ }).join("\n")));
1958
+ case 5:
1959
+ if (spinner) {
1960
+ spinner.succeed();
1961
+ }
1847
1962
  allBuiltTemplates = import_glob.glob.sync((0, import_normalize_path.default)("".concat(pathToWhereEmailMarkupShouldBeDumped, "/**/*.cjs")), {
1848
1963
  absolute: true
1849
1964
  });
1850
1965
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1966
+ _state.label = 6;
1967
+ case 6:
1968
+ _state.trys.push([
1969
+ 6,
1970
+ 13,
1971
+ 14,
1972
+ 15
1973
+ ]);
1974
+ _iterator = allBuiltTemplates[Symbol.iterator]();
1975
+ _state.label = 7;
1976
+ case 7:
1977
+ if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
1978
+ 3,
1979
+ 12
1980
+ ];
1981
+ template = _step.value;
1982
+ _state.label = 8;
1983
+ case 8:
1984
+ _state.trys.push([
1985
+ 8,
1986
+ 10,
1987
+ ,
1988
+ 11
1989
+ ]);
1990
+ if (spinner) {
1991
+ spinner.text = "rendering ".concat(template.split("/").pop());
1992
+ spinner.render();
1993
+ }
1994
+ delete require.cache[template];
1995
+ emailModule = require(template);
1996
+ return [
1997
+ 4,
1998
+ emailModule.renderAsync((0, import_react.createElement)(emailModule.default, {}), options)
1999
+ ];
2000
+ case 9:
2001
+ rendered = _state.sent();
2002
+ htmlPath = template.replace(".cjs", options.plainText ? ".txt" : ".html");
2003
+ (0, import_node_fs7.writeFileSync)(htmlPath, rendered);
2004
+ (0, import_node_fs7.unlinkSync)(template);
2005
+ return [
2006
+ 3,
2007
+ 11
2008
+ ];
2009
+ case 10:
2010
+ exception1 = _state.sent();
2011
+ if (spinner) {
2012
+ spinner.stopAndPersist({
2013
+ symbol: import_log_symbols2.default.error,
2014
+ text: "failed when rendering ".concat(template.split("/").pop())
2015
+ });
2016
+ }
2017
+ console.error(exception1);
2018
+ throw exception1;
2019
+ case 11:
2020
+ _iteratorNormalCompletion = true;
2021
+ return [
2022
+ 3,
2023
+ 7
2024
+ ];
2025
+ case 12:
2026
+ return [
2027
+ 3,
2028
+ 15
2029
+ ];
2030
+ case 13:
2031
+ err = _state.sent();
2032
+ _didIteratorError = true;
2033
+ _iteratorError = err;
2034
+ return [
2035
+ 3,
2036
+ 15
2037
+ ];
2038
+ case 14:
1851
2039
  try {
1852
- for(_iterator = allBuiltTemplates[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1853
- template = _step.value;
1854
- try {
1855
- spinner.text = "rendering ".concat(template.split("/").pop());
1856
- spinner.render();
1857
- delete require.cache[template];
1858
- component = require(template);
1859
- rendered = (0, import_render.render)(component.default({}), options);
1860
- htmlPath = template.replace(".cjs", options.plainText ? ".txt" : ".html");
1861
- (0, import_node_fs6.writeFileSync)(htmlPath, rendered);
1862
- (0, import_node_fs6.unlinkSync)(template);
1863
- } catch (exception) {
1864
- spinner.stopAndPersist({
1865
- symbol: import_log_symbols2.default.error,
1866
- text: "failed when rendering ".concat(template.split("/").pop())
1867
- });
1868
- console.error(exception);
1869
- throw exception;
1870
- }
2040
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2041
+ _iterator.return();
1871
2042
  }
1872
- } catch (err) {
1873
- _didIteratorError = true;
1874
- _iteratorError = err;
1875
2043
  } finally{
1876
- try {
1877
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1878
- _iterator.return();
1879
- }
1880
- } finally{
1881
- if (_didIteratorError) {
1882
- throw _iteratorError;
1883
- }
2044
+ if (_didIteratorError) {
2045
+ throw _iteratorError;
1884
2046
  }
1885
2047
  }
1886
- spinner.succeed("Rendered all files");
1887
- spinner.text = "Copying static files";
1888
- spinner.render();
1889
- staticDirectoryPath = import_node_path7.default.join(emailsDirectoryPath, "static");
1890
- if (!import_node_fs6.default.existsSync(staticDirectoryPath)) return [
2048
+ return [
2049
+ 7
2050
+ ];
2051
+ case 15:
2052
+ if (spinner) {
2053
+ spinner.succeed("Rendered all files");
2054
+ spinner.text = "Copying static files";
2055
+ spinner.render();
2056
+ }
2057
+ staticDirectoryPath = import_node_path8.default.join(emailsDirectoryPath, "static");
2058
+ if (!import_node_fs7.default.existsSync(staticDirectoryPath)) return [
1891
2059
  3,
1892
- 4
2060
+ 18
1893
2061
  ];
1894
- pathToDumpStaticFilesInto = import_node_path7.default.join(pathToWhereEmailMarkupShouldBeDumped, "static");
1895
- if (!import_node_fs6.default.existsSync(pathToDumpStaticFilesInto)) return [
2062
+ pathToDumpStaticFilesInto = import_node_path8.default.join(pathToWhereEmailMarkupShouldBeDumped, "static");
2063
+ if (!import_node_fs7.default.existsSync(pathToDumpStaticFilesInto)) return [
1896
2064
  3,
1897
- 3
2065
+ 17
1898
2066
  ];
1899
2067
  return [
1900
2068
  4,
1901
- import_node_fs6.default.promises.rm(pathToDumpStaticFilesInto, {
2069
+ import_node_fs7.default.promises.rm(pathToDumpStaticFilesInto, {
1902
2070
  recursive: true
1903
2071
  })
1904
2072
  ];
1905
- case 2:
2073
+ case 16:
1906
2074
  _state.sent();
1907
- _state.label = 3;
1908
- case 3:
1909
- result = (0, import_shelljs.cp)("-r", staticDirectoryPath, import_node_path7.default.join(pathToWhereEmailMarkupShouldBeDumped, "static"));
2075
+ _state.label = 17;
2076
+ case 17:
2077
+ result = (0, import_shelljs.cp)("-r", staticDirectoryPath, import_node_path8.default.join(pathToWhereEmailMarkupShouldBeDumped, "static"));
1910
2078
  if (result.code > 0) {
1911
- spinner.stopAndPersist({
1912
- symbol: import_log_symbols2.default.error,
1913
- text: "Failed to copy static files"
1914
- });
2079
+ if (spinner) {
2080
+ spinner.stopAndPersist({
2081
+ symbol: import_log_symbols2.default.error,
2082
+ text: "Failed to copy static files"
2083
+ });
2084
+ }
1915
2085
  throw new Error("Something went wrong while copying the file to ".concat(pathToWhereEmailMarkupShouldBeDumped, "/static, ").concat(result.stderr));
1916
2086
  }
1917
- _state.label = 4;
1918
- case 4:
2087
+ _state.label = 18;
2088
+ case 18:
2089
+ if (!(spinner && !options.silent)) return [
2090
+ 3,
2091
+ 20
2092
+ ];
1919
2093
  spinner.succeed();
1920
2094
  return [
1921
2095
  4,
1922
2096
  tree(pathToWhereEmailMarkupShouldBeDumped, 4)
1923
2097
  ];
1924
- case 5:
2098
+ case 19:
1925
2099
  fileTree = _state.sent();
1926
2100
  console.log(fileTree);
1927
2101
  spinner.stopAndPersist({
1928
2102
  symbol: import_log_symbols2.default.success,
1929
2103
  text: "Successfully exported emails"
1930
2104
  });
1931
- process.exit();
2105
+ _state.label = 20;
2106
+ case 20:
1932
2107
  return [
1933
2108
  2
1934
2109
  ];
@@ -1940,8 +2115,8 @@ var exportTemplates = function() {
1940
2115
  };
1941
2116
  }();
1942
2117
  // src/cli/commands/build.ts
1943
- var import_node_fs7 = __toESM(require("fs"));
1944
- var import_node_path8 = __toESM(require("path"));
2118
+ var import_node_fs8 = __toESM(require("fs"));
2119
+ var import_node_path9 = __toESM(require("path"));
1945
2120
  var import_ora3 = __toESM(require("ora"));
1946
2121
  var import_shelljs2 = __toESM(require("shelljs"));
1947
2122
  var import_node_child_process = require("child_process");
@@ -1976,13 +2151,13 @@ var setNextEnvironmentVariablesForBuild = function() {
1976
2151
  switch(_state.label){
1977
2152
  case 0:
1978
2153
  envVariables = _object_spread_props(_object_spread({}, getEnvVariablesForPreviewApp(// If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
1979
- import_node_path8.default.normalize(emailsDirRelativePath), "PLACEHOLDER", "PLACEHOLDER")), {
2154
+ import_node_path9.default.normalize(emailsDirRelativePath), "PLACEHOLDER", "PLACEHOLDER")), {
1980
2155
  NEXT_PUBLIC_IS_BUILDING: "true"
1981
2156
  });
1982
2157
  nextConfigContents = "\nconst path = require('path');\n/** @type {import('next').NextConfig} */\nmodule.exports = {\n env: {\n ...".concat(JSON.stringify(envVariables), ",\n NEXT_PUBLIC_USER_PROJECT_LOCATION: path.resolve(process.cwd(), '../'),\n NEXT_PUBLIC_CLI_PACKAGE_LOCATION: process.cwd(),\n },\n // this is needed so that the code for building emails works properly\n webpack: (\n /** @type {import('webpack').Configuration & { externals: string[] }} */\n config,\n { isServer }\n ) => {\n if (isServer) {\n config.externals.push('esbuild');\n }\n\n return config;\n },\n typescript: {\n ignoreBuildErrors: true\n },\n eslint: {\n ignoreDuringBuilds: true\n },\n experimental: {\n webpackBuildWorker: true\n },\n}");
1983
2158
  return [
1984
2159
  4,
1985
- import_node_fs7.default.promises.writeFile(import_node_path8.default.resolve(builtPreviewAppPath, "./next.config.js"), nextConfigContents, "utf8")
2160
+ import_node_fs8.default.promises.writeFile(import_node_path9.default.resolve(builtPreviewAppPath, "./next.config.js"), nextConfigContents, "utf8")
1986
2161
  ];
1987
2162
  case 1:
1988
2163
  _state.sent();
@@ -2000,7 +2175,7 @@ var getEmailSlugsFromEmailDirectory = function(emailDirectory, emailsDirectoryAb
2000
2175
  var directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
2001
2176
  var slugs = [];
2002
2177
  emailDirectory.emailFilenames.forEach(function(filename) {
2003
- return slugs.push(import_node_path8.default.join(directoryPathRelativeToEmailsDirectory, filename).split(import_node_path8.default.sep).filter(function(segment) {
2178
+ return slugs.push(import_node_path9.default.join(directoryPathRelativeToEmailsDirectory, filename).split(import_node_path9.default.sep).filter(function(segment) {
2004
2179
  return segment.length > 0;
2005
2180
  }));
2006
2181
  });
@@ -2030,7 +2205,7 @@ var forceSSGForEmailPreviews = function() {
2030
2205
  });
2031
2206
  return [
2032
2207
  4,
2033
- import_node_fs7.default.promises.appendFile(import_node_path8.default.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"), "\n\nexport function generateStaticParams() { \n return Promise.resolve(\n ".concat(JSON.stringify(parameters), "\n );\n}"), "utf8")
2208
+ import_node_fs8.default.promises.appendFile(import_node_path9.default.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"), "\n\nexport function generateStaticParams() { \n return Promise.resolve(\n ".concat(JSON.stringify(parameters), "\n );\n}"), "utf8")
2034
2209
  ];
2035
2210
  case 2:
2036
2211
  _state.sent();
@@ -2050,11 +2225,11 @@ var updatePackageJson = function() {
2050
2225
  return _ts_generator(this, function(_state) {
2051
2226
  switch(_state.label){
2052
2227
  case 0:
2053
- packageJsonPath = import_node_path8.default.resolve(builtPreviewAppPath, "./package.json");
2228
+ packageJsonPath = import_node_path9.default.resolve(builtPreviewAppPath, "./package.json");
2054
2229
  _ = JSON.parse;
2055
2230
  return [
2056
2231
  4,
2057
- import_node_fs7.default.promises.readFile(packageJsonPath, "utf8")
2232
+ import_node_fs8.default.promises.readFile(packageJsonPath, "utf8")
2058
2233
  ];
2059
2234
  case 1:
2060
2235
  packageJson = _.apply(JSON, [
@@ -2063,11 +2238,12 @@ var updatePackageJson = function() {
2063
2238
  packageJson.scripts.build = "next build";
2064
2239
  packageJson.scripts.start = "next start";
2065
2240
  packageJson.name = "preview-server";
2066
- delete packageJson.dependencies["@react-email/render"];
2241
+ delete packageJson.devDependencies["@react-email/render"];
2242
+ delete packageJson.devDependencies["@react-email/components"];
2067
2243
  packageJson.dependencies.sharp = "0.33.2";
2068
2244
  return [
2069
2245
  4,
2070
- import_node_fs7.default.promises.writeFile(packageJsonPath, JSON.stringify(packageJson), "utf8")
2246
+ import_node_fs8.default.promises.writeFile(packageJsonPath, JSON.stringify(packageJson), "utf8")
2071
2247
  ];
2072
2248
  case 2:
2073
2249
  _state.sent();
@@ -2104,7 +2280,7 @@ var npmInstall = function() {
2104
2280
  return _ref.apply(this, arguments);
2105
2281
  };
2106
2282
  }();
2107
- var build = function() {
2283
+ var build2 = function() {
2108
2284
  var _ref = _async_to_generator(function(param) {
2109
2285
  var emailsDirRelativePath, packageManager, spinner, emailsDirPath, staticPath, builtPreviewAppPath, builtStaticDirectory, error;
2110
2286
  return _ts_generator(this, function(_state) {
@@ -2125,20 +2301,20 @@ var build = function() {
2125
2301
  }).start();
2126
2302
  closeOraOnSIGNIT(spinner);
2127
2303
  spinner.text = "Checking if emails folder exists";
2128
- if (!import_node_fs7.default.existsSync(emailsDirRelativePath)) {
2304
+ if (!import_node_fs8.default.existsSync(emailsDirRelativePath)) {
2129
2305
  throw new Error("Missing ".concat(emailsDirRelativePath, " folder"));
2130
2306
  }
2131
- emailsDirPath = import_node_path8.default.join(process.cwd(), emailsDirRelativePath);
2132
- staticPath = import_node_path8.default.join(emailsDirPath, "static");
2133
- builtPreviewAppPath = import_node_path8.default.join(process.cwd(), ".react-email");
2134
- if (!import_node_fs7.default.existsSync(builtPreviewAppPath)) return [
2307
+ emailsDirPath = import_node_path9.default.join(process.cwd(), emailsDirRelativePath);
2308
+ staticPath = import_node_path9.default.join(emailsDirPath, "static");
2309
+ builtPreviewAppPath = import_node_path9.default.join(process.cwd(), ".react-email");
2310
+ if (!import_node_fs8.default.existsSync(builtPreviewAppPath)) return [
2135
2311
  3,
2136
2312
  3
2137
2313
  ];
2138
2314
  spinner.text = "Deleting pre-existing `.react-email` folder";
2139
2315
  return [
2140
2316
  4,
2141
- import_node_fs7.default.promises.rm(builtPreviewAppPath, {
2317
+ import_node_fs8.default.promises.rm(builtPreviewAppPath, {
2142
2318
  recursive: true
2143
2319
  })
2144
2320
  ];
@@ -2149,7 +2325,7 @@ var build = function() {
2149
2325
  spinner.text = "Copying preview app from CLI to `.react-email`";
2150
2326
  return [
2151
2327
  4,
2152
- import_node_fs7.default.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
2328
+ import_node_fs8.default.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
2153
2329
  recursive: true,
2154
2330
  filter: function(source) {
2155
2331
  return !source.includes("/cli/") && !source.includes("/.next/") && !/\/node_modules\/?$/.test(source);
@@ -2158,15 +2334,15 @@ var build = function() {
2158
2334
  ];
2159
2335
  case 4:
2160
2336
  _state.sent();
2161
- if (!import_node_fs7.default.existsSync(staticPath)) return [
2337
+ if (!import_node_fs8.default.existsSync(staticPath)) return [
2162
2338
  3,
2163
2339
  6
2164
2340
  ];
2165
2341
  spinner.text = "Copying `static` folder into `.react-email/public/static`";
2166
- builtStaticDirectory = import_node_path8.default.resolve(builtPreviewAppPath, "./public/static");
2342
+ builtStaticDirectory = import_node_path9.default.resolve(builtPreviewAppPath, "./public/static");
2167
2343
  return [
2168
2344
  4,
2169
- import_node_fs7.default.promises.cp(staticPath, builtStaticDirectory, {
2345
+ import_node_fs8.default.promises.cp(staticPath, builtStaticDirectory, {
2170
2346
  recursive: true
2171
2347
  })
2172
2348
  ];
@@ -2231,13 +2407,13 @@ var build = function() {
2231
2407
  }
2232
2408
  });
2233
2409
  });
2234
- return function build(_) {
2410
+ return function build2(_) {
2235
2411
  return _ref.apply(this, arguments);
2236
2412
  };
2237
2413
  }();
2238
2414
  // src/cli/commands/start.ts
2239
- var import_node_fs8 = __toESM(require("fs"));
2240
- var import_node_path9 = __toESM(require("path"));
2415
+ var import_node_fs9 = __toESM(require("fs"));
2416
+ var import_node_path10 = __toESM(require("path"));
2241
2417
  var import_node_child_process2 = require("child_process");
2242
2418
  var start = function() {
2243
2419
  var _ref = _async_to_generator(function() {
@@ -2245,8 +2421,8 @@ var start = function() {
2245
2421
  return _ts_generator(this, function(_state) {
2246
2422
  try {
2247
2423
  usersProjectLocation = process.cwd();
2248
- builtPreviewPath = import_node_path9.default.resolve(usersProjectLocation, "./.react-email");
2249
- if (!import_node_fs8.default.existsSync(builtPreviewPath)) {
2424
+ builtPreviewPath = import_node_path10.default.resolve(usersProjectLocation, "./.react-email");
2425
+ if (!import_node_fs9.default.existsSync(builtPreviewPath)) {
2250
2426
  throw new Error("Could not find `.react-email`, maybe you haven't ran `email build`?");
2251
2427
  }
2252
2428
  nextStart = (0, import_node_child_process2.spawn)("npm", [
@@ -2277,12 +2453,13 @@ var start = function() {
2277
2453
  var PACKAGE_NAME = "react-email";
2278
2454
  import_commander.program.name(PACKAGE_NAME).description("A live preview of your emails right in your browser").version(package_default.version);
2279
2455
  import_commander.program.command("dev").description("Starts the preview email development app").option("-d, --dir <path>", "Directory with your email templates", "./emails").option("-p --port <port>", "Port to run dev server on", "3000").action(dev);
2280
- import_commander.program.command("build").description("Copies the preview app for onto .react-email and builds it").option("-d, --dir <path>", "Directory with your email templates", "./emails").option("-p --packageManager <name>", "Package name to use on installation on `.react-email`", "npm").action(build);
2456
+ import_commander.program.command("build").description("Copies the preview app for onto .react-email and builds it").option("-d, --dir <path>", "Directory with your email templates", "./emails").option("-p --packageManager <name>", "Package name to use on installation on `.react-email`", "npm").action(build2);
2281
2457
  import_commander.program.command("start").description('Runs the built preview app that is inside of ".react-email"').action(start);
2282
- import_commander.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").action(function(param) {
2283
- var outDir = param.outDir, pretty = param.pretty, plainText = param.plainText, srcDir = param.dir;
2458
+ import_commander.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("-s, --silent", "To, or not to show a spinner with process information", false).action(function(param) {
2459
+ var outDir = param.outDir, pretty = param.pretty, plainText = param.plainText, silent = param.silent, srcDir = param.dir;
2284
2460
  return exportTemplates(outDir, srcDir, {
2285
2461
  pretty: pretty,
2462
+ silent: silent,
2286
2463
  plainText: plainText
2287
2464
  });
2288
2465
  });
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-canary.1",
16
+ version: "2.1.3",
17
17
  description: "A live preview of your emails right in your browser.",
18
18
  bin: {
19
19
  email: "./cli/index.js"
@@ -47,7 +47,6 @@ var package_default = {
47
47
  "@radix-ui/react-slot": "1.0.2",
48
48
  "@radix-ui/react-toggle-group": "1.0.4",
49
49
  "@radix-ui/react-tooltip": "1.0.7",
50
- "@react-email/render": "0.0.14-canary.0",
51
50
  "@swc/core": "1.3.101",
52
51
  "@types/react": "^18.2.0",
53
52
  "@types/react-dom": "^18.2.0",
@@ -84,6 +83,8 @@ var package_default = {
84
83
  typescript: "5.1.6"
85
84
  },
86
85
  devDependencies: {
86
+ "@react-email/components": "0.0.18",
87
+ "@react-email/render": "0.0.14",
87
88
  "@types/fs-extra": "11.0.1",
88
89
  "@types/mime-types": "2.1.4",
89
90
  "@types/node": "18.0.0",
@@ -220,10 +221,10 @@ var createDependencyGraph = async (directory) => {
220
221
  const filePaths = await readAllFilesInsideDirectory(directory);
221
222
  const modulePaths = filePaths.filter(isJavascriptModule);
222
223
  const graph = Object.fromEntries(
223
- modulePaths.map((path11) => [
224
- path11,
224
+ modulePaths.map((path12) => [
225
+ path12,
225
226
  {
226
- path: path11,
227
+ path: path12,
227
228
  dependencyPaths: [],
228
229
  dependentPaths: [],
229
230
  moduleDependencies: []
@@ -633,13 +634,12 @@ var dev = async ({ dir: emailsDirRelativePath, port }) => {
633
634
  };
634
635
 
635
636
  // src/cli/commands/export.ts
636
- import fs6, { unlinkSync, writeFileSync } from "fs";
637
- import path8 from "path";
637
+ import fs7, { unlinkSync, writeFileSync } from "fs";
638
+ import path9 from "path";
638
639
  import { glob } from "glob";
639
- import { buildSync } from "esbuild";
640
+ import { build } from "esbuild";
640
641
  import ora2 from "ora";
641
642
  import logSymbols2 from "log-symbols";
642
- import { render } from "@react-email/render";
643
643
  import normalize from "normalize-path";
644
644
  import { cp } from "shelljs";
645
645
 
@@ -701,11 +701,52 @@ var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory) => {
701
701
  });
702
702
  };
703
703
 
704
+ // src/utils/render-resolver-esbuild-plugin.ts
705
+ import path8 from "path";
706
+ import { promises as fs6 } from "fs";
707
+ var renderResolver = (emailTemplates) => ({
708
+ name: "render-resolver",
709
+ setup: (b) => {
710
+ b.onLoad(
711
+ { filter: new RegExp(emailTemplates.join("|")) },
712
+ async ({ path: pathToFile }) => {
713
+ return {
714
+ contents: `${await fs6.readFile(pathToFile, "utf8")};
715
+ export { renderAsync } from 'react-email-module-that-will-export-render'
716
+ `,
717
+ loader: path8.extname(pathToFile).slice(1)
718
+ };
719
+ }
720
+ );
721
+ b.onResolve(
722
+ { filter: /^react-email-module-that-will-export-render$/ },
723
+ async (args) => {
724
+ const options = {
725
+ kind: "import-statement",
726
+ importer: args.importer,
727
+ resolveDir: args.resolveDir,
728
+ namespace: args.namespace
729
+ };
730
+ let result = await b.resolve("@react-email/render", options);
731
+ if (result.errors.length === 0) {
732
+ return result;
733
+ }
734
+ result = await b.resolve("@react-email/components", options);
735
+ if (result.errors.length > 0 && result.errors[0]) {
736
+ result.errors[0].text = "Failed trying to import `renderAsync` 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?";
737
+ }
738
+ return result;
739
+ }
740
+ );
741
+ }
742
+ });
743
+
704
744
  // src/cli/commands/export.ts
745
+ import { createElement } from "react";
705
746
  var getEmailTemplatesFromDirectory = (emailDirectory) => {
706
747
  const templatePaths = [];
707
748
  emailDirectory.emailFilenames.forEach(
708
- (filename) => templatePaths.push(path8.join(emailDirectory.absolutePath, filename))
749
+ (filename) => templatePaths.push(path9.join(emailDirectory.absolutePath, filename))
709
750
  );
710
751
  emailDirectory.subDirectories.forEach((directory) => {
711
752
  templatePaths.push(...getEmailTemplatesFromDirectory(directory));
@@ -713,48 +754,58 @@ var getEmailTemplatesFromDirectory = (emailDirectory) => {
713
754
  return templatePaths;
714
755
  };
715
756
  var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
716
- if (fs6.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
717
- fs6.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
757
+ if (fs7.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
758
+ fs7.rmSync(pathToWhereEmailMarkupShouldBeDumped, { recursive: true });
759
+ }
760
+ let spinner;
761
+ if (!options.silent) {
762
+ spinner = ora2("Preparing files...\n").start();
763
+ closeOraOnSIGNIT(spinner);
718
764
  }
719
- const spinner = ora2("Preparing files...\n").start();
720
- closeOraOnSIGNIT(spinner);
721
765
  const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
722
- path8.join(process.cwd(), emailsDirectoryPath)
766
+ path9.resolve(process.cwd(), emailsDirectoryPath)
723
767
  );
724
768
  if (typeof emailsDirectoryMetadata === "undefined") {
725
- spinner.stopAndPersist({
726
- symbol: logSymbols2.error,
727
- text: `Could not find the directory at ${emailsDirectoryPath}`
728
- });
769
+ if (spinner) {
770
+ spinner.stopAndPersist({
771
+ symbol: logSymbols2.error,
772
+ text: `Could not find the directory at ${emailsDirectoryPath}`
773
+ });
774
+ }
729
775
  return;
730
776
  }
731
777
  const allTemplates = getEmailTemplatesFromDirectory(emailsDirectoryMetadata);
732
- const buildResult = buildSync({
733
- bundle: true,
734
- entryPoints: allTemplates,
735
- platform: "node",
736
- format: "cjs",
737
- loader: { ".js": "jsx" },
738
- outExtension: { ".js": ".cjs" },
739
- jsx: "transform",
740
- write: true,
741
- outdir: pathToWhereEmailMarkupShouldBeDumped
742
- });
743
- if (buildResult.warnings.length > 0) {
744
- console.warn(buildResult.warnings);
745
- }
746
- if (buildResult.errors.length > 0) {
747
- spinner.stopAndPersist({
748
- symbol: logSymbols2.error,
749
- text: "Failed to build emails"
778
+ try {
779
+ await build({
780
+ bundle: true,
781
+ entryPoints: allTemplates,
782
+ plugins: [renderResolver(allTemplates)],
783
+ platform: "node",
784
+ format: "cjs",
785
+ loader: { ".js": "jsx" },
786
+ outExtension: { ".js": ".cjs" },
787
+ jsx: "transform",
788
+ write: true,
789
+ outdir: pathToWhereEmailMarkupShouldBeDumped
750
790
  });
751
- console.error(buildResult.errors);
791
+ } catch (exception) {
792
+ const buildFailure = exception;
793
+ if (spinner) {
794
+ spinner.stopAndPersist({
795
+ symbol: logSymbols2.error,
796
+ text: "Failed to build emails"
797
+ });
798
+ }
799
+ console.warn(buildFailure.warnings);
800
+ console.error(buildFailure.errors);
752
801
  throw new Error(
753
- `esbuild bundling process for email templates:
802
+ `esbuild bundling process for email templates failed:
754
803
  ${allTemplates.map((p) => `- ${p}`).join("\n")}`
755
804
  );
756
805
  }
757
- spinner.succeed();
806
+ if (spinner) {
807
+ spinner.succeed();
808
+ }
758
809
  const allBuiltTemplates = glob.sync(
759
810
  normalize(`${pathToWhereEmailMarkupShouldBeDumped}/**/*.cjs`),
760
811
  {
@@ -763,11 +814,16 @@ ${allTemplates.map((p) => `- ${p}`).join("\n")}`
763
814
  );
764
815
  for (const template of allBuiltTemplates) {
765
816
  try {
766
- spinner.text = `rendering ${template.split("/").pop()}`;
767
- spinner.render();
817
+ if (spinner) {
818
+ spinner.text = `rendering ${template.split("/").pop()}`;
819
+ spinner.render();
820
+ }
768
821
  delete __require.cache[template];
769
- const component = __require(template);
770
- const rendered = render(component.default({}), options);
822
+ const emailModule = __require(template);
823
+ const rendered = await emailModule.renderAsync(
824
+ createElement(emailModule.default, {}),
825
+ options
826
+ );
771
827
  const htmlPath = template.replace(
772
828
  ".cjs",
773
829
  options.plainText ? ".txt" : ".html"
@@ -775,53 +831,60 @@ ${allTemplates.map((p) => `- ${p}`).join("\n")}`
775
831
  writeFileSync(htmlPath, rendered);
776
832
  unlinkSync(template);
777
833
  } catch (exception) {
778
- spinner.stopAndPersist({
779
- symbol: logSymbols2.error,
780
- text: `failed when rendering ${template.split("/").pop()}`
781
- });
834
+ if (spinner) {
835
+ spinner.stopAndPersist({
836
+ symbol: logSymbols2.error,
837
+ text: `failed when rendering ${template.split("/").pop()}`
838
+ });
839
+ }
782
840
  console.error(exception);
783
841
  throw exception;
784
842
  }
785
843
  }
786
- spinner.succeed("Rendered all files");
787
- spinner.text = `Copying static files`;
788
- spinner.render();
789
- const staticDirectoryPath = path8.join(emailsDirectoryPath, "static");
790
- if (fs6.existsSync(staticDirectoryPath)) {
791
- const pathToDumpStaticFilesInto = path8.join(
844
+ if (spinner) {
845
+ spinner.succeed("Rendered all files");
846
+ spinner.text = `Copying static files`;
847
+ spinner.render();
848
+ }
849
+ const staticDirectoryPath = path9.join(emailsDirectoryPath, "static");
850
+ if (fs7.existsSync(staticDirectoryPath)) {
851
+ const pathToDumpStaticFilesInto = path9.join(
792
852
  pathToWhereEmailMarkupShouldBeDumped,
793
853
  "static"
794
854
  );
795
- if (fs6.existsSync(pathToDumpStaticFilesInto))
796
- await fs6.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
855
+ if (fs7.existsSync(pathToDumpStaticFilesInto))
856
+ await fs7.promises.rm(pathToDumpStaticFilesInto, { recursive: true });
797
857
  const result = cp(
798
858
  "-r",
799
859
  staticDirectoryPath,
800
- path8.join(pathToWhereEmailMarkupShouldBeDumped, "static")
860
+ path9.join(pathToWhereEmailMarkupShouldBeDumped, "static")
801
861
  );
802
862
  if (result.code > 0) {
803
- spinner.stopAndPersist({
804
- symbol: logSymbols2.error,
805
- text: "Failed to copy static files"
806
- });
863
+ if (spinner) {
864
+ spinner.stopAndPersist({
865
+ symbol: logSymbols2.error,
866
+ text: "Failed to copy static files"
867
+ });
868
+ }
807
869
  throw new Error(
808
870
  `Something went wrong while copying the file to ${pathToWhereEmailMarkupShouldBeDumped}/static, ${result.stderr}`
809
871
  );
810
872
  }
811
873
  }
812
- spinner.succeed();
813
- const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
814
- console.log(fileTree);
815
- spinner.stopAndPersist({
816
- symbol: logSymbols2.success,
817
- text: "Successfully exported emails"
818
- });
819
- process.exit();
874
+ if (spinner && !options.silent) {
875
+ spinner.succeed();
876
+ const fileTree = await tree(pathToWhereEmailMarkupShouldBeDumped, 4);
877
+ console.log(fileTree);
878
+ spinner.stopAndPersist({
879
+ symbol: logSymbols2.success,
880
+ text: "Successfully exported emails"
881
+ });
882
+ }
820
883
  };
821
884
 
822
885
  // src/cli/commands/build.ts
823
- import fs7 from "fs";
824
- import path9 from "path";
886
+ import fs8 from "fs";
887
+ import path10 from "path";
825
888
  import ora3 from "ora";
826
889
  import shell from "shelljs";
827
890
  import { spawn } from "child_process";
@@ -854,7 +917,7 @@ var setNextEnvironmentVariablesForBuild = async (emailsDirRelativePath, builtPre
854
917
  const envVariables = {
855
918
  ...getEnvVariablesForPreviewApp(
856
919
  // If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
857
- path9.normalize(emailsDirRelativePath),
920
+ path10.normalize(emailsDirRelativePath),
858
921
  "PLACEHOLDER",
859
922
  "PLACEHOLDER"
860
923
  ),
@@ -891,8 +954,8 @@ module.exports = {
891
954
  webpackBuildWorker: true
892
955
  },
893
956
  }`;
894
- await fs7.promises.writeFile(
895
- path9.resolve(builtPreviewAppPath, "./next.config.js"),
957
+ await fs8.promises.writeFile(
958
+ path10.resolve(builtPreviewAppPath, "./next.config.js"),
896
959
  nextConfigContents,
897
960
  "utf8"
898
961
  );
@@ -902,7 +965,7 @@ var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePa
902
965
  const slugs = [];
903
966
  emailDirectory.emailFilenames.forEach(
904
967
  (filename) => slugs.push(
905
- path9.join(directoryPathRelativeToEmailsDirectory, filename).split(path9.sep).filter((segment) => segment.length > 0)
968
+ path10.join(directoryPathRelativeToEmailsDirectory, filename).split(path10.sep).filter((segment) => segment.length > 0)
906
969
  )
907
970
  );
908
971
  emailDirectory.subDirectories.forEach((directory) => {
@@ -924,8 +987,8 @@ var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
924
987
  emailDirectoryMetadata,
925
988
  emailsDirPath
926
989
  ).map((slug) => ({ slug }));
927
- await fs7.promises.appendFile(
928
- path9.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
990
+ await fs8.promises.appendFile(
991
+ path10.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
929
992
  `
930
993
 
931
994
  export function generateStaticParams() {
@@ -937,16 +1000,17 @@ export function generateStaticParams() {
937
1000
  );
938
1001
  };
939
1002
  var updatePackageJson = async (builtPreviewAppPath) => {
940
- const packageJsonPath = path9.resolve(builtPreviewAppPath, "./package.json");
1003
+ const packageJsonPath = path10.resolve(builtPreviewAppPath, "./package.json");
941
1004
  const packageJson = JSON.parse(
942
- await fs7.promises.readFile(packageJsonPath, "utf8")
1005
+ await fs8.promises.readFile(packageJsonPath, "utf8")
943
1006
  );
944
1007
  packageJson.scripts.build = "next build";
945
1008
  packageJson.scripts.start = "next start";
946
1009
  packageJson.name = "preview-server";
947
- delete packageJson.dependencies["@react-email/render"];
1010
+ delete packageJson.devDependencies["@react-email/render"];
1011
+ delete packageJson.devDependencies["@react-email/components"];
948
1012
  packageJson.dependencies.sharp = "0.33.2";
949
- await fs7.promises.writeFile(
1013
+ await fs8.promises.writeFile(
950
1014
  packageJsonPath,
951
1015
  JSON.stringify(packageJson),
952
1016
  "utf8"
@@ -971,7 +1035,7 @@ var npmInstall = async (builtPreviewAppPath, packageManager) => {
971
1035
  );
972
1036
  });
973
1037
  };
974
- var build = async ({
1038
+ var build2 = async ({
975
1039
  dir: emailsDirRelativePath,
976
1040
  packageManager
977
1041
  }) => {
@@ -982,30 +1046,30 @@ var build = async ({
982
1046
  }).start();
983
1047
  closeOraOnSIGNIT(spinner);
984
1048
  spinner.text = "Checking if emails folder exists";
985
- if (!fs7.existsSync(emailsDirRelativePath)) {
1049
+ if (!fs8.existsSync(emailsDirRelativePath)) {
986
1050
  throw new Error(`Missing ${emailsDirRelativePath} folder`);
987
1051
  }
988
- const emailsDirPath = path9.join(process.cwd(), emailsDirRelativePath);
989
- const staticPath = path9.join(emailsDirPath, "static");
990
- const builtPreviewAppPath = path9.join(process.cwd(), ".react-email");
991
- if (fs7.existsSync(builtPreviewAppPath)) {
1052
+ const emailsDirPath = path10.join(process.cwd(), emailsDirRelativePath);
1053
+ const staticPath = path10.join(emailsDirPath, "static");
1054
+ const builtPreviewAppPath = path10.join(process.cwd(), ".react-email");
1055
+ if (fs8.existsSync(builtPreviewAppPath)) {
992
1056
  spinner.text = "Deleting pre-existing `.react-email` folder";
993
- await fs7.promises.rm(builtPreviewAppPath, { recursive: true });
1057
+ await fs8.promises.rm(builtPreviewAppPath, { recursive: true });
994
1058
  }
995
1059
  spinner.text = "Copying preview app from CLI to `.react-email`";
996
- await fs7.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
1060
+ await fs8.promises.cp(cliPacakgeLocation, builtPreviewAppPath, {
997
1061
  recursive: true,
998
1062
  filter: (source) => {
999
1063
  return !source.includes("/cli/") && !source.includes("/.next/") && !/\/node_modules\/?$/.test(source);
1000
1064
  }
1001
1065
  });
1002
- if (fs7.existsSync(staticPath)) {
1066
+ if (fs8.existsSync(staticPath)) {
1003
1067
  spinner.text = "Copying `static` folder into `.react-email/public/static`";
1004
- const builtStaticDirectory = path9.resolve(
1068
+ const builtStaticDirectory = path10.resolve(
1005
1069
  builtPreviewAppPath,
1006
1070
  "./public/static"
1007
1071
  );
1008
- await fs7.promises.cp(staticPath, builtStaticDirectory, {
1072
+ await fs8.promises.cp(staticPath, builtStaticDirectory, {
1009
1073
  recursive: true
1010
1074
  });
1011
1075
  }
@@ -1032,17 +1096,17 @@ var build = async ({
1032
1096
  };
1033
1097
 
1034
1098
  // src/cli/commands/start.ts
1035
- import fs8 from "fs";
1036
- import path10 from "path";
1099
+ import fs9 from "fs";
1100
+ import path11 from "path";
1037
1101
  import { spawn as spawn2 } from "child_process";
1038
1102
  var start = async () => {
1039
1103
  try {
1040
1104
  const usersProjectLocation = process.cwd();
1041
- const builtPreviewPath = path10.resolve(
1105
+ const builtPreviewPath = path11.resolve(
1042
1106
  usersProjectLocation,
1043
1107
  "./.react-email"
1044
1108
  );
1045
- if (!fs8.existsSync(builtPreviewPath)) {
1109
+ if (!fs9.existsSync(builtPreviewPath)) {
1046
1110
  throw new Error(
1047
1111
  "Could not find `.react-email`, maybe you haven't ran `email build`?"
1048
1112
  );
@@ -1070,9 +1134,13 @@ program.command("build").description("Copies the preview app for onto .react-ema
1070
1134
  "-p --packageManager <name>",
1071
1135
  "Package name to use on installation on `.react-email`",
1072
1136
  "npm"
1073
- ).action(build);
1137
+ ).action(build2);
1074
1138
  program.command("start").description('Runs the built preview app that is inside of ".react-email"').action(start);
1075
- 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").action(
1076
- ({ outDir, pretty, plainText, dir: srcDir }) => exportTemplates(outDir, srcDir, { pretty, plainText })
1139
+ 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(
1140
+ "-s, --silent",
1141
+ "To, or not to show a spinner with process information",
1142
+ false
1143
+ ).action(
1144
+ ({ outDir, pretty, plainText, silent, dir: srcDir }) => exportTemplates(outDir, srcDir, { pretty, silent, plainText })
1077
1145
  );
1078
1146
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-email",
3
- "version": "2.1.3-canary.1",
3
+ "version": "2.1.3",
4
4
  "description": "A live preview of your emails right in your browser.",
5
5
  "bin": {
6
6
  "email": "./cli/index.js"
@@ -26,7 +26,6 @@
26
26
  "@radix-ui/react-slot": "1.0.2",
27
27
  "@radix-ui/react-toggle-group": "1.0.4",
28
28
  "@radix-ui/react-tooltip": "1.0.7",
29
- "@react-email/render": "0.0.14-canary.0",
30
29
  "@swc/core": "1.3.101",
31
30
  "@types/react": "^18.2.0",
32
31
  "@types/react-dom": "^18.2.0",
@@ -63,6 +62,8 @@
63
62
  "typescript": "5.1.6"
64
63
  },
65
64
  "devDependencies": {
65
+ "@react-email/components": "0.0.18",
66
+ "@react-email/render": "0.0.14",
66
67
  "@types/fs-extra": "11.0.1",
67
68
  "@types/mime-types": "2.1.4",
68
69
  "@types/node": "18.0.0",
@@ -1,20 +1,14 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
  import path from 'node:path';
3
3
  import vm from 'node:vm';
4
- import fs from 'node:fs/promises';
5
4
  import { type RawSourceMap } from 'source-map-js';
6
- import {
7
- type OutputFile,
8
- build,
9
- type ResolveOptions,
10
- type BuildFailure,
11
- type Loader,
12
- } from 'esbuild';
5
+ import { type OutputFile, build, type BuildFailure } from 'esbuild';
13
6
  import type { renderAsync } from '@react-email/render';
14
7
  import type { EmailTemplate as EmailComponent } from './types/email-template';
15
8
  import type { ErrorObject } from './types/error-object';
16
9
  import { improveErrorWithSourceMap } from './improve-error-with-sourcemap';
17
10
  import { staticNodeModulesForVM } from './static-node-modules-for-vm';
11
+ import { renderResolver } from './render-resolver-esbuild-plugin';
18
12
 
19
13
  export const getEmailComponent = async (
20
14
  emailPath: string,
@@ -33,46 +27,7 @@ export const getEmailComponent = async (
33
27
  const buildData = await build({
34
28
  bundle: true,
35
29
  entryPoints: [emailPath],
36
- plugins: [
37
- {
38
- name: 'add-export-for-render-async',
39
- setup(b) {
40
- b.onLoad(
41
- { filter: new RegExp(path.basename(emailPath)) },
42
- async () => ({
43
- contents: `${await fs.readFile(emailPath, 'utf8')};
44
- export { renderAsync } from 'react-email-module-that-will-export-render'
45
- `,
46
- loader: path.extname(emailPath).slice(1) as Loader,
47
- }),
48
- );
49
-
50
- b.onResolve(
51
- { filter: /^react-email-module-that-will-export-render$/ },
52
- async (args) => {
53
- const options: ResolveOptions = {
54
- kind: 'import-statement',
55
- importer: args.importer,
56
- resolveDir: args.resolveDir,
57
- namespace: args.namespace,
58
- };
59
- let result = await b.resolve('@react-email/render', options);
60
- if (result.errors.length === 0) {
61
- return result;
62
- }
63
-
64
- // If @react-email/render does not exist, resolve to @react-email/components
65
- result = await b.resolve('@react-email/components', options);
66
- if (result.errors.length > 0) {
67
- result.errors[0]!.text =
68
- "Failed trying to import `renderAsync` 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?";
69
- }
70
- return result;
71
- },
72
- );
73
- },
74
- },
75
- ],
30
+ plugins: [renderResolver([emailPath])],
76
31
  platform: 'node',
77
32
  write: false,
78
33
 
@@ -0,0 +1,52 @@
1
+ import path from 'node:path';
2
+ import { promises as fs } from 'node:fs';
3
+ import type { Loader, PluginBuild, ResolveOptions } from 'esbuild';
4
+
5
+ /**
6
+ * Made to export the `renderAsync` function out of the user's email template
7
+ * so that issues like https://github.com/resend/react-email/issues/649 don't
8
+ * happen.
9
+ *
10
+ * This avoids multiple versions of React being involved, i.e., the version
11
+ * in the CLI vs. the version the user has on their emails.
12
+ */
13
+ export const renderResolver = (emailTemplates: string[]) => ({
14
+ name: 'render-resolver',
15
+ setup: (b: PluginBuild) => {
16
+ b.onLoad(
17
+ { filter: new RegExp(emailTemplates.join('|')) },
18
+ async ({ path: pathToFile }) => {
19
+ return {
20
+ contents: `${await fs.readFile(pathToFile, 'utf8')};
21
+ export { renderAsync } from 'react-email-module-that-will-export-render'
22
+ `,
23
+ loader: path.extname(pathToFile).slice(1) as Loader,
24
+ };
25
+ },
26
+ );
27
+
28
+ b.onResolve(
29
+ { filter: /^react-email-module-that-will-export-render$/ },
30
+ async (args) => {
31
+ const options: ResolveOptions = {
32
+ kind: 'import-statement',
33
+ importer: args.importer,
34
+ resolveDir: args.resolveDir,
35
+ namespace: args.namespace,
36
+ };
37
+ let result = await b.resolve('@react-email/render', options);
38
+ if (result.errors.length === 0) {
39
+ return result;
40
+ }
41
+
42
+ // If @react-email/render does not exist, resolve to @react-email/components
43
+ result = await b.resolve('@react-email/components', options);
44
+ if (result.errors.length > 0 && result.errors[0]) {
45
+ result.errors[0].text =
46
+ "Failed trying to import `renderAsync` 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?";
47
+ }
48
+ return result;
49
+ },
50
+ );
51
+ },
52
+ });