react-email 4.1.0-canary.7 → 4.1.0-canary.9
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/CHANGELOG.md +24 -0
- package/dist/{cli/index.mjs → index.js} +445 -422
- package/package.json +11 -46
- package/src/commands/build.ts +306 -0
- package/src/commands/dev.ts +27 -0
- package/src/commands/export.ts +204 -0
- package/src/commands/start.ts +38 -0
- package/src/index.ts +55 -0
- package/src/utils/__snapshots__/tree.spec.ts.snap +27 -0
- package/src/utils/esbuild/renderring-utilities-exporter.ts +1 -1
- package/src/utils/get-emails-directory-metadata.spec.ts +1 -1
- package/src/utils/get-preview-server-location.ts +51 -0
- package/src/utils/index.ts +2 -6
- package/src/utils/packageJson.ts +4 -0
- package/src/utils/preview/get-env-variables-for-preview-app.ts +14 -0
- package/src/utils/preview/hot-reloading/create-dependency-graph.spec.ts +281 -0
- package/src/utils/preview/hot-reloading/create-dependency-graph.ts +321 -0
- package/src/utils/preview/hot-reloading/get-imported-modules.spec.ts +151 -0
- package/src/utils/preview/hot-reloading/get-imported-modules.ts +49 -0
- package/src/utils/preview/hot-reloading/resolve-path-aliases.spec.ts +11 -0
- package/src/utils/preview/hot-reloading/resolve-path-aliases.ts +32 -0
- package/src/utils/preview/hot-reloading/setup-hot-reloading.ts +121 -0
- package/src/utils/preview/hot-reloading/test/tsconfig.json +8 -0
- package/src/utils/preview/index.ts +2 -0
- package/src/utils/preview/serve-static-file.ts +51 -0
- package/src/utils/preview/start-dev-server.ts +234 -0
- package/src/utils/tree.spec.ts +5 -0
- package/src/utils/tree.ts +76 -0
- package/src/utils/types/hot-reload-change.ts +1 -1
- package/src/utils/types/hot-reload-event.ts +1 -1
- package/tsconfig.json +4 -10
- package/dist/preview/.next/BUILD_ID +0 -1
- package/dist/preview/.next/app-build-manifest.json +0 -44
- package/dist/preview/.next/app-path-routes-manifest.json +0 -6
- package/dist/preview/.next/build-manifest.json +0 -33
- package/dist/preview/.next/diagnostics/build-diagnostics.json +0 -6
- package/dist/preview/.next/diagnostics/framework.json +0 -1
- package/dist/preview/.next/export-marker.json +0 -6
- package/dist/preview/.next/images-manifest.json +0 -57
- package/dist/preview/.next/next-minimal-server.js.nft.json +0 -1
- package/dist/preview/.next/next-server.js.nft.json +0 -1
- package/dist/preview/.next/package.json +0 -1
- package/dist/preview/.next/prerender-manifest.json +0 -41
- package/dist/preview/.next/react-loadable-manifest.json +0 -1
- package/dist/preview/.next/required-server-files.json +0 -311
- package/dist/preview/.next/routes-manifest.json +0 -64
- package/dist/preview/.next/server/app/_not-found/page.js +0 -1
- package/dist/preview/.next/server/app/_not-found/page.js.nft.json +0 -1
- package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
- package/dist/preview/.next/server/app/favicon.ico/route.js +0 -1
- package/dist/preview/.next/server/app/favicon.ico/route.js.nft.json +0 -1
- package/dist/preview/.next/server/app/favicon.ico.body +0 -0
- package/dist/preview/.next/server/app/favicon.ico.meta +0 -1
- package/dist/preview/.next/server/app/page.js +0 -1
- package/dist/preview/.next/server/app/page.js.nft.json +0 -1
- package/dist/preview/.next/server/app/page_client-reference-manifest.js +0 -1
- package/dist/preview/.next/server/app/preview/[...slug]/page.js +0 -321
- package/dist/preview/.next/server/app/preview/[...slug]/page.js.nft.json +0 -1
- package/dist/preview/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +0 -1
- package/dist/preview/.next/server/app-paths-manifest.json +0 -6
- package/dist/preview/.next/server/chunks/134.js +0 -6
- package/dist/preview/.next/server/chunks/235.js +0 -15
- package/dist/preview/.next/server/chunks/343.js +0 -20
- package/dist/preview/.next/server/chunks/425.js +0 -1
- package/dist/preview/.next/server/chunks/428.js +0 -14
- package/dist/preview/.next/server/chunks/963.js +0 -1
- package/dist/preview/.next/server/functions-config-manifest.json +0 -4
- package/dist/preview/.next/server/interception-route-rewrite-manifest.js +0 -1
- package/dist/preview/.next/server/middleware-build-manifest.js +0 -1
- package/dist/preview/.next/server/middleware-manifest.json +0 -6
- package/dist/preview/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/dist/preview/.next/server/next-font-manifest.js +0 -1
- package/dist/preview/.next/server/next-font-manifest.json +0 -1
- package/dist/preview/.next/server/pages/500.html +0 -1
- package/dist/preview/.next/server/pages/_app.js +0 -1
- package/dist/preview/.next/server/pages/_app.js.nft.json +0 -1
- package/dist/preview/.next/server/pages/_document.js +0 -1
- package/dist/preview/.next/server/pages/_document.js.nft.json +0 -1
- package/dist/preview/.next/server/pages/_error.js +0 -1
- package/dist/preview/.next/server/pages/_error.js.nft.json +0 -1
- package/dist/preview/.next/server/pages-manifest.json +0 -5
- package/dist/preview/.next/server/server-reference-manifest.js +0 -1
- package/dist/preview/.next/server/server-reference-manifest.json +0 -1
- package/dist/preview/.next/server/webpack-runtime.js +0 -1
- package/dist/preview/.next/static/4K22R8mt8Z5akBgUuivvR/_buildManifest.js +0 -1
- package/dist/preview/.next/static/4K22R8mt8Z5akBgUuivvR/_ssgManifest.js +0 -1
- package/dist/preview/.next/static/chunks/107-3043079e7cb8bcae.js +0 -1
- package/dist/preview/.next/static/chunks/293-297b1eb2241f9a70.js +0 -1
- package/dist/preview/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +0 -1
- package/dist/preview/.next/static/chunks/45-1021fac82f766268.js +0 -1
- package/dist/preview/.next/static/chunks/484-25cf313c25750c6a.js +0 -1
- package/dist/preview/.next/static/chunks/589-817d8691661d370e.js +0 -1
- package/dist/preview/.next/static/chunks/902-c34acb56733e0ce1.js +0 -1
- package/dist/preview/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +0 -1
- package/dist/preview/.next/static/chunks/app/layout-ce14b7ba365bfddc.js +0 -1
- package/dist/preview/.next/static/chunks/app/page-65fd67d48528e2ba.js +0 -1
- package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-35fab824504104aa.js +0 -1
- package/dist/preview/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +0 -6
- package/dist/preview/.next/static/chunks/framework-b887e9fc751a9906.js +0 -1
- package/dist/preview/.next/static/chunks/main-9a03e7ba8acb1900.js +0 -1
- package/dist/preview/.next/static/chunks/main-app-dbd8e1ec12eabb66.js +0 -1
- package/dist/preview/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +0 -1
- package/dist/preview/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +0 -1
- package/dist/preview/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/dist/preview/.next/static/chunks/webpack-31c45daa2bd82a7b.js +0 -1
- package/dist/preview/.next/static/css/6f42d128f111d7fa.css +0 -3
- package/dist/preview/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
- package/dist/preview/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
- package/dist/preview/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
- package/dist/preview/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
- package/dist/preview/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
- package/dist/preview/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
- package/dist/preview/.next/static/media/6d93bde91c0c2823-s.woff2 +0 -0
- package/dist/preview/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
- package/dist/preview/.next/static/media/a34f9d1faa5f3315-s.p.woff2 +0 -0
- package/dist/preview/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
- package/dist/preview/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
- package/dist/preview/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
- package/dist/preview/.next/static/media/e4051546b3043204-s.p.otf +0 -0
- package/dist/preview/.next/static/media/logo.2ce2a759.png +0 -0
- package/dist/preview/.next/trace +0 -28
- package/dist/preview/.next/types/app/layout.ts +0 -84
- package/dist/preview/.next/types/app/page.ts +0 -84
- package/dist/preview/.next/types/app/preview/[...slug]/page.ts +0 -84
- package/dist/preview/.next/types/cache-life.d.ts +0 -141
- package/dist/preview/.next/types/package.json +0 -1
- package/module-punycode.d.ts +0 -3
- package/next-env.d.ts +0 -5
- package/next.config.js +0 -22
- package/postcss.config.js +0 -8
- package/scripts/build-preview-server.mjs +0 -33
- package/scripts/fill-caniemail-data.mjs +0 -36
- package/src/actions/email-validation/caniemail-data.ts +0 -85993
- package/src/actions/email-validation/check-compatibility.ts +0 -333
- package/src/actions/email-validation/check-images.spec.tsx +0 -100
- package/src/actions/email-validation/check-images.ts +0 -160
- package/src/actions/email-validation/check-links.spec.tsx +0 -113
- package/src/actions/email-validation/check-links.ts +0 -113
- package/src/actions/email-validation/get-code-location-from-ast-element.ts +0 -18
- package/src/actions/email-validation/quick-fetch.ts +0 -14
- package/src/actions/get-email-path-from-slug.ts +0 -32
- package/src/actions/get-emails-directory-metadata-action.ts +0 -19
- package/src/actions/render-email-by-path.tsx +0 -121
- package/src/animated-icons-data/help.json +0 -1082
- package/src/animated-icons-data/link.json +0 -1309
- package/src/animated-icons-data/load.json +0 -443
- package/src/animated-icons-data/mail.json +0 -1320
- package/src/app/env.ts +0 -15
- package/src/app/favicon.ico +0 -0
- package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
- package/src/app/fonts.ts +0 -39
- package/src/app/globals.css +0 -15
- package/src/app/layout.tsx +0 -45
- package/src/app/logo.png +0 -0
- package/src/app/page.tsx +0 -46
- package/src/app/preview/[...slug]/page.tsx +0 -157
- package/src/app/preview/[...slug]/preview.tsx +0 -234
- package/src/app/preview/[...slug]/rendering-error.tsx +0 -40
- package/src/components/button.tsx +0 -101
- package/src/components/code-container.tsx +0 -164
- package/src/components/code-snippet.tsx +0 -9
- package/src/components/code.tsx +0 -184
- package/src/components/heading.tsx +0 -113
- package/src/components/icons/icon-arrow-down.tsx +0 -16
- package/src/components/icons/icon-base.tsx +0 -26
- package/src/components/icons/icon-bug.tsx +0 -19
- package/src/components/icons/icon-button.tsx +0 -23
- package/src/components/icons/icon-check.tsx +0 -19
- package/src/components/icons/icon-clipboard.tsx +0 -40
- package/src/components/icons/icon-download.tsx +0 -19
- package/src/components/icons/icon-email.tsx +0 -18
- package/src/components/icons/icon-file.tsx +0 -19
- package/src/components/icons/icon-folder-open.tsx +0 -19
- package/src/components/icons/icon-folder.tsx +0 -18
- package/src/components/icons/icon-hide-sidebar.tsx +0 -23
- package/src/components/icons/icon-image.tsx +0 -19
- package/src/components/icons/icon-info.tsx +0 -18
- package/src/components/icons/icon-link.tsx +0 -14
- package/src/components/icons/icon-monitor.tsx +0 -19
- package/src/components/icons/icon-moon.tsx +0 -16
- package/src/components/icons/icon-phone.tsx +0 -26
- package/src/components/icons/icon-reload.tsx +0 -18
- package/src/components/icons/icon-source.tsx +0 -19
- package/src/components/icons/icon-stamp.tsx +0 -14
- package/src/components/icons/icon-sun.tsx +0 -16
- package/src/components/icons/icon-warning.tsx +0 -31
- package/src/components/index.ts +0 -7
- package/src/components/logo.tsx +0 -63
- package/src/components/resizable-wrapper.tsx +0 -173
- package/src/components/send.tsx +0 -134
- package/src/components/shell.tsx +0 -92
- package/src/components/sidebar/file-tree-directory-children.tsx +0 -139
- package/src/components/sidebar/file-tree-directory.tsx +0 -92
- package/src/components/sidebar/file-tree.tsx +0 -31
- package/src/components/sidebar/index.ts +0 -1
- package/src/components/sidebar/sidebar.tsx +0 -43
- package/src/components/text.tsx +0 -99
- package/src/components/toolbar/checking-results.tsx +0 -150
- package/src/components/toolbar/code-preview-line-link.tsx +0 -40
- package/src/components/toolbar/compatibility.tsx +0 -113
- package/src/components/toolbar/linter.tsx +0 -278
- package/src/components/toolbar/results.tsx +0 -51
- package/src/components/toolbar/spam-assassin.tsx +0 -155
- package/src/components/toolbar/toolbar-button.tsx +0 -52
- package/src/components/toolbar/use-cached-state.ts +0 -33
- package/src/components/toolbar.tsx +0 -349
- package/src/components/tooltip-content.tsx +0 -31
- package/src/components/tooltip.tsx +0 -19
- package/src/components/topbar/active-view-toggle-group.tsx +0 -86
- package/src/components/topbar/theme-toggle-group.tsx +0 -87
- package/src/components/topbar/view-size-controls.tsx +0 -247
- package/src/components/topbar.tsx +0 -59
- package/src/contexts/emails.tsx +0 -59
- package/src/contexts/fragment-identifier.tsx +0 -48
- package/src/contexts/preview.tsx +0 -79
- package/src/hooks/use-clamped-state.ts +0 -24
- package/src/hooks/use-email-rendering-result.ts +0 -58
- package/src/hooks/use-fragment-identifier.ts +0 -14
- package/src/hooks/use-hot-reload.ts +0 -31
- package/src/hooks/use-icon-animation.ts +0 -41
- package/src/hooks/use-iframe-color-scheme.ts +0 -35
- package/src/hooks/use-rendering-metadata.ts +0 -36
- package/src/utils/__snapshots__/get-email-component.spec.ts.snap +0 -3
- package/src/utils/caniemail/all-css-properties.ts +0 -358
- package/src/utils/caniemail/ast/__snapshots__/get-object-variables.spec.ts.snap +0 -74
- package/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap +0 -24
- package/src/utils/caniemail/ast/get-object-variables.spec.ts +0 -19
- package/src/utils/caniemail/ast/get-object-variables.ts +0 -61
- package/src/utils/caniemail/ast/get-used-style-properties.spec.ts +0 -23
- package/src/utils/caniemail/ast/get-used-style-properties.ts +0 -91
- package/src/utils/caniemail/get-compatibility-stats-for-entry.ts +0 -118
- package/src/utils/caniemail/get-css-functions.ts +0 -25
- package/src/utils/caniemail/get-css-property-names.ts +0 -32
- package/src/utils/caniemail/get-css-property-with-value.ts +0 -14
- package/src/utils/caniemail/get-css-unit.ts +0 -3
- package/src/utils/caniemail/get-element-attributes.ts +0 -7
- package/src/utils/caniemail/get-element-names.ts +0 -20
- package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +0 -30
- package/src/utils/caniemail/tailwind/get-tailwind-config.ts +0 -187
- package/src/utils/caniemail/tailwind/get-tailwind-metadata.spec.ts +0 -25
- package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +0 -45
- package/src/utils/caniemail/tailwind/setup-tailwind-context.ts +0 -15
- package/src/utils/cn.ts +0 -6
- package/src/utils/constants.ts +0 -6
- package/src/utils/contains-email-template.spec.ts +0 -107
- package/src/utils/contains-email-template.ts +0 -33
- package/src/utils/copy-text-to-clipboard.ts +0 -7
- package/src/utils/get-email-component.spec.ts +0 -41
- package/src/utils/get-email-component.ts +0 -134
- package/src/utils/get-line-and-column-from-offset.spec.ts +0 -11
- package/src/utils/get-line-and-column-from-offset.ts +0 -11
- package/src/utils/improve-error-with-sourcemap.ts +0 -85
- package/src/utils/js-email-detection.spec.ts +0 -24
- package/src/utils/language-map.ts +0 -7
- package/src/utils/linting.ts +0 -60
- package/src/utils/load-stream.ts +0 -15
- package/src/utils/result.ts +0 -49
- package/src/utils/run-bundled-code.ts +0 -64
- package/src/utils/sanitize.ts +0 -6
- package/src/utils/static-node-modules-for-vm.ts +0 -93
- package/src/utils/testing/js-email-export-default.js +0 -17
- package/src/utils/testing/js-email-test.js +0 -18
- package/src/utils/testing/mdx-email-test.js +0 -128
- package/src/utils/testing/request-response-email.tsx +0 -9
- package/src/utils/types/as.ts +0 -26
- package/src/utils/types/email-template.ts +0 -8
- package/src/utils/types/error-object.ts +0 -11
- package/src/utils/unreachable.ts +0 -8
- package/tailwind-internals.d.ts +0 -133
- package/tailwind.config.ts +0 -99
- /package/src/{components/toolbar/results-table.tsx → utils/preview/hot-reloading/test/some-file.ts} +0 -0
|
@@ -1,112 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// src/
|
|
3
|
+
// src/index.ts
|
|
4
4
|
import { program } from "commander";
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
var package_default = {
|
|
8
|
-
name: "react-email",
|
|
9
|
-
version: "4.1.0-canary.7",
|
|
10
|
-
description: "A live preview of your emails right in your browser.",
|
|
11
|
-
bin: {
|
|
12
|
-
email: "./dist/cli/index.mjs"
|
|
13
|
-
},
|
|
14
|
-
scripts: {
|
|
15
|
-
build: "tsup-node && node ./scripts/build-preview-server.mjs",
|
|
16
|
-
postbuild: "pnpm install --frozen-lockfile",
|
|
17
|
-
"caniemail:fetch": "node ./scripts/fill-caniemail-data.mjs",
|
|
18
|
-
clean: "rm -rf dist",
|
|
19
|
-
dev: "tsup-node --watch",
|
|
20
|
-
"dev:preview": "cd ../../apps/demo && tsx ../../packages/react-email/src/cli/index.ts dev",
|
|
21
|
-
test: "vitest run",
|
|
22
|
-
"test:watch": "vitest"
|
|
23
|
-
},
|
|
24
|
-
license: "MIT",
|
|
25
|
-
repository: {
|
|
26
|
-
type: "git",
|
|
27
|
-
url: "https://github.com/resend/react-email.git",
|
|
28
|
-
directory: "packages/react-email"
|
|
29
|
-
},
|
|
30
|
-
keywords: [
|
|
31
|
-
"react",
|
|
32
|
-
"email"
|
|
33
|
-
],
|
|
34
|
-
engines: {
|
|
35
|
-
node: ">=18.0.0"
|
|
36
|
-
},
|
|
37
|
-
dependencies: {
|
|
38
|
-
"@babel/parser": "^7.27.0",
|
|
39
|
-
"@babel/traverse": "^7.27.0",
|
|
40
|
-
chalk: "^5.0.0",
|
|
41
|
-
chokidar: "^4.0.3",
|
|
42
|
-
commander: "^13.0.0",
|
|
43
|
-
debounce: "^2.0.0",
|
|
44
|
-
esbuild: "^0.25.0",
|
|
45
|
-
glob: "^11.0.0",
|
|
46
|
-
"log-symbols": "^7.0.0",
|
|
47
|
-
"mime-types": "^3.0.0",
|
|
48
|
-
next: "^15.3.1",
|
|
49
|
-
"normalize-path": "^3.0.0",
|
|
50
|
-
ora: "^8.0.0",
|
|
51
|
-
"socket.io": "^4.8.1",
|
|
52
|
-
"tsconfig-paths": "4.2.0"
|
|
53
|
-
},
|
|
54
|
-
devDependencies: {
|
|
55
|
-
"@babel/core": "7.26.10",
|
|
56
|
-
"@lottiefiles/dotlottie-react": "0.13.3",
|
|
57
|
-
"@radix-ui/colors": "3.0.0",
|
|
58
|
-
"@radix-ui/react-collapsible": "1.1.7",
|
|
59
|
-
"@radix-ui/react-dropdown-menu": "2.1.10",
|
|
60
|
-
"@radix-ui/react-popover": "1.1.10",
|
|
61
|
-
"@radix-ui/react-slot": "1.2.0",
|
|
62
|
-
"@radix-ui/react-tabs": "1.1.7",
|
|
63
|
-
"@radix-ui/react-toggle-group": "1.1.6",
|
|
64
|
-
"@radix-ui/react-tooltip": "1.2.3",
|
|
65
|
-
"@react-email/components": "workspace:*",
|
|
66
|
-
"@swc/core": "1.11.21",
|
|
67
|
-
"@types/babel__core": "7.20.5",
|
|
68
|
-
"@types/babel__traverse": "7.20.7",
|
|
69
|
-
"@types/fs-extra": "11.0.1",
|
|
70
|
-
"@types/mime-types": "2.1.4",
|
|
71
|
-
"@types/node": "22.14.1",
|
|
72
|
-
"@types/normalize-path": "3.0.2",
|
|
73
|
-
"@types/react": "19.0.10",
|
|
74
|
-
"@types/react-dom": "19.0.4",
|
|
75
|
-
"@types/webpack": "5.28.5",
|
|
76
|
-
autoprefixer: "10.4.21",
|
|
77
|
-
clsx: "2.1.1",
|
|
78
|
-
"framer-motion": "12.7.5",
|
|
79
|
-
jiti: "2.4.2",
|
|
80
|
-
json5: "2.2.3",
|
|
81
|
-
"module-punycode": "npm:punycode@2.3.1",
|
|
82
|
-
"node-html-parser": "7.0.1",
|
|
83
|
-
postcss: "8.5.3",
|
|
84
|
-
"pretty-bytes": "6.1.1",
|
|
85
|
-
"prism-react-renderer": "2.4.1",
|
|
86
|
-
react: "19.0.0",
|
|
87
|
-
"react-dom": "19.0.0",
|
|
88
|
-
sharp: "0.34.1",
|
|
89
|
-
"socket.io-client": "4.8.1",
|
|
90
|
-
sonner: "2.0.3",
|
|
91
|
-
"source-map-js": "1.2.1",
|
|
92
|
-
spamc: "0.0.5",
|
|
93
|
-
"stacktrace-parser": "0.1.11",
|
|
94
|
-
"tailwind-merge": "3.2.0",
|
|
95
|
-
tailwindcss: "3.4.0",
|
|
96
|
-
tsup: "8.4.0",
|
|
97
|
-
tsx: "4.19.3",
|
|
98
|
-
typescript: "5.8.3",
|
|
99
|
-
"use-debounce": "10.0.4",
|
|
100
|
-
zod: "3.24.3"
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// src/cli/commands/build.ts
|
|
6
|
+
// src/commands/build.ts
|
|
105
7
|
import { spawn } from "node:child_process";
|
|
106
|
-
import
|
|
107
|
-
import
|
|
108
|
-
import
|
|
109
|
-
import
|
|
8
|
+
import fs2 from "node:fs";
|
|
9
|
+
import path3 from "node:path";
|
|
10
|
+
import logSymbols2 from "log-symbols";
|
|
11
|
+
import ora from "ora";
|
|
110
12
|
|
|
111
13
|
// src/utils/get-emails-directory-metadata.ts
|
|
112
14
|
import fs from "node:fs";
|
|
@@ -194,6 +96,115 @@ var getEmailsDirectoryMetadata = async (absolutePathToEmailsDirectory, keepFileE
|
|
|
194
96
|
return isSubDirectory ? mergeDirectoriesWithSubDirectories(emailsMetadata) : emailsMetadata;
|
|
195
97
|
};
|
|
196
98
|
|
|
99
|
+
// src/utils/get-preview-server-location.ts
|
|
100
|
+
import path2 from "node:path";
|
|
101
|
+
import url from "node:url";
|
|
102
|
+
import { createJiti } from "jiti";
|
|
103
|
+
import { addDevDependency } from "nypm";
|
|
104
|
+
import prompts from "prompts";
|
|
105
|
+
|
|
106
|
+
// package.json
|
|
107
|
+
var package_default = {
|
|
108
|
+
name: "react-email",
|
|
109
|
+
version: "4.1.0-canary.9",
|
|
110
|
+
description: "A live preview of your emails right in your browser.",
|
|
111
|
+
bin: {
|
|
112
|
+
email: "./dist/index.js"
|
|
113
|
+
},
|
|
114
|
+
type: "module",
|
|
115
|
+
scripts: {
|
|
116
|
+
build: "tsup-node",
|
|
117
|
+
clean: "rm -rf dist",
|
|
118
|
+
dev: "tsup-node --watch src",
|
|
119
|
+
test: "vitest run",
|
|
120
|
+
"test:watch": "vitest"
|
|
121
|
+
},
|
|
122
|
+
license: "MIT",
|
|
123
|
+
repository: {
|
|
124
|
+
type: "git",
|
|
125
|
+
url: "https://github.com/resend/react-email.git",
|
|
126
|
+
directory: "packages/react-email"
|
|
127
|
+
},
|
|
128
|
+
keywords: [
|
|
129
|
+
"react",
|
|
130
|
+
"email"
|
|
131
|
+
],
|
|
132
|
+
engines: {
|
|
133
|
+
node: ">=18.0.0"
|
|
134
|
+
},
|
|
135
|
+
dependencies: {
|
|
136
|
+
"@babel/parser": "^7.27.0",
|
|
137
|
+
"@babel/traverse": "^7.27.0",
|
|
138
|
+
chalk: "^5.0.0",
|
|
139
|
+
chokidar: "^4.0.3",
|
|
140
|
+
commander: "^13.0.0",
|
|
141
|
+
debounce: "^2.0.0",
|
|
142
|
+
esbuild: "^0.25.0",
|
|
143
|
+
glob: "^11.0.0",
|
|
144
|
+
jiti: "2.4.2",
|
|
145
|
+
"log-symbols": "^7.0.0",
|
|
146
|
+
"mime-types": "^3.0.0",
|
|
147
|
+
"normalize-path": "^3.0.0",
|
|
148
|
+
nypm: "0.6.0",
|
|
149
|
+
ora: "^8.0.0",
|
|
150
|
+
prompts: "2.4.2",
|
|
151
|
+
"socket.io": "^4.8.1",
|
|
152
|
+
"tsconfig-paths": "4.2.0"
|
|
153
|
+
},
|
|
154
|
+
devDependencies: {
|
|
155
|
+
"@react-email/components": "workspace:*",
|
|
156
|
+
"@types/babel__core": "7.20.5",
|
|
157
|
+
"@types/babel__traverse": "7.20.7",
|
|
158
|
+
"@types/mime-types": "2.1.4",
|
|
159
|
+
"@types/prompts": "2.4.9",
|
|
160
|
+
next: "^15.3.2",
|
|
161
|
+
react: "19.0.0",
|
|
162
|
+
"react-dom": "19.0.0",
|
|
163
|
+
tsup: "8.4.0",
|
|
164
|
+
tsx: "4.19.3",
|
|
165
|
+
typescript: "5.8.3"
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// src/utils/get-preview-server-location.ts
|
|
170
|
+
var ensurePreviewServerInstalled = async (message) => {
|
|
171
|
+
const response = await prompts({
|
|
172
|
+
type: "confirm",
|
|
173
|
+
name: "installPreviewServer",
|
|
174
|
+
message,
|
|
175
|
+
initial: true
|
|
176
|
+
});
|
|
177
|
+
if (response.installPreviewServer) {
|
|
178
|
+
console.log('Installing "@react-email/preview-server"');
|
|
179
|
+
await addDevDependency(
|
|
180
|
+
`@react-email/preview-server@${package_default.version}`
|
|
181
|
+
);
|
|
182
|
+
process.exit(0);
|
|
183
|
+
} else {
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
var getPreviewServerLocation = async () => {
|
|
188
|
+
const usersProject = createJiti(process.cwd());
|
|
189
|
+
let previewServerLocation;
|
|
190
|
+
try {
|
|
191
|
+
previewServerLocation = path2.dirname(
|
|
192
|
+
url.parse(usersProject.esmResolve("@react-email/preview-server"), true).path
|
|
193
|
+
);
|
|
194
|
+
} catch (_exception) {
|
|
195
|
+
await ensurePreviewServerInstalled(
|
|
196
|
+
'To run the preview server, the package "@react-email/preview-server" must be installed. Would you like to install it?'
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
const { version } = await usersProject.import("@react-email/preview-server");
|
|
200
|
+
if (version !== package_default.version) {
|
|
201
|
+
await ensurePreviewServerInstalled(
|
|
202
|
+
`To run the preview server, the version of "@react-email/preview-server" must match the version of "react-email" (${package_default.version}). Would you like to install it?`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
return previewServerLocation;
|
|
206
|
+
};
|
|
207
|
+
|
|
197
208
|
// src/utils/register-spinner-autostopping.ts
|
|
198
209
|
import logSymbols from "log-symbols";
|
|
199
210
|
var spinners = /* @__PURE__ */ new Set();
|
|
@@ -214,58 +225,285 @@ process.on("exit", (code) => {
|
|
|
214
225
|
}
|
|
215
226
|
});
|
|
216
227
|
}
|
|
217
|
-
});
|
|
218
|
-
var registerSpinnerAutostopping = (spinner) => {
|
|
219
|
-
spinners.add(spinner);
|
|
228
|
+
});
|
|
229
|
+
var registerSpinnerAutostopping = (spinner) => {
|
|
230
|
+
spinners.add(spinner);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// src/commands/build.ts
|
|
234
|
+
var buildPreviewApp = (absoluteDirectory) => {
|
|
235
|
+
return new Promise((resolve, reject) => {
|
|
236
|
+
const nextBuild = spawn("npm", ["run", "build"], {
|
|
237
|
+
cwd: absoluteDirectory,
|
|
238
|
+
shell: true
|
|
239
|
+
});
|
|
240
|
+
nextBuild.stdout.pipe(process.stdout);
|
|
241
|
+
nextBuild.stderr.pipe(process.stderr);
|
|
242
|
+
nextBuild.on("close", (code) => {
|
|
243
|
+
if (code === 0) {
|
|
244
|
+
resolve();
|
|
245
|
+
} else {
|
|
246
|
+
reject(
|
|
247
|
+
new Error(
|
|
248
|
+
`Unable to build the Next app and it exited with code: ${code}`
|
|
249
|
+
)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
var npmInstall = async (builtPreviewAppPath, packageManager) => {
|
|
256
|
+
return new Promise((resolve, reject) => {
|
|
257
|
+
const childProc = spawn(
|
|
258
|
+
packageManager,
|
|
259
|
+
[
|
|
260
|
+
"install",
|
|
261
|
+
packageManager === "deno" ? "" : "--include=dev",
|
|
262
|
+
packageManager === "deno" ? "--quiet" : "--silent"
|
|
263
|
+
],
|
|
264
|
+
{
|
|
265
|
+
cwd: builtPreviewAppPath,
|
|
266
|
+
shell: true
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
childProc.stdout.pipe(process.stdout);
|
|
270
|
+
childProc.stderr.pipe(process.stderr);
|
|
271
|
+
childProc.on("close", (code) => {
|
|
272
|
+
if (code === 0) {
|
|
273
|
+
resolve();
|
|
274
|
+
} else {
|
|
275
|
+
reject(
|
|
276
|
+
new Error(
|
|
277
|
+
`Unable to install the dependencies and it exited with code: ${code}`
|
|
278
|
+
)
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
var setNextEnvironmentVariablesForBuild = async (emailsDirRelativePath, builtPreviewAppPath) => {
|
|
285
|
+
const nextConfigContents = `
|
|
286
|
+
const path = require('path');
|
|
287
|
+
const emailsDirRelativePath = path.normalize('${emailsDirRelativePath}');
|
|
288
|
+
const userProjectLocation = '${process.cwd()}';
|
|
289
|
+
/** @type {import('next').NextConfig} */
|
|
290
|
+
module.exports = {
|
|
291
|
+
env: {
|
|
292
|
+
NEXT_PUBLIC_IS_BUILDING: 'true',
|
|
293
|
+
EMAILS_DIR_RELATIVE_PATH: emailsDirRelativePath,
|
|
294
|
+
EMAILS_DIR_ABSOLUTE_PATH: path.resolve(userProjectLocation, emailsDirRelativePath),
|
|
295
|
+
USER_PROJECT_LOCATION: userProjectLocation
|
|
296
|
+
},
|
|
297
|
+
// this is needed so that the code for building emails works properly
|
|
298
|
+
webpack: (
|
|
299
|
+
/** @type {import('webpack').Configuration & { externals: string[] }} */
|
|
300
|
+
config,
|
|
301
|
+
{ isServer }
|
|
302
|
+
) => {
|
|
303
|
+
if (isServer) {
|
|
304
|
+
config.externals.push('esbuild');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return config;
|
|
308
|
+
},
|
|
309
|
+
typescript: {
|
|
310
|
+
ignoreBuildErrors: true
|
|
311
|
+
},
|
|
312
|
+
eslint: {
|
|
313
|
+
ignoreDuringBuilds: true
|
|
314
|
+
},
|
|
315
|
+
experimental: {
|
|
316
|
+
webpackBuildWorker: true
|
|
317
|
+
},
|
|
318
|
+
}`;
|
|
319
|
+
await fs2.promises.writeFile(
|
|
320
|
+
path3.resolve(builtPreviewAppPath, "./next.config.js"),
|
|
321
|
+
nextConfigContents,
|
|
322
|
+
"utf8"
|
|
323
|
+
);
|
|
324
|
+
};
|
|
325
|
+
var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePath) => {
|
|
326
|
+
const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
|
|
327
|
+
const slugs = [];
|
|
328
|
+
emailDirectory.emailFilenames.forEach(
|
|
329
|
+
(filename3) => slugs.push(
|
|
330
|
+
path3.join(directoryPathRelativeToEmailsDirectory, filename3).split(path3.sep).filter((segment) => segment.length > 0)
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
emailDirectory.subDirectories.forEach((directory) => {
|
|
334
|
+
slugs.push(
|
|
335
|
+
...getEmailSlugsFromEmailDirectory(
|
|
336
|
+
directory,
|
|
337
|
+
emailsDirectoryAbsolutePath
|
|
338
|
+
)
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
return slugs;
|
|
342
|
+
};
|
|
343
|
+
var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
|
|
344
|
+
const emailDirectoryMetadata = (
|
|
345
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
346
|
+
await getEmailsDirectoryMetadata(emailsDirPath)
|
|
347
|
+
);
|
|
348
|
+
const parameters = getEmailSlugsFromEmailDirectory(
|
|
349
|
+
emailDirectoryMetadata,
|
|
350
|
+
emailsDirPath
|
|
351
|
+
).map((slug) => ({ slug }));
|
|
352
|
+
const removeForceDynamic = async (filePath) => {
|
|
353
|
+
const contents = await fs2.promises.readFile(filePath, "utf8");
|
|
354
|
+
await fs2.promises.writeFile(
|
|
355
|
+
filePath,
|
|
356
|
+
contents.replace("export const dynamic = 'force-dynamic';", ""),
|
|
357
|
+
"utf8"
|
|
358
|
+
);
|
|
359
|
+
};
|
|
360
|
+
await removeForceDynamic(
|
|
361
|
+
path3.resolve(builtPreviewAppPath, "./src/app/layout.tsx")
|
|
362
|
+
);
|
|
363
|
+
await removeForceDynamic(
|
|
364
|
+
path3.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx")
|
|
365
|
+
);
|
|
366
|
+
await fs2.promises.appendFile(
|
|
367
|
+
path3.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
|
|
368
|
+
`
|
|
369
|
+
|
|
370
|
+
export function generateStaticParams() {
|
|
371
|
+
return Promise.resolve(
|
|
372
|
+
${JSON.stringify(parameters)}
|
|
373
|
+
);
|
|
374
|
+
}`,
|
|
375
|
+
"utf8"
|
|
376
|
+
);
|
|
377
|
+
};
|
|
378
|
+
var updatePackageJson = async (builtPreviewAppPath) => {
|
|
379
|
+
const packageJsonPath = path3.resolve(builtPreviewAppPath, "./package.json");
|
|
380
|
+
const packageJson = JSON.parse(
|
|
381
|
+
await fs2.promises.readFile(packageJsonPath, "utf8")
|
|
382
|
+
);
|
|
383
|
+
packageJson.scripts.build = "next build";
|
|
384
|
+
packageJson.scripts.start = "next start";
|
|
385
|
+
delete packageJson.scripts.postbuild;
|
|
386
|
+
packageJson.name = "preview-server";
|
|
387
|
+
delete packageJson.devDependencies["@react-email/render"];
|
|
388
|
+
delete packageJson.devDependencies["@react-email/components"];
|
|
389
|
+
delete packageJson.scripts.prepare;
|
|
390
|
+
await fs2.promises.writeFile(
|
|
391
|
+
packageJsonPath,
|
|
392
|
+
JSON.stringify(packageJson),
|
|
393
|
+
"utf8"
|
|
394
|
+
);
|
|
395
|
+
};
|
|
396
|
+
var build = async ({
|
|
397
|
+
dir: emailsDirRelativePath,
|
|
398
|
+
packageManager
|
|
399
|
+
}) => {
|
|
400
|
+
try {
|
|
401
|
+
const previewServerLocation = await getPreviewServerLocation();
|
|
402
|
+
const spinner = ora({
|
|
403
|
+
text: "Starting build process...",
|
|
404
|
+
prefixText: " "
|
|
405
|
+
}).start();
|
|
406
|
+
registerSpinnerAutostopping(spinner);
|
|
407
|
+
spinner.text = `Checking if ${emailsDirRelativePath} folder exists`;
|
|
408
|
+
if (!fs2.existsSync(emailsDirRelativePath)) {
|
|
409
|
+
process.exit(1);
|
|
410
|
+
}
|
|
411
|
+
const emailsDirPath = path3.join(process.cwd(), emailsDirRelativePath);
|
|
412
|
+
const staticPath = path3.join(emailsDirPath, "static");
|
|
413
|
+
const builtPreviewAppPath = path3.join(process.cwd(), ".react-email");
|
|
414
|
+
if (fs2.existsSync(builtPreviewAppPath)) {
|
|
415
|
+
spinner.text = "Deleting pre-existing `.react-email` folder";
|
|
416
|
+
await fs2.promises.rm(builtPreviewAppPath, { recursive: true });
|
|
417
|
+
}
|
|
418
|
+
spinner.text = "Copying preview app from CLI to `.react-email`";
|
|
419
|
+
await fs2.promises.cp(previewServerLocation, builtPreviewAppPath, {
|
|
420
|
+
recursive: true,
|
|
421
|
+
filter: (source) => {
|
|
422
|
+
return !/(\/|\\)cli(\/|\\)?/.test(source) && !/(\/|\\)\.next(\/|\\)?/.test(source) && !/(\/|\\)\.turbo(\/|\\)?/.test(source) && !/(\/|\\)node_modules(\/|\\)?$/.test(source);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
if (fs2.existsSync(staticPath)) {
|
|
426
|
+
spinner.text = "Copying `static` folder into `.react-email/public/static`";
|
|
427
|
+
const builtStaticDirectory = path3.resolve(
|
|
428
|
+
builtPreviewAppPath,
|
|
429
|
+
"./public/static"
|
|
430
|
+
);
|
|
431
|
+
await fs2.promises.cp(staticPath, builtStaticDirectory, {
|
|
432
|
+
recursive: true
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
spinner.text = "Setting Next environment variables for preview app to work properly";
|
|
436
|
+
await setNextEnvironmentVariablesForBuild(
|
|
437
|
+
emailsDirRelativePath,
|
|
438
|
+
builtPreviewAppPath
|
|
439
|
+
);
|
|
440
|
+
spinner.text = "Setting server side generation for the email preview pages";
|
|
441
|
+
await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
|
|
442
|
+
spinner.text = "Updating package.json's build and start scripts";
|
|
443
|
+
await updatePackageJson(builtPreviewAppPath);
|
|
444
|
+
spinner.text = "Installing dependencies on `.react-email`";
|
|
445
|
+
await npmInstall(builtPreviewAppPath, packageManager);
|
|
446
|
+
spinner.stopAndPersist({
|
|
447
|
+
text: "Successfully prepared `.react-email` for `next build`",
|
|
448
|
+
symbol: logSymbols2.success
|
|
449
|
+
});
|
|
450
|
+
await buildPreviewApp(builtPreviewAppPath);
|
|
451
|
+
} catch (error) {
|
|
452
|
+
console.log(error);
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
220
455
|
};
|
|
221
456
|
|
|
222
|
-
// src/
|
|
223
|
-
import
|
|
457
|
+
// src/commands/dev.ts
|
|
458
|
+
import fs6 from "node:fs";
|
|
459
|
+
|
|
460
|
+
// src/utils/preview/hot-reloading/setup-hot-reloading.ts
|
|
461
|
+
import path9 from "node:path";
|
|
224
462
|
import { watch } from "chokidar";
|
|
225
463
|
import debounce from "debounce";
|
|
226
464
|
import { Server as SocketServer } from "socket.io";
|
|
227
465
|
|
|
228
|
-
// src/
|
|
229
|
-
import { existsSync as existsSync2, promises as
|
|
230
|
-
import
|
|
466
|
+
// src/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
467
|
+
import { existsSync as existsSync2, promises as fs4, statSync } from "node:fs";
|
|
468
|
+
import path8 from "node:path";
|
|
231
469
|
|
|
232
|
-
// src/
|
|
470
|
+
// src/utils/preview/start-dev-server.ts
|
|
233
471
|
import http from "node:http";
|
|
234
|
-
import
|
|
235
|
-
import
|
|
472
|
+
import path6 from "node:path";
|
|
473
|
+
import url2 from "node:url";
|
|
236
474
|
import chalk from "chalk";
|
|
237
|
-
import
|
|
238
|
-
import
|
|
239
|
-
import
|
|
475
|
+
import { createJiti as createJiti2 } from "jiti";
|
|
476
|
+
import logSymbols3 from "log-symbols";
|
|
477
|
+
import ora2 from "ora";
|
|
240
478
|
|
|
241
|
-
// src/
|
|
242
|
-
import
|
|
479
|
+
// src/utils/preview/get-env-variables-for-preview-app.ts
|
|
480
|
+
import path4 from "node:path";
|
|
243
481
|
var getEnvVariablesForPreviewApp = (relativePathToEmailsDirectory, cwd) => {
|
|
244
482
|
return {
|
|
245
483
|
EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
|
|
246
|
-
EMAILS_DIR_ABSOLUTE_PATH:
|
|
484
|
+
EMAILS_DIR_ABSOLUTE_PATH: path4.resolve(cwd, relativePathToEmailsDirectory),
|
|
247
485
|
USER_PROJECT_LOCATION: cwd,
|
|
248
486
|
NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT: isDev ? "true" : "false"
|
|
249
487
|
};
|
|
250
488
|
};
|
|
251
489
|
|
|
252
|
-
// src/
|
|
253
|
-
import { existsSync, promises as
|
|
254
|
-
import
|
|
490
|
+
// src/utils/preview/serve-static-file.ts
|
|
491
|
+
import { existsSync, promises as fs3 } from "node:fs";
|
|
492
|
+
import path5 from "node:path";
|
|
255
493
|
import { lookup } from "mime-types";
|
|
256
494
|
var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
|
|
257
495
|
const pathname = parsedUrl.pathname.replace("/static", "./static");
|
|
258
|
-
const ext =
|
|
259
|
-
const staticBaseDir =
|
|
260
|
-
const fileAbsolutePath =
|
|
496
|
+
const ext = path5.parse(pathname).ext;
|
|
497
|
+
const staticBaseDir = path5.resolve(process.cwd(), staticDirRelativePath);
|
|
498
|
+
const fileAbsolutePath = path5.resolve(staticBaseDir, pathname);
|
|
261
499
|
if (!fileAbsolutePath.startsWith(staticBaseDir)) {
|
|
262
500
|
res.statusCode = 403;
|
|
263
501
|
res.end();
|
|
264
502
|
return;
|
|
265
503
|
}
|
|
266
504
|
try {
|
|
267
|
-
const fileHandle = await
|
|
268
|
-
const fileData = await
|
|
505
|
+
const fileHandle = await fs3.open(fileAbsolutePath, "r");
|
|
506
|
+
const fileData = await fs3.readFile(fileHandle);
|
|
269
507
|
res.setHeader("Content-type", lookup(ext) || "text/plain");
|
|
270
508
|
res.end(fileData);
|
|
271
509
|
fileHandle.close();
|
|
@@ -287,7 +525,7 @@ var serveStaticFile = async (res, parsedUrl, staticDirRelativePath) => {
|
|
|
287
525
|
}
|
|
288
526
|
};
|
|
289
527
|
|
|
290
|
-
// src/
|
|
528
|
+
// src/utils/preview/start-dev-server.ts
|
|
291
529
|
var devServer;
|
|
292
530
|
var safeAsyncServerListen = (server, port) => {
|
|
293
531
|
return new Promise((resolve) => {
|
|
@@ -301,25 +539,26 @@ var safeAsyncServerListen = (server, port) => {
|
|
|
301
539
|
});
|
|
302
540
|
});
|
|
303
541
|
};
|
|
304
|
-
var filename =
|
|
305
|
-
var dirname =
|
|
306
|
-
var isDev = !
|
|
307
|
-
var cliPackageLocation = isDev ? path4.resolve(dirname, "../../../..") : path4.resolve(dirname, "../..");
|
|
308
|
-
var previewServerLocation = isDev ? path4.resolve(dirname, "../../../..") : path4.resolve(dirname, "../preview");
|
|
542
|
+
var filename = url2.fileURLToPath(import.meta.url);
|
|
543
|
+
var dirname = path6.dirname(filename);
|
|
544
|
+
var isDev = !dirname.includes("dist");
|
|
309
545
|
var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, port) => {
|
|
310
546
|
const [majorNodeVersion] = process.versions.node.split(".");
|
|
311
547
|
if (majorNodeVersion && Number.parseInt(majorNodeVersion) < 18) {
|
|
312
548
|
console.error(
|
|
313
|
-
` ${
|
|
549
|
+
` ${logSymbols3.error} Node ${majorNodeVersion} is not supported. Please upgrade to Node 18 or higher.`
|
|
314
550
|
);
|
|
315
551
|
process.exit(1);
|
|
316
552
|
}
|
|
553
|
+
const previewServerLocation = await getPreviewServerLocation();
|
|
554
|
+
const previewServer = createJiti2(previewServerLocation);
|
|
555
|
+
const { default: next } = await previewServer.import("next");
|
|
317
556
|
devServer = http.createServer((req, res) => {
|
|
318
557
|
if (!req.url) {
|
|
319
558
|
res.end(404);
|
|
320
559
|
return;
|
|
321
560
|
}
|
|
322
|
-
const parsedUrl =
|
|
561
|
+
const parsedUrl = url2.parse(req.url, true);
|
|
323
562
|
res.setHeader(
|
|
324
563
|
"Cache-Control",
|
|
325
564
|
"no-cache, max-age=0, must-revalidate, no-store"
|
|
@@ -350,7 +589,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
350
589
|
} else {
|
|
351
590
|
const nextPortToTry = port + 1;
|
|
352
591
|
console.warn(
|
|
353
|
-
` ${
|
|
592
|
+
` ${logSymbols3.warning} Port ${port} is already in use, trying ${nextPortToTry}`
|
|
354
593
|
);
|
|
355
594
|
return startDevServer(
|
|
356
595
|
emailsDirRelativePath,
|
|
@@ -363,12 +602,12 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
363
602
|
});
|
|
364
603
|
devServer.on("error", (e) => {
|
|
365
604
|
spinner.stopAndPersist({
|
|
366
|
-
symbol:
|
|
605
|
+
symbol: logSymbols3.error,
|
|
367
606
|
text: `Preview Server had an error: ${e}`
|
|
368
607
|
});
|
|
369
608
|
process.exit(1);
|
|
370
609
|
});
|
|
371
|
-
const spinner =
|
|
610
|
+
const spinner = ora2({
|
|
372
611
|
text: "Getting react-email preview server ready...\n",
|
|
373
612
|
prefixText: " "
|
|
374
613
|
}).start();
|
|
@@ -379,7 +618,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
379
618
|
...process.env,
|
|
380
619
|
...getEnvVariablesForPreviewApp(
|
|
381
620
|
// If we don't do normalization here, stuff like https://github.com/resend/react-email/issues/1354 happens.
|
|
382
|
-
|
|
621
|
+
path6.normalize(emailsDirRelativePath),
|
|
383
622
|
process.cwd()
|
|
384
623
|
)
|
|
385
624
|
};
|
|
@@ -402,7 +641,7 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
402
641
|
await nextReadyPromise;
|
|
403
642
|
} catch (exception) {
|
|
404
643
|
spinner.stopAndPersist({
|
|
405
|
-
symbol:
|
|
644
|
+
symbol: logSymbols3.error,
|
|
406
645
|
text: ` Preview Server had an error: ${exception}`
|
|
407
646
|
});
|
|
408
647
|
process.exit(1);
|
|
@@ -413,16 +652,19 @@ var startDevServer = async (emailsDirRelativePath, staticBaseDirRelativePath, po
|
|
|
413
652
|
spinner.stopAndPersist({
|
|
414
653
|
text: `Ready in ${secondsToNextReady}s
|
|
415
654
|
`,
|
|
416
|
-
symbol:
|
|
655
|
+
symbol: logSymbols3.success
|
|
417
656
|
});
|
|
418
657
|
return devServer;
|
|
419
658
|
};
|
|
420
|
-
var makeExitHandler = (options) => (
|
|
659
|
+
var makeExitHandler = (options) => (codeSignalOrError) => {
|
|
421
660
|
if (typeof devServer !== "undefined") {
|
|
422
|
-
console.log("\
|
|
661
|
+
console.log("\nshutting down dev server");
|
|
423
662
|
devServer.close();
|
|
424
663
|
devServer = void 0;
|
|
425
664
|
}
|
|
665
|
+
if (codeSignalOrError instanceof Error) {
|
|
666
|
+
console.error(codeSignalOrError);
|
|
667
|
+
}
|
|
426
668
|
if (options?.shouldKillProcess) {
|
|
427
669
|
process.exit(options.killWithErrorCode ? 1 : 0);
|
|
428
670
|
}
|
|
@@ -445,10 +687,14 @@ process.on(
|
|
|
445
687
|
makeExitHandler({ shouldKillProcess: true, killWithErrorCode: true })
|
|
446
688
|
);
|
|
447
689
|
|
|
448
|
-
// src/
|
|
690
|
+
// src/utils/preview/hot-reloading/get-imported-modules.ts
|
|
449
691
|
import { parse } from "@babel/parser";
|
|
450
692
|
import traverseModule from "@babel/traverse";
|
|
451
|
-
var traverse =
|
|
693
|
+
var traverse = (
|
|
694
|
+
// we keep this check here so that this still works with the dev:preview
|
|
695
|
+
// script's use of tsx
|
|
696
|
+
typeof traverseModule === "function" ? traverseModule : traverseModule.default
|
|
697
|
+
);
|
|
452
698
|
var getImportedModules = (contents) => {
|
|
453
699
|
const importedPaths = [];
|
|
454
700
|
const parsedContents = parse(contents, {
|
|
@@ -486,8 +732,8 @@ var getImportedModules = (contents) => {
|
|
|
486
732
|
return importedPaths;
|
|
487
733
|
};
|
|
488
734
|
|
|
489
|
-
// src/
|
|
490
|
-
import
|
|
735
|
+
// src/utils/preview/hot-reloading/resolve-path-aliases.ts
|
|
736
|
+
import path7 from "node:path";
|
|
491
737
|
import { createMatchPath, loadConfig } from "tsconfig-paths";
|
|
492
738
|
var resolvePathAliases = (importPaths, projectPath) => {
|
|
493
739
|
const configLoadResult = loadConfig(projectPath);
|
|
@@ -506,7 +752,7 @@ var resolvePathAliases = (importPaths, projectPath) => {
|
|
|
506
752
|
".mjs"
|
|
507
753
|
]);
|
|
508
754
|
if (unaliasedPath) {
|
|
509
|
-
return `./${
|
|
755
|
+
return `./${path7.relative(projectPath, unaliasedPath)}`;
|
|
510
756
|
}
|
|
511
757
|
return importedPath;
|
|
512
758
|
});
|
|
@@ -514,12 +760,12 @@ var resolvePathAliases = (importPaths, projectPath) => {
|
|
|
514
760
|
return importPaths;
|
|
515
761
|
};
|
|
516
762
|
|
|
517
|
-
// src/
|
|
763
|
+
// src/utils/preview/hot-reloading/create-dependency-graph.ts
|
|
518
764
|
var readAllFilesInsideDirectory = async (directory) => {
|
|
519
765
|
let allFilePaths = [];
|
|
520
|
-
const topLevelDirents = await
|
|
766
|
+
const topLevelDirents = await fs4.readdir(directory, { withFileTypes: true });
|
|
521
767
|
for await (const dirent of topLevelDirents) {
|
|
522
|
-
const pathToDirent =
|
|
768
|
+
const pathToDirent = path8.join(directory, dirent.name);
|
|
523
769
|
if (dirent.isDirectory()) {
|
|
524
770
|
allFilePaths = allFilePaths.concat(
|
|
525
771
|
await readAllFilesInsideDirectory(pathToDirent)
|
|
@@ -531,7 +777,7 @@ var readAllFilesInsideDirectory = async (directory) => {
|
|
|
531
777
|
return allFilePaths;
|
|
532
778
|
};
|
|
533
779
|
var isJavascriptModule = (filePath) => {
|
|
534
|
-
const extensionName =
|
|
780
|
+
const extensionName = path8.extname(filePath);
|
|
535
781
|
return [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"].includes(extensionName);
|
|
536
782
|
};
|
|
537
783
|
var checkFileExtensionsUntilItExists = (pathWithoutExtension) => {
|
|
@@ -558,10 +804,10 @@ var createDependencyGraph = async (directory) => {
|
|
|
558
804
|
const filePaths = await readAllFilesInsideDirectory(directory);
|
|
559
805
|
const modulePaths = filePaths.filter(isJavascriptModule);
|
|
560
806
|
const graph = Object.fromEntries(
|
|
561
|
-
modulePaths.map((
|
|
562
|
-
|
|
807
|
+
modulePaths.map((path14) => [
|
|
808
|
+
path14,
|
|
563
809
|
{
|
|
564
|
-
path:
|
|
810
|
+
path: path14,
|
|
565
811
|
dependencyPaths: [],
|
|
566
812
|
dependentPaths: [],
|
|
567
813
|
moduleDependencies: []
|
|
@@ -569,15 +815,15 @@ var createDependencyGraph = async (directory) => {
|
|
|
569
815
|
])
|
|
570
816
|
);
|
|
571
817
|
const getDependencyPaths = async (filePath) => {
|
|
572
|
-
const contents = await
|
|
573
|
-
const importedPaths = isJavascriptModule(filePath) ? resolvePathAliases(getImportedModules(contents),
|
|
818
|
+
const contents = await fs4.readFile(filePath, "utf8");
|
|
819
|
+
const importedPaths = isJavascriptModule(filePath) ? resolvePathAliases(getImportedModules(contents), path8.dirname(filePath)) : [];
|
|
574
820
|
const importedPathsRelativeToDirectory = importedPaths.map(
|
|
575
821
|
(dependencyPath) => {
|
|
576
822
|
const isModulePath = !dependencyPath.startsWith(".");
|
|
577
|
-
if (isModulePath ||
|
|
823
|
+
if (isModulePath || path8.isAbsolute(dependencyPath)) {
|
|
578
824
|
return dependencyPath;
|
|
579
825
|
}
|
|
580
|
-
let pathToDependencyFromDirectory =
|
|
826
|
+
let pathToDependencyFromDirectory = path8.resolve(
|
|
581
827
|
/*
|
|
582
828
|
path.resolve resolves paths differently from what imports on javascript do.
|
|
583
829
|
|
|
@@ -585,7 +831,7 @@ var createDependencyGraph = async (directory) => {
|
|
|
585
831
|
would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
|
|
586
832
|
one the import is meant to go to
|
|
587
833
|
*/
|
|
588
|
-
|
|
834
|
+
path8.dirname(filePath),
|
|
589
835
|
dependencyPath
|
|
590
836
|
);
|
|
591
837
|
let isDirectory = false;
|
|
@@ -606,7 +852,7 @@ var createDependencyGraph = async (directory) => {
|
|
|
606
852
|
);
|
|
607
853
|
}
|
|
608
854
|
}
|
|
609
|
-
const extension =
|
|
855
|
+
const extension = path8.extname(pathToDependencyFromDirectory);
|
|
610
856
|
const pathWithEnsuredExtension = (() => {
|
|
611
857
|
if (extension.length > 0 && existsSync2(pathToDependencyFromDirectory)) {
|
|
612
858
|
return pathToDependencyFromDirectory;
|
|
@@ -626,10 +872,10 @@ var createDependencyGraph = async (directory) => {
|
|
|
626
872
|
}
|
|
627
873
|
);
|
|
628
874
|
const moduleDependencies = importedPathsRelativeToDirectory.filter(
|
|
629
|
-
(dependencyPath) => !dependencyPath.startsWith(".") && !
|
|
875
|
+
(dependencyPath) => !dependencyPath.startsWith(".") && !path8.isAbsolute(dependencyPath)
|
|
630
876
|
);
|
|
631
877
|
const nonNodeModuleImportPathsRelativeToDirectory = importedPathsRelativeToDirectory.filter(
|
|
632
|
-
(dependencyPath) => dependencyPath.startsWith(".") ||
|
|
878
|
+
(dependencyPath) => dependencyPath.startsWith(".") || path8.isAbsolute(dependencyPath)
|
|
633
879
|
);
|
|
634
880
|
return {
|
|
635
881
|
dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
|
|
@@ -742,7 +988,7 @@ var createDependencyGraph = async (directory) => {
|
|
|
742
988
|
];
|
|
743
989
|
};
|
|
744
990
|
|
|
745
|
-
// src/
|
|
991
|
+
// src/utils/preview/hot-reloading/setup-hot-reloading.ts
|
|
746
992
|
var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
747
993
|
let clients = [];
|
|
748
994
|
const io = new SocketServer(devServer2);
|
|
@@ -760,14 +1006,14 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
760
1006
|
changes.filter(
|
|
761
1007
|
(change) => (
|
|
762
1008
|
// Ensures only changes inside the emails directory are emitted
|
|
763
|
-
|
|
1009
|
+
path9.resolve(absolutePathToEmailsDirectory, change.filename).startsWith(absolutePathToEmailsDirectory)
|
|
764
1010
|
)
|
|
765
1011
|
)
|
|
766
1012
|
);
|
|
767
1013
|
});
|
|
768
1014
|
changes = [];
|
|
769
1015
|
}, 150);
|
|
770
|
-
const absolutePathToEmailsDirectory =
|
|
1016
|
+
const absolutePathToEmailsDirectory = path9.resolve(
|
|
771
1017
|
process.cwd(),
|
|
772
1018
|
emailDirRelativePath
|
|
773
1019
|
);
|
|
@@ -777,7 +1023,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
777
1023
|
cwd: absolutePathToEmailsDirectory
|
|
778
1024
|
});
|
|
779
1025
|
const getFilesOutsideEmailsDirectory = () => Object.keys(dependencyGraph).filter(
|
|
780
|
-
(p) =>
|
|
1026
|
+
(p) => path9.relative(absolutePathToEmailsDirectory, p).startsWith("..")
|
|
781
1027
|
);
|
|
782
1028
|
let filesOutsideEmailsDirectory = getFilesOutsideEmailsDirectory();
|
|
783
1029
|
for (const p of filesOutsideEmailsDirectory) {
|
|
@@ -789,11 +1035,11 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
789
1035
|
process.on("SIGINT", exit);
|
|
790
1036
|
process.on("uncaughtException", exit);
|
|
791
1037
|
watcher.on("all", async (event, relativePathToChangeTarget) => {
|
|
792
|
-
const file = relativePathToChangeTarget.split(
|
|
1038
|
+
const file = relativePathToChangeTarget.split(path9.sep);
|
|
793
1039
|
if (file.length === 0) {
|
|
794
1040
|
return;
|
|
795
1041
|
}
|
|
796
|
-
const pathToChangeTarget =
|
|
1042
|
+
const pathToChangeTarget = path9.resolve(
|
|
797
1043
|
absolutePathToEmailsDirectory,
|
|
798
1044
|
relativePathToChangeTarget
|
|
799
1045
|
);
|
|
@@ -817,7 +1063,7 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
817
1063
|
for (const dependentPath of resolveDependentsOf(pathToChangeTarget)) {
|
|
818
1064
|
changes.push({
|
|
819
1065
|
event: "change",
|
|
820
|
-
filename:
|
|
1066
|
+
filename: path9.relative(absolutePathToEmailsDirectory, dependentPath)
|
|
821
1067
|
});
|
|
822
1068
|
}
|
|
823
1069
|
reload();
|
|
@@ -825,10 +1071,10 @@ var setupHotreloading = async (devServer2, emailDirRelativePath) => {
|
|
|
825
1071
|
return watcher;
|
|
826
1072
|
};
|
|
827
1073
|
|
|
828
|
-
// src/
|
|
829
|
-
import { promises as
|
|
1074
|
+
// src/utils/tree.ts
|
|
1075
|
+
import { promises as fs5 } from "node:fs";
|
|
830
1076
|
import os from "node:os";
|
|
831
|
-
import
|
|
1077
|
+
import path10 from "node:path";
|
|
832
1078
|
var SYMBOLS = {
|
|
833
1079
|
BRANCH: "\u251C\u2500\u2500 ",
|
|
834
1080
|
EMPTY: "",
|
|
@@ -838,12 +1084,12 @@ var SYMBOLS = {
|
|
|
838
1084
|
};
|
|
839
1085
|
var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
|
|
840
1086
|
const base = process.cwd();
|
|
841
|
-
const dirFullpath =
|
|
842
|
-
const dirname2 =
|
|
1087
|
+
const dirFullpath = path10.resolve(base, dirPath);
|
|
1088
|
+
const dirname2 = path10.basename(dirFullpath);
|
|
843
1089
|
let lines = [dirname2];
|
|
844
|
-
const dirStat = await
|
|
1090
|
+
const dirStat = await fs5.stat(dirFullpath);
|
|
845
1091
|
if (dirStat.isDirectory() && currentDepth < depth) {
|
|
846
|
-
const childDirents = await
|
|
1092
|
+
const childDirents = await fs5.readdir(dirFullpath, { withFileTypes: true });
|
|
847
1093
|
childDirents.sort((a, b) => {
|
|
848
1094
|
if (a.isDirectory() && b.isFile()) {
|
|
849
1095
|
return -1;
|
|
@@ -861,7 +1107,7 @@ var getTreeLines = async (dirPath, depth, currentDepth = 0) => {
|
|
|
861
1107
|
if (dirent.isFile()) {
|
|
862
1108
|
lines.push(`${branchingSymbol}${dirent.name}`);
|
|
863
1109
|
} else {
|
|
864
|
-
const pathToDirectory =
|
|
1110
|
+
const pathToDirectory = path10.join(dirFullpath, dirent.name);
|
|
865
1111
|
const treeLinesForSubDirectory = await getTreeLines(
|
|
866
1112
|
pathToDirectory,
|
|
867
1113
|
depth,
|
|
@@ -882,231 +1128,7 @@ var tree = async (dirPath, depth) => {
|
|
|
882
1128
|
return lines.join(os.EOL);
|
|
883
1129
|
};
|
|
884
1130
|
|
|
885
|
-
// src/
|
|
886
|
-
var buildPreviewApp = (absoluteDirectory) => {
|
|
887
|
-
return new Promise((resolve, reject) => {
|
|
888
|
-
const nextBuild = spawn("npm", ["run", "build"], {
|
|
889
|
-
cwd: absoluteDirectory,
|
|
890
|
-
shell: true
|
|
891
|
-
});
|
|
892
|
-
nextBuild.stdout.pipe(process.stdout);
|
|
893
|
-
nextBuild.stderr.pipe(process.stderr);
|
|
894
|
-
nextBuild.on("close", (code) => {
|
|
895
|
-
if (code === 0) {
|
|
896
|
-
resolve();
|
|
897
|
-
} else {
|
|
898
|
-
reject(
|
|
899
|
-
new Error(
|
|
900
|
-
`Unable to build the Next app and it exited with code: ${code}`
|
|
901
|
-
)
|
|
902
|
-
);
|
|
903
|
-
}
|
|
904
|
-
});
|
|
905
|
-
});
|
|
906
|
-
};
|
|
907
|
-
var setNextEnvironmentVariablesForBuild = async (emailsDirRelativePath, builtPreviewAppPath) => {
|
|
908
|
-
const nextConfigContents = `
|
|
909
|
-
const path = require('path');
|
|
910
|
-
const emailsDirRelativePath = path.normalize('${emailsDirRelativePath}');
|
|
911
|
-
const userProjectLocation = path.resolve(process.cwd(), '../');
|
|
912
|
-
/** @type {import('next').NextConfig} */
|
|
913
|
-
module.exports = {
|
|
914
|
-
env: {
|
|
915
|
-
NEXT_PUBLIC_IS_BUILDING: 'true',
|
|
916
|
-
EMAILS_DIR_RELATIVE_PATH: emailsDirRelativePath,
|
|
917
|
-
EMAILS_DIR_ABSOLUTE_PATH: path.resolve(userProjectLocation, emailsDirRelativePath),
|
|
918
|
-
USER_PROJECT_LOCATION: userProjectLocation
|
|
919
|
-
},
|
|
920
|
-
// this is needed so that the code for building emails works properly
|
|
921
|
-
webpack: (
|
|
922
|
-
/** @type {import('webpack').Configuration & { externals: string[] }} */
|
|
923
|
-
config,
|
|
924
|
-
{ isServer }
|
|
925
|
-
) => {
|
|
926
|
-
if (isServer) {
|
|
927
|
-
config.externals.push('esbuild');
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
return config;
|
|
931
|
-
},
|
|
932
|
-
typescript: {
|
|
933
|
-
ignoreBuildErrors: true
|
|
934
|
-
},
|
|
935
|
-
eslint: {
|
|
936
|
-
ignoreDuringBuilds: true
|
|
937
|
-
},
|
|
938
|
-
experimental: {
|
|
939
|
-
webpackBuildWorker: true
|
|
940
|
-
},
|
|
941
|
-
}`;
|
|
942
|
-
await fs5.promises.writeFile(
|
|
943
|
-
path9.resolve(builtPreviewAppPath, "./next.config.js"),
|
|
944
|
-
nextConfigContents,
|
|
945
|
-
"utf8"
|
|
946
|
-
);
|
|
947
|
-
};
|
|
948
|
-
var getEmailSlugsFromEmailDirectory = (emailDirectory, emailsDirectoryAbsolutePath) => {
|
|
949
|
-
const directoryPathRelativeToEmailsDirectory = emailDirectory.absolutePath.replace(emailsDirectoryAbsolutePath, "").trim();
|
|
950
|
-
const slugs = [];
|
|
951
|
-
emailDirectory.emailFilenames.forEach(
|
|
952
|
-
(filename3) => slugs.push(
|
|
953
|
-
path9.join(directoryPathRelativeToEmailsDirectory, filename3).split(path9.sep).filter((segment) => segment.length > 0)
|
|
954
|
-
)
|
|
955
|
-
);
|
|
956
|
-
emailDirectory.subDirectories.forEach((directory) => {
|
|
957
|
-
slugs.push(
|
|
958
|
-
...getEmailSlugsFromEmailDirectory(
|
|
959
|
-
directory,
|
|
960
|
-
emailsDirectoryAbsolutePath
|
|
961
|
-
)
|
|
962
|
-
);
|
|
963
|
-
});
|
|
964
|
-
return slugs;
|
|
965
|
-
};
|
|
966
|
-
var forceSSGForEmailPreviews = async (emailsDirPath, builtPreviewAppPath) => {
|
|
967
|
-
const emailDirectoryMetadata = (
|
|
968
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
969
|
-
await getEmailsDirectoryMetadata(emailsDirPath)
|
|
970
|
-
);
|
|
971
|
-
const parameters = getEmailSlugsFromEmailDirectory(
|
|
972
|
-
emailDirectoryMetadata,
|
|
973
|
-
emailsDirPath
|
|
974
|
-
).map((slug) => ({ slug }));
|
|
975
|
-
const removeForceDynamic = async (filePath) => {
|
|
976
|
-
const contents = await fs5.promises.readFile(filePath, "utf8");
|
|
977
|
-
await fs5.promises.writeFile(
|
|
978
|
-
filePath,
|
|
979
|
-
contents.replace("export const dynamic = 'force-dynamic';", ""),
|
|
980
|
-
"utf8"
|
|
981
|
-
);
|
|
982
|
-
};
|
|
983
|
-
await removeForceDynamic(
|
|
984
|
-
path9.resolve(builtPreviewAppPath, "./src/app/layout.tsx")
|
|
985
|
-
);
|
|
986
|
-
await removeForceDynamic(
|
|
987
|
-
path9.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx")
|
|
988
|
-
);
|
|
989
|
-
await fs5.promises.appendFile(
|
|
990
|
-
path9.resolve(builtPreviewAppPath, "./src/app/preview/[...slug]/page.tsx"),
|
|
991
|
-
`
|
|
992
|
-
|
|
993
|
-
export function generateStaticParams() {
|
|
994
|
-
return Promise.resolve(
|
|
995
|
-
${JSON.stringify(parameters)}
|
|
996
|
-
);
|
|
997
|
-
}`,
|
|
998
|
-
"utf8"
|
|
999
|
-
);
|
|
1000
|
-
};
|
|
1001
|
-
var updatePackageJson = async (builtPreviewAppPath) => {
|
|
1002
|
-
const packageJsonPath = path9.resolve(builtPreviewAppPath, "./package.json");
|
|
1003
|
-
const packageJson = JSON.parse(
|
|
1004
|
-
await fs5.promises.readFile(packageJsonPath, "utf8")
|
|
1005
|
-
);
|
|
1006
|
-
packageJson.scripts.build = "next build";
|
|
1007
|
-
packageJson.scripts.start = "next start";
|
|
1008
|
-
delete packageJson.scripts.postbuild;
|
|
1009
|
-
packageJson.name = "preview-server";
|
|
1010
|
-
delete packageJson.devDependencies["@react-email/render"];
|
|
1011
|
-
delete packageJson.devDependencies["@react-email/components"];
|
|
1012
|
-
delete packageJson.scripts.prepare;
|
|
1013
|
-
await fs5.promises.writeFile(
|
|
1014
|
-
packageJsonPath,
|
|
1015
|
-
JSON.stringify(packageJson),
|
|
1016
|
-
"utf8"
|
|
1017
|
-
);
|
|
1018
|
-
};
|
|
1019
|
-
var npmInstall = async (builtPreviewAppPath, packageManager) => {
|
|
1020
|
-
return new Promise((resolve, reject) => {
|
|
1021
|
-
const childProc = spawn(
|
|
1022
|
-
packageManager,
|
|
1023
|
-
[
|
|
1024
|
-
"install",
|
|
1025
|
-
packageManager === "deno" ? "" : "--include=dev",
|
|
1026
|
-
packageManager === "deno" ? "--quiet" : "--silent"
|
|
1027
|
-
],
|
|
1028
|
-
{
|
|
1029
|
-
cwd: builtPreviewAppPath,
|
|
1030
|
-
shell: true
|
|
1031
|
-
}
|
|
1032
|
-
);
|
|
1033
|
-
childProc.stdout.pipe(process.stdout);
|
|
1034
|
-
childProc.stderr.pipe(process.stderr);
|
|
1035
|
-
childProc.on("close", (code) => {
|
|
1036
|
-
if (code === 0) {
|
|
1037
|
-
resolve();
|
|
1038
|
-
} else {
|
|
1039
|
-
reject(
|
|
1040
|
-
new Error(
|
|
1041
|
-
`Unable to install the dependencies and it exited with code: ${code}`
|
|
1042
|
-
)
|
|
1043
|
-
);
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
});
|
|
1047
|
-
};
|
|
1048
|
-
var build = async ({
|
|
1049
|
-
dir: emailsDirRelativePath,
|
|
1050
|
-
packageManager
|
|
1051
|
-
}) => {
|
|
1052
|
-
try {
|
|
1053
|
-
const spinner = ora2({
|
|
1054
|
-
text: "Starting build process...",
|
|
1055
|
-
prefixText: " "
|
|
1056
|
-
}).start();
|
|
1057
|
-
registerSpinnerAutostopping(spinner);
|
|
1058
|
-
spinner.text = `Checking if ${emailsDirRelativePath} folder exists`;
|
|
1059
|
-
if (!fs5.existsSync(emailsDirRelativePath)) {
|
|
1060
|
-
process.exit(1);
|
|
1061
|
-
}
|
|
1062
|
-
const emailsDirPath = path9.join(process.cwd(), emailsDirRelativePath);
|
|
1063
|
-
const staticPath = path9.join(emailsDirPath, "static");
|
|
1064
|
-
const builtPreviewAppPath = path9.join(process.cwd(), ".react-email");
|
|
1065
|
-
if (fs5.existsSync(builtPreviewAppPath)) {
|
|
1066
|
-
spinner.text = "Deleting pre-existing `.react-email` folder";
|
|
1067
|
-
await fs5.promises.rm(builtPreviewAppPath, { recursive: true });
|
|
1068
|
-
}
|
|
1069
|
-
spinner.text = "Copying preview app from CLI to `.react-email`";
|
|
1070
|
-
await fs5.promises.cp(cliPackageLocation, builtPreviewAppPath, {
|
|
1071
|
-
recursive: true,
|
|
1072
|
-
filter: (source) => {
|
|
1073
|
-
return !/(\/|\\)cli(\/|\\)?/.test(source) && !/(\/|\\)\.next(\/|\\)?/.test(source) && !/(\/|\\)\.turbo(\/|\\)?/.test(source) && !/(\/|\\)node_modules(\/|\\)?$/.test(source);
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
if (fs5.existsSync(staticPath)) {
|
|
1077
|
-
spinner.text = "Copying `static` folder into `.react-email/public/static`";
|
|
1078
|
-
const builtStaticDirectory = path9.resolve(
|
|
1079
|
-
builtPreviewAppPath,
|
|
1080
|
-
"./public/static"
|
|
1081
|
-
);
|
|
1082
|
-
await fs5.promises.cp(staticPath, builtStaticDirectory, {
|
|
1083
|
-
recursive: true
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
spinner.text = "Setting Next environment variables for preview app to work properly";
|
|
1087
|
-
await setNextEnvironmentVariablesForBuild(
|
|
1088
|
-
emailsDirRelativePath,
|
|
1089
|
-
builtPreviewAppPath
|
|
1090
|
-
);
|
|
1091
|
-
spinner.text = "Setting server side generation for the email preview pages";
|
|
1092
|
-
await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
|
|
1093
|
-
spinner.text = "Updating package.json's build and start scripts";
|
|
1094
|
-
await updatePackageJson(builtPreviewAppPath);
|
|
1095
|
-
spinner.text = "Installing dependencies on `.react-email`";
|
|
1096
|
-
await npmInstall(builtPreviewAppPath, packageManager);
|
|
1097
|
-
spinner.stopAndPersist({
|
|
1098
|
-
text: "Successfully prepared `.react-email` for `next build`",
|
|
1099
|
-
symbol: logSymbols3.success
|
|
1100
|
-
});
|
|
1101
|
-
await buildPreviewApp(builtPreviewAppPath);
|
|
1102
|
-
} catch (error) {
|
|
1103
|
-
console.log(error);
|
|
1104
|
-
process.exit(1);
|
|
1105
|
-
}
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
|
-
// src/cli/commands/dev.ts
|
|
1109
|
-
import fs6 from "node:fs";
|
|
1131
|
+
// src/commands/dev.ts
|
|
1110
1132
|
var dev = async ({ dir: emailsDirRelativePath, port }) => {
|
|
1111
1133
|
try {
|
|
1112
1134
|
if (!fs6.existsSync(emailsDirRelativePath)) {
|
|
@@ -1126,11 +1148,11 @@ var dev = async ({ dir: emailsDirRelativePath, port }) => {
|
|
|
1126
1148
|
}
|
|
1127
1149
|
};
|
|
1128
1150
|
|
|
1129
|
-
// src/
|
|
1151
|
+
// src/commands/export.ts
|
|
1130
1152
|
import fs8, { unlinkSync, writeFileSync } from "node:fs";
|
|
1131
1153
|
import { createRequire } from "node:module";
|
|
1132
|
-
import
|
|
1133
|
-
import
|
|
1154
|
+
import path12 from "node:path";
|
|
1155
|
+
import url3 from "node:url";
|
|
1134
1156
|
import { build as build2 } from "esbuild";
|
|
1135
1157
|
import { glob } from "glob";
|
|
1136
1158
|
import logSymbols4 from "log-symbols";
|
|
@@ -1139,7 +1161,7 @@ import ora3 from "ora";
|
|
|
1139
1161
|
|
|
1140
1162
|
// src/utils/esbuild/renderring-utilities-exporter.ts
|
|
1141
1163
|
import { promises as fs7 } from "node:fs";
|
|
1142
|
-
import
|
|
1164
|
+
import path11 from "node:path";
|
|
1143
1165
|
|
|
1144
1166
|
// src/utils/esbuild/escape-string-for-regex.ts
|
|
1145
1167
|
function escapeStringForRegex(string) {
|
|
@@ -1162,7 +1184,7 @@ var renderingUtilitiesExporter = (emailTemplates) => ({
|
|
|
1162
1184
|
export { render } from 'react-email-module-that-will-export-render'
|
|
1163
1185
|
export { createElement as reactEmailCreateReactElement } from 'react';
|
|
1164
1186
|
`,
|
|
1165
|
-
loader:
|
|
1187
|
+
loader: path11.extname(pathToFile).slice(1)
|
|
1166
1188
|
};
|
|
1167
1189
|
}
|
|
1168
1190
|
);
|
|
@@ -1189,18 +1211,18 @@ var renderingUtilitiesExporter = (emailTemplates) => ({
|
|
|
1189
1211
|
}
|
|
1190
1212
|
});
|
|
1191
1213
|
|
|
1192
|
-
// src/
|
|
1214
|
+
// src/commands/export.ts
|
|
1193
1215
|
var getEmailTemplatesFromDirectory = (emailDirectory) => {
|
|
1194
1216
|
const templatePaths = [];
|
|
1195
1217
|
emailDirectory.emailFilenames.forEach(
|
|
1196
|
-
(filename3) => templatePaths.push(
|
|
1218
|
+
(filename3) => templatePaths.push(path12.join(emailDirectory.absolutePath, filename3))
|
|
1197
1219
|
);
|
|
1198
1220
|
emailDirectory.subDirectories.forEach((directory) => {
|
|
1199
1221
|
templatePaths.push(...getEmailTemplatesFromDirectory(directory));
|
|
1200
1222
|
});
|
|
1201
1223
|
return templatePaths;
|
|
1202
1224
|
};
|
|
1203
|
-
var filename2 =
|
|
1225
|
+
var filename2 = url3.fileURLToPath(import.meta.url);
|
|
1204
1226
|
var require2 = createRequire(filename2);
|
|
1205
1227
|
var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirectoryPath, options) => {
|
|
1206
1228
|
if (fs8.existsSync(pathToWhereEmailMarkupShouldBeDumped)) {
|
|
@@ -1212,7 +1234,7 @@ var exportTemplates = async (pathToWhereEmailMarkupShouldBeDumped, emailsDirecto
|
|
|
1212
1234
|
registerSpinnerAutostopping(spinner);
|
|
1213
1235
|
}
|
|
1214
1236
|
const emailsDirectoryMetadata = await getEmailsDirectoryMetadata(
|
|
1215
|
-
|
|
1237
|
+
path12.resolve(process.cwd(), emailsDirectoryPath),
|
|
1216
1238
|
true
|
|
1217
1239
|
);
|
|
1218
1240
|
if (typeof emailsDirectoryMetadata === "undefined") {
|
|
@@ -1294,9 +1316,9 @@ ${buildFailure.message}`);
|
|
|
1294
1316
|
spinner.text = "Copying static files";
|
|
1295
1317
|
spinner.render();
|
|
1296
1318
|
}
|
|
1297
|
-
const staticDirectoryPath =
|
|
1319
|
+
const staticDirectoryPath = path12.join(emailsDirectoryPath, "static");
|
|
1298
1320
|
if (fs8.existsSync(staticDirectoryPath)) {
|
|
1299
|
-
const pathToDumpStaticFilesInto =
|
|
1321
|
+
const pathToDumpStaticFilesInto = path12.join(
|
|
1300
1322
|
pathToWhereEmailMarkupShouldBeDumped,
|
|
1301
1323
|
"static"
|
|
1302
1324
|
);
|
|
@@ -1331,14 +1353,15 @@ ${buildFailure.message}`);
|
|
|
1331
1353
|
}
|
|
1332
1354
|
};
|
|
1333
1355
|
|
|
1334
|
-
// src/
|
|
1356
|
+
// src/commands/start.ts
|
|
1335
1357
|
import { spawn as spawn2 } from "node:child_process";
|
|
1336
1358
|
import fs9 from "node:fs";
|
|
1337
|
-
import
|
|
1359
|
+
import path13 from "node:path";
|
|
1338
1360
|
var start = async () => {
|
|
1339
1361
|
try {
|
|
1362
|
+
const previewServerLocation = await getPreviewServerLocation();
|
|
1340
1363
|
const usersProjectLocation = process.cwd();
|
|
1341
|
-
const builtPreviewPath =
|
|
1364
|
+
const builtPreviewPath = path13.resolve(
|
|
1342
1365
|
usersProjectLocation,
|
|
1343
1366
|
"./.react-email"
|
|
1344
1367
|
);
|
|
@@ -1348,8 +1371,8 @@ var start = async () => {
|
|
|
1348
1371
|
);
|
|
1349
1372
|
process.exit(1);
|
|
1350
1373
|
}
|
|
1351
|
-
const nextStart = spawn2("
|
|
1352
|
-
cwd:
|
|
1374
|
+
const nextStart = spawn2("npx", ["next", "start", builtPreviewPath], {
|
|
1375
|
+
cwd: previewServerLocation,
|
|
1353
1376
|
stdio: "inherit"
|
|
1354
1377
|
});
|
|
1355
1378
|
process.on("SIGINT", () => {
|
|
@@ -1364,7 +1387,7 @@ var start = async () => {
|
|
|
1364
1387
|
}
|
|
1365
1388
|
};
|
|
1366
1389
|
|
|
1367
|
-
// src/
|
|
1390
|
+
// src/index.ts
|
|
1368
1391
|
var PACKAGE_NAME = "react-email";
|
|
1369
1392
|
program.name(PACKAGE_NAME).description("A live preview of your emails right in your browser").version(package_default.version);
|
|
1370
1393
|
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);
|