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 +301 -124
- package/cli/index.mjs +167 -99
- package/package.json +3 -2
- package/src/utils/get-email-component.ts +3 -48
- package/src/utils/render-resolver-esbuild-plugin.ts +52 -0
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
|
|
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(
|
|
761
|
+
graph = Object.fromEntries(modulePaths.map(function(path12) {
|
|
761
762
|
return [
|
|
762
|
-
|
|
763
|
+
path12,
|
|
763
764
|
{
|
|
764
|
-
path:
|
|
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
|
|
1690
|
-
var
|
|
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(
|
|
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,
|
|
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 (
|
|
1796
|
-
|
|
1882
|
+
if (import_node_fs7.default.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
|
|
1883
|
+
import_node_fs7.default.rmSync(pathToWhereEmailMarkupShouldBeDumped, {
|
|
1797
1884
|
recursive: true
|
|
1798
1885
|
});
|
|
1799
1886
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
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(
|
|
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
|
|
1810
|
-
|
|
1811
|
-
|
|
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
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1853
|
-
|
|
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
|
-
|
|
1877
|
-
|
|
1878
|
-
_iterator.return();
|
|
1879
|
-
}
|
|
1880
|
-
} finally{
|
|
1881
|
-
if (_didIteratorError) {
|
|
1882
|
-
throw _iteratorError;
|
|
1883
|
-
}
|
|
2044
|
+
if (_didIteratorError) {
|
|
2045
|
+
throw _iteratorError;
|
|
1884
2046
|
}
|
|
1885
2047
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
if (
|
|
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
|
-
|
|
2060
|
+
18
|
|
1893
2061
|
];
|
|
1894
|
-
pathToDumpStaticFilesInto =
|
|
1895
|
-
if (!
|
|
2062
|
+
pathToDumpStaticFilesInto = import_node_path8.default.join(pathToWhereEmailMarkupShouldBeDumped, "static");
|
|
2063
|
+
if (!import_node_fs7.default.existsSync(pathToDumpStaticFilesInto)) return [
|
|
1896
2064
|
3,
|
|
1897
|
-
|
|
2065
|
+
17
|
|
1898
2066
|
];
|
|
1899
2067
|
return [
|
|
1900
2068
|
4,
|
|
1901
|
-
|
|
2069
|
+
import_node_fs7.default.promises.rm(pathToDumpStaticFilesInto, {
|
|
1902
2070
|
recursive: true
|
|
1903
2071
|
})
|
|
1904
2072
|
];
|
|
1905
|
-
case
|
|
2073
|
+
case 16:
|
|
1906
2074
|
_state.sent();
|
|
1907
|
-
_state.label =
|
|
1908
|
-
case
|
|
1909
|
-
result = (0, import_shelljs.cp)("-r", staticDirectoryPath,
|
|
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
|
|
1912
|
-
|
|
1913
|
-
|
|
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 =
|
|
1918
|
-
case
|
|
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
|
|
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
|
-
|
|
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
|
|
1944
|
-
var
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
2228
|
+
packageJsonPath = import_node_path9.default.resolve(builtPreviewAppPath, "./package.json");
|
|
2054
2229
|
_ = JSON.parse;
|
|
2055
2230
|
return [
|
|
2056
2231
|
4,
|
|
2057
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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 (!
|
|
2304
|
+
if (!import_node_fs8.default.existsSync(emailsDirRelativePath)) {
|
|
2129
2305
|
throw new Error("Missing ".concat(emailsDirRelativePath, " folder"));
|
|
2130
2306
|
}
|
|
2131
|
-
emailsDirPath =
|
|
2132
|
-
staticPath =
|
|
2133
|
-
builtPreviewAppPath =
|
|
2134
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
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 (!
|
|
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 =
|
|
2342
|
+
builtStaticDirectory = import_node_path9.default.resolve(builtPreviewAppPath, "./public/static");
|
|
2167
2343
|
return [
|
|
2168
2344
|
4,
|
|
2169
|
-
|
|
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
|
|
2410
|
+
return function build2(_) {
|
|
2235
2411
|
return _ref.apply(this, arguments);
|
|
2236
2412
|
};
|
|
2237
2413
|
}();
|
|
2238
2414
|
// src/cli/commands/start.ts
|
|
2239
|
-
var
|
|
2240
|
-
var
|
|
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 =
|
|
2249
|
-
if (!
|
|
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(
|
|
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
|
|
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((
|
|
224
|
-
|
|
224
|
+
modulePaths.map((path12) => [
|
|
225
|
+
path12,
|
|
225
226
|
{
|
|
226
|
-
path:
|
|
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
|
|
637
|
-
import
|
|
637
|
+
import fs7, { unlinkSync, writeFileSync } from "fs";
|
|
638
|
+
import path9 from "path";
|
|
638
639
|
import { glob } from "glob";
|
|
639
|
-
import {
|
|
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(
|
|
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 (
|
|
717
|
-
|
|
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
|
-
|
|
766
|
+
path9.resolve(process.cwd(), emailsDirectoryPath)
|
|
723
767
|
);
|
|
724
768
|
if (typeof emailsDirectoryMetadata === "undefined") {
|
|
725
|
-
spinner
|
|
726
|
-
|
|
727
|
-
|
|
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
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
767
|
-
|
|
817
|
+
if (spinner) {
|
|
818
|
+
spinner.text = `rendering ${template.split("/").pop()}`;
|
|
819
|
+
spinner.render();
|
|
820
|
+
}
|
|
768
821
|
delete __require.cache[template];
|
|
769
|
-
const
|
|
770
|
-
const rendered =
|
|
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
|
|
779
|
-
|
|
780
|
-
|
|
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
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
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 (
|
|
796
|
-
await
|
|
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
|
-
|
|
860
|
+
path9.join(pathToWhereEmailMarkupShouldBeDumped, "static")
|
|
801
861
|
);
|
|
802
862
|
if (result.code > 0) {
|
|
803
|
-
spinner
|
|
804
|
-
|
|
805
|
-
|
|
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.
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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
|
|
824
|
-
import
|
|
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
|
-
|
|
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
|
|
895
|
-
|
|
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
|
-
|
|
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
|
|
928
|
-
|
|
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 =
|
|
1003
|
+
const packageJsonPath = path10.resolve(builtPreviewAppPath, "./package.json");
|
|
941
1004
|
const packageJson = JSON.parse(
|
|
942
|
-
await
|
|
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.
|
|
1010
|
+
delete packageJson.devDependencies["@react-email/render"];
|
|
1011
|
+
delete packageJson.devDependencies["@react-email/components"];
|
|
948
1012
|
packageJson.dependencies.sharp = "0.33.2";
|
|
949
|
-
await
|
|
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
|
|
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 (!
|
|
1049
|
+
if (!fs8.existsSync(emailsDirRelativePath)) {
|
|
986
1050
|
throw new Error(`Missing ${emailsDirRelativePath} folder`);
|
|
987
1051
|
}
|
|
988
|
-
const emailsDirPath =
|
|
989
|
-
const staticPath =
|
|
990
|
-
const builtPreviewAppPath =
|
|
991
|
-
if (
|
|
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
|
|
1057
|
+
await fs8.promises.rm(builtPreviewAppPath, { recursive: true });
|
|
994
1058
|
}
|
|
995
1059
|
spinner.text = "Copying preview app from CLI to `.react-email`";
|
|
996
|
-
await
|
|
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 (
|
|
1066
|
+
if (fs8.existsSync(staticPath)) {
|
|
1003
1067
|
spinner.text = "Copying `static` folder into `.react-email/public/static`";
|
|
1004
|
-
const builtStaticDirectory =
|
|
1068
|
+
const builtStaticDirectory = path10.resolve(
|
|
1005
1069
|
builtPreviewAppPath,
|
|
1006
1070
|
"./public/static"
|
|
1007
1071
|
);
|
|
1008
|
-
await
|
|
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
|
|
1036
|
-
import
|
|
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 =
|
|
1105
|
+
const builtPreviewPath = path11.resolve(
|
|
1042
1106
|
usersProjectLocation,
|
|
1043
1107
|
"./.react-email"
|
|
1044
1108
|
);
|
|
1045
|
-
if (!
|
|
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(
|
|
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").
|
|
1076
|
-
|
|
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
|
|
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
|
+
});
|