react-email 4.0.16 → 4.1.0-canary.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dev/index.js +40 -0
  3. package/dev/package.json +13 -0
  4. package/dist/index.js +1 -1
  5. package/package.json +13 -46
  6. package/readme.md +16 -0
  7. package/src/commands/build.ts +306 -0
  8. package/src/commands/dev.ts +27 -0
  9. package/src/commands/export.ts +204 -0
  10. package/src/commands/start.ts +38 -0
  11. package/src/index.ts +55 -0
  12. package/src/utils/__snapshots__/tree.spec.ts.snap +27 -0
  13. package/src/utils/esbuild/renderring-utilities-exporter.ts +1 -1
  14. package/src/utils/get-emails-directory-metadata.spec.ts +1 -1
  15. package/src/utils/get-preview-server-location.ts +51 -0
  16. package/src/utils/index.ts +2 -6
  17. package/src/utils/packageJson.ts +4 -0
  18. package/src/utils/preview/get-env-variables-for-preview-app.ts +14 -0
  19. package/src/utils/preview/hot-reloading/create-dependency-graph.spec.ts +284 -0
  20. package/src/utils/preview/hot-reloading/create-dependency-graph.ts +321 -0
  21. package/src/utils/preview/hot-reloading/get-imported-modules.spec.ts +151 -0
  22. package/src/utils/preview/hot-reloading/get-imported-modules.ts +49 -0
  23. package/src/utils/preview/hot-reloading/resolve-path-aliases.spec.ts +11 -0
  24. package/src/utils/preview/hot-reloading/resolve-path-aliases.ts +32 -0
  25. package/src/utils/preview/hot-reloading/setup-hot-reloading.ts +121 -0
  26. package/src/utils/preview/hot-reloading/test/tsconfig.json +8 -0
  27. package/src/utils/preview/index.ts +2 -0
  28. package/src/utils/preview/serve-static-file.ts +51 -0
  29. package/src/utils/preview/start-dev-server.ts +234 -0
  30. package/src/utils/tree.spec.ts +5 -0
  31. package/src/utils/tree.ts +76 -0
  32. package/src/utils/types/hot-reload-change.ts +1 -1
  33. package/src/utils/types/hot-reload-event.ts +1 -1
  34. package/tsconfig.json +4 -10
  35. package/dist/cli/index.d.mts +0 -1
  36. package/dist/cli/index.d.ts +0 -1
  37. package/dist/cli/index.js +0 -2785
  38. package/dist/cli/index.mjs +0 -1361
  39. package/dist/index.d.mts +0 -20
  40. package/dist/index.d.ts +0 -20
  41. package/dist/index.mjs +0 -21
  42. package/dist/package/index.d.mts +0 -33
  43. package/dist/package/index.d.ts +0 -33
  44. package/dist/package/index.js +0 -62
  45. package/dist/package/index.mjs +0 -7
  46. package/dist/preview/.next/BUILD_ID +0 -1
  47. package/dist/preview/.next/app-build-manifest.json +0 -44
  48. package/dist/preview/.next/app-path-routes-manifest.json +0 -6
  49. package/dist/preview/.next/build-manifest.json +0 -33
  50. package/dist/preview/.next/diagnostics/build-diagnostics.json +0 -6
  51. package/dist/preview/.next/diagnostics/framework.json +0 -1
  52. package/dist/preview/.next/export-marker.json +0 -6
  53. package/dist/preview/.next/images-manifest.json +0 -57
  54. package/dist/preview/.next/next-minimal-server.js.nft.json +0 -1
  55. package/dist/preview/.next/next-server.js.nft.json +0 -1
  56. package/dist/preview/.next/package.json +0 -1
  57. package/dist/preview/.next/prerender-manifest.json +0 -41
  58. package/dist/preview/.next/react-loadable-manifest.json +0 -1
  59. package/dist/preview/.next/required-server-files.json +0 -311
  60. package/dist/preview/.next/routes-manifest.json +0 -64
  61. package/dist/preview/.next/server/app/_not-found/page.js +0 -1
  62. package/dist/preview/.next/server/app/_not-found/page.js.nft.json +0 -1
  63. package/dist/preview/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  64. package/dist/preview/.next/server/app/favicon.ico/route.js +0 -1
  65. package/dist/preview/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  66. package/dist/preview/.next/server/app/favicon.ico.body +0 -0
  67. package/dist/preview/.next/server/app/favicon.ico.meta +0 -1
  68. package/dist/preview/.next/server/app/page.js +0 -1
  69. package/dist/preview/.next/server/app/page.js.nft.json +0 -1
  70. package/dist/preview/.next/server/app/page_client-reference-manifest.js +0 -1
  71. package/dist/preview/.next/server/app/preview/[...slug]/page.js +0 -321
  72. package/dist/preview/.next/server/app/preview/[...slug]/page.js.nft.json +0 -1
  73. package/dist/preview/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +0 -1
  74. package/dist/preview/.next/server/app-paths-manifest.json +0 -6
  75. package/dist/preview/.next/server/chunks/134.js +0 -6
  76. package/dist/preview/.next/server/chunks/235.js +0 -15
  77. package/dist/preview/.next/server/chunks/275.js +0 -1
  78. package/dist/preview/.next/server/chunks/343.js +0 -20
  79. package/dist/preview/.next/server/chunks/428.js +0 -14
  80. package/dist/preview/.next/server/chunks/963.js +0 -1
  81. package/dist/preview/.next/server/functions-config-manifest.json +0 -4
  82. package/dist/preview/.next/server/interception-route-rewrite-manifest.js +0 -1
  83. package/dist/preview/.next/server/middleware-build-manifest.js +0 -1
  84. package/dist/preview/.next/server/middleware-manifest.json +0 -6
  85. package/dist/preview/.next/server/middleware-react-loadable-manifest.js +0 -1
  86. package/dist/preview/.next/server/next-font-manifest.js +0 -1
  87. package/dist/preview/.next/server/next-font-manifest.json +0 -1
  88. package/dist/preview/.next/server/pages/500.html +0 -1
  89. package/dist/preview/.next/server/pages/_app.js +0 -1
  90. package/dist/preview/.next/server/pages/_app.js.nft.json +0 -1
  91. package/dist/preview/.next/server/pages/_document.js +0 -1
  92. package/dist/preview/.next/server/pages/_document.js.nft.json +0 -1
  93. package/dist/preview/.next/server/pages/_error.js +0 -1
  94. package/dist/preview/.next/server/pages/_error.js.nft.json +0 -1
  95. package/dist/preview/.next/server/pages-manifest.json +0 -5
  96. package/dist/preview/.next/server/server-reference-manifest.js +0 -1
  97. package/dist/preview/.next/server/server-reference-manifest.json +0 -1
  98. package/dist/preview/.next/server/webpack-runtime.js +0 -1
  99. package/dist/preview/.next/static/chunks/107-3043079e7cb8bcae.js +0 -1
  100. package/dist/preview/.next/static/chunks/293-297b1eb2241f9a70.js +0 -1
  101. package/dist/preview/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +0 -1
  102. package/dist/preview/.next/static/chunks/45-1021fac82f766268.js +0 -1
  103. package/dist/preview/.next/static/chunks/484-e38a627386aae911.js +0 -1
  104. package/dist/preview/.next/static/chunks/589-817d8691661d370e.js +0 -1
  105. package/dist/preview/.next/static/chunks/902-c34acb56733e0ce1.js +0 -1
  106. package/dist/preview/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +0 -1
  107. package/dist/preview/.next/static/chunks/app/layout-269b5cbd8f4cd2e3.js +0 -1
  108. package/dist/preview/.next/static/chunks/app/page-2dbfb5b2dc4b1191.js +0 -1
  109. package/dist/preview/.next/static/chunks/app/preview/[...slug]/page-79e0c9b528a62f8b.js +0 -1
  110. package/dist/preview/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +0 -6
  111. package/dist/preview/.next/static/chunks/framework-b887e9fc751a9906.js +0 -1
  112. package/dist/preview/.next/static/chunks/main-9a03e7ba8acb1900.js +0 -1
  113. package/dist/preview/.next/static/chunks/main-app-976577a424e11c75.js +0 -1
  114. package/dist/preview/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +0 -1
  115. package/dist/preview/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +0 -1
  116. package/dist/preview/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  117. package/dist/preview/.next/static/chunks/webpack-31c45daa2bd82a7b.js +0 -1
  118. package/dist/preview/.next/static/css/ac3decd5d6736fbe.css +0 -3
  119. package/dist/preview/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
  120. package/dist/preview/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
  121. package/dist/preview/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
  122. package/dist/preview/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
  123. package/dist/preview/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
  124. package/dist/preview/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
  125. package/dist/preview/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  126. package/dist/preview/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
  127. package/dist/preview/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
  128. package/dist/preview/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
  129. package/dist/preview/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  130. package/dist/preview/.next/static/media/e4051546b3043204-s.p.otf +0 -0
  131. package/dist/preview/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  132. package/dist/preview/.next/static/media/logo.2ce2a759.png +0 -0
  133. package/dist/preview/.next/static/yxjkw7Y7HRLmRWkl3S43z/_buildManifest.js +0 -1
  134. package/dist/preview/.next/static/yxjkw7Y7HRLmRWkl3S43z/_ssgManifest.js +0 -1
  135. package/dist/preview/.next/trace +0 -27
  136. package/dist/preview/.next/types/app/layout.ts +0 -84
  137. package/dist/preview/.next/types/app/page.ts +0 -84
  138. package/dist/preview/.next/types/app/preview/[...slug]/page.ts +0 -84
  139. package/dist/preview/.next/types/cache-life.d.ts +0 -141
  140. package/dist/preview/.next/types/package.json +0 -1
  141. package/module-punycode.d.ts +0 -3
  142. package/next-env.d.ts +0 -5
  143. package/next.config.js +0 -22
  144. package/postcss.config.js +0 -8
  145. package/scripts/build-preview-server.mjs +0 -33
  146. package/scripts/fill-caniemail-data.mjs +0 -36
  147. package/src/actions/email-validation/caniemail-data.ts +0 -85993
  148. package/src/actions/email-validation/check-compatibility.ts +0 -333
  149. package/src/actions/email-validation/check-images.spec.tsx +0 -100
  150. package/src/actions/email-validation/check-images.ts +0 -160
  151. package/src/actions/email-validation/check-links.spec.tsx +0 -113
  152. package/src/actions/email-validation/check-links.ts +0 -113
  153. package/src/actions/email-validation/get-code-location-from-ast-element.ts +0 -18
  154. package/src/actions/email-validation/quick-fetch.ts +0 -14
  155. package/src/actions/get-email-path-from-slug.ts +0 -32
  156. package/src/actions/get-emails-directory-metadata-action.ts +0 -19
  157. package/src/actions/render-email-by-path.tsx +0 -121
  158. package/src/animated-icons-data/help.json +0 -1082
  159. package/src/animated-icons-data/link.json +0 -1309
  160. package/src/animated-icons-data/load.json +0 -443
  161. package/src/animated-icons-data/mail.json +0 -1320
  162. package/src/app/env.ts +0 -15
  163. package/src/app/favicon.ico +0 -0
  164. package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
  165. package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
  166. package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
  167. package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
  168. package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
  169. package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
  170. package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
  171. package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
  172. package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
  173. package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
  174. package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
  175. package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
  176. package/src/app/fonts.ts +0 -39
  177. package/src/app/globals.css +0 -15
  178. package/src/app/layout.tsx +0 -43
  179. package/src/app/logo.png +0 -0
  180. package/src/app/page.tsx +0 -46
  181. package/src/app/preview/[...slug]/page.tsx +0 -157
  182. package/src/app/preview/[...slug]/preview.tsx +0 -216
  183. package/src/app/preview/[...slug]/rendering-error.tsx +0 -40
  184. package/src/commands/testing/out/magic-links/aws-verify-email.html +0 -165
  185. package/src/commands/testing/out/magic-links/linear-login-code.html +0 -90
  186. package/src/commands/testing/out/magic-links/notion-magic-link.html +0 -76
  187. package/src/commands/testing/out/magic-links/plaid-verify-identity.html +0 -78
  188. package/src/commands/testing/out/magic-links/raycast-magic-link.html +0 -91
  189. package/src/commands/testing/out/magic-links/slack-confirm.html +0 -240
  190. package/src/commands/testing/out/newsletters/codepen-challengers.html +0 -548
  191. package/src/commands/testing/out/newsletters/google-play-policy-update.html +0 -339
  192. package/src/commands/testing/out/newsletters/stack-overflow-tips.html +0 -231
  193. package/src/commands/testing/out/notifications/github-access-token.html +0 -104
  194. package/src/commands/testing/out/notifications/papermark-year-in-review.html +0 -317
  195. package/src/commands/testing/out/notifications/vercel-invite-user.html +0 -171
  196. package/src/commands/testing/out/notifications/yelp-recent-login.html +0 -195
  197. package/src/commands/testing/out/receipts/apple-receipt.html +0 -677
  198. package/src/commands/testing/out/receipts/nike-receipt.html +0 -724
  199. package/src/commands/testing/out/reset-password/dropbox-reset-password.html +0 -98
  200. package/src/commands/testing/out/reset-password/twitch-reset-password.html +0 -220
  201. package/src/commands/testing/out/reviews/airbnb-review.html +0 -206
  202. package/src/commands/testing/out/reviews/amazon-review.html +0 -356
  203. package/src/commands/testing/out/static/airbnb-logo.png +0 -0
  204. package/src/commands/testing/out/static/airbnb-review-user.jpg +0 -0
  205. package/src/commands/testing/out/static/amazon-book.jpg +0 -0
  206. package/src/commands/testing/out/static/amazon-facebook.jpg +0 -0
  207. package/src/commands/testing/out/static/amazon-instagram.jpg +0 -0
  208. package/src/commands/testing/out/static/amazon-logo.png +0 -0
  209. package/src/commands/testing/out/static/amazon-prime-logo.png +0 -0
  210. package/src/commands/testing/out/static/amazon-rating.gif +0 -0
  211. package/src/commands/testing/out/static/amazon-twitter.jpg +0 -0
  212. package/src/commands/testing/out/static/apple-card-icon.png +0 -0
  213. package/src/commands/testing/out/static/apple-hbo-max-icon.jpeg +0 -0
  214. package/src/commands/testing/out/static/apple-logo.png +0 -0
  215. package/src/commands/testing/out/static/apple-wallet.png +0 -0
  216. package/src/commands/testing/out/static/aws-logo.png +0 -0
  217. package/src/commands/testing/out/static/codepen-challengers.png +0 -0
  218. package/src/commands/testing/out/static/codepen-cube.png +0 -0
  219. package/src/commands/testing/out/static/codepen-pro.png +0 -0
  220. package/src/commands/testing/out/static/dropbox-logo.png +0 -0
  221. package/src/commands/testing/out/static/github.png +0 -0
  222. package/src/commands/testing/out/static/google-play-academy.png +0 -0
  223. package/src/commands/testing/out/static/google-play-chat.png +0 -0
  224. package/src/commands/testing/out/static/google-play-footer.png +0 -0
  225. package/src/commands/testing/out/static/google-play-header.png +0 -0
  226. package/src/commands/testing/out/static/google-play-icon.png +0 -0
  227. package/src/commands/testing/out/static/google-play-logo.png +0 -0
  228. package/src/commands/testing/out/static/google-play-pl.png +0 -0
  229. package/src/commands/testing/out/static/google-play.png +0 -0
  230. package/src/commands/testing/out/static/koala-logo.png +0 -0
  231. package/src/commands/testing/out/static/linear-logo.png +0 -0
  232. package/src/commands/testing/out/static/netlify-logo.png +0 -0
  233. package/src/commands/testing/out/static/nike-logo.png +0 -0
  234. package/src/commands/testing/out/static/nike-phone.png +0 -0
  235. package/src/commands/testing/out/static/nike-product.png +0 -0
  236. package/src/commands/testing/out/static/nike-recomendation-1.png +0 -0
  237. package/src/commands/testing/out/static/nike-recomendation-2.png +0 -0
  238. package/src/commands/testing/out/static/nike-recomendation-3.png +0 -0
  239. package/src/commands/testing/out/static/nike-recomendation-4.png +0 -0
  240. package/src/commands/testing/out/static/notion-logo.png +0 -0
  241. package/src/commands/testing/out/static/plaid-logo.png +0 -0
  242. package/src/commands/testing/out/static/raycast-bg.png +0 -0
  243. package/src/commands/testing/out/static/raycast-logo.png +0 -0
  244. package/src/commands/testing/out/static/slack-facebook.png +0 -0
  245. package/src/commands/testing/out/static/slack-linkedin.png +0 -0
  246. package/src/commands/testing/out/static/slack-logo.png +0 -0
  247. package/src/commands/testing/out/static/slack-twitter.png +0 -0
  248. package/src/commands/testing/out/static/stack-overflow-header.png +0 -0
  249. package/src/commands/testing/out/static/stack-overflow-logo-sm.png +0 -0
  250. package/src/commands/testing/out/static/stack-overflow-logo.png +0 -0
  251. package/src/commands/testing/out/static/stripe-logo.png +0 -0
  252. package/src/commands/testing/out/static/twitch-icon-facebook.png +0 -0
  253. package/src/commands/testing/out/static/twitch-icon-twitter.png +0 -0
  254. package/src/commands/testing/out/static/twitch-logo.png +0 -0
  255. package/src/commands/testing/out/static/vercel-arrow.png +0 -0
  256. package/src/commands/testing/out/static/vercel-logo.png +0 -0
  257. package/src/commands/testing/out/static/vercel-team.png +0 -0
  258. package/src/commands/testing/out/static/vercel-user.png +0 -0
  259. package/src/commands/testing/out/static/yelp-footer.png +0 -0
  260. package/src/commands/testing/out/static/yelp-header.png +0 -0
  261. package/src/commands/testing/out/static/yelp-logo.png +0 -0
  262. package/src/commands/testing/out/welcome/koala-welcome.html +0 -90
  263. package/src/commands/testing/out/welcome/netlify-welcome.html +0 -199
  264. package/src/commands/testing/out/welcome/stripe-welcome.html +0 -153
  265. package/src/components/button.tsx +0 -101
  266. package/src/components/code-container.tsx +0 -164
  267. package/src/components/code-snippet.tsx +0 -9
  268. package/src/components/code.tsx +0 -184
  269. package/src/components/heading.tsx +0 -113
  270. package/src/components/icons/icon-arrow-down.tsx +0 -16
  271. package/src/components/icons/icon-base.tsx +0 -26
  272. package/src/components/icons/icon-bug.tsx +0 -19
  273. package/src/components/icons/icon-button.tsx +0 -23
  274. package/src/components/icons/icon-check.tsx +0 -19
  275. package/src/components/icons/icon-clipboard.tsx +0 -40
  276. package/src/components/icons/icon-download.tsx +0 -19
  277. package/src/components/icons/icon-email.tsx +0 -18
  278. package/src/components/icons/icon-file.tsx +0 -19
  279. package/src/components/icons/icon-folder-open.tsx +0 -19
  280. package/src/components/icons/icon-folder.tsx +0 -18
  281. package/src/components/icons/icon-hide-sidebar.tsx +0 -23
  282. package/src/components/icons/icon-image.tsx +0 -19
  283. package/src/components/icons/icon-info.tsx +0 -18
  284. package/src/components/icons/icon-link.tsx +0 -14
  285. package/src/components/icons/icon-monitor.tsx +0 -19
  286. package/src/components/icons/icon-phone.tsx +0 -26
  287. package/src/components/icons/icon-reload.tsx +0 -18
  288. package/src/components/icons/icon-source.tsx +0 -19
  289. package/src/components/icons/icon-stamp.tsx +0 -14
  290. package/src/components/icons/icon-warning.tsx +0 -31
  291. package/src/components/index.ts +0 -7
  292. package/src/components/logo.tsx +0 -63
  293. package/src/components/resizable-wrapper.tsx +0 -173
  294. package/src/components/send.tsx +0 -134
  295. package/src/components/shell.tsx +0 -95
  296. package/src/components/sidebar/file-tree-directory-children.tsx +0 -134
  297. package/src/components/sidebar/file-tree-directory.tsx +0 -92
  298. package/src/components/sidebar/file-tree.tsx +0 -31
  299. package/src/components/sidebar/index.ts +0 -1
  300. package/src/components/sidebar/sidebar.tsx +0 -43
  301. package/src/components/text.tsx +0 -99
  302. package/src/components/toolbar/checking-results.tsx +0 -150
  303. package/src/components/toolbar/code-preview-line-link.tsx +0 -40
  304. package/src/components/toolbar/compatibility.tsx +0 -113
  305. package/src/components/toolbar/linter.tsx +0 -278
  306. package/src/components/toolbar/results.tsx +0 -51
  307. package/src/components/toolbar/spam-assassin.tsx +0 -155
  308. package/src/components/toolbar/toolbar-button.tsx +0 -52
  309. package/src/components/toolbar/use-cached-state.ts +0 -33
  310. package/src/components/toolbar.tsx +0 -349
  311. package/src/components/tooltip-content.tsx +0 -31
  312. package/src/components/tooltip.tsx +0 -19
  313. package/src/components/topbar/active-view-toggle-group.tsx +0 -86
  314. package/src/components/topbar/view-size-controls.tsx +0 -247
  315. package/src/components/topbar.tsx +0 -59
  316. package/src/contexts/emails.tsx +0 -59
  317. package/src/contexts/fragment-identifier.tsx +0 -48
  318. package/src/contexts/preview.tsx +0 -79
  319. package/src/hooks/use-clamped-state.ts +0 -24
  320. package/src/hooks/use-email-rendering-result.ts +0 -58
  321. package/src/hooks/use-fragment-identifier.ts +0 -14
  322. package/src/hooks/use-hot-reload.ts +0 -31
  323. package/src/hooks/use-icon-animation.ts +0 -41
  324. package/src/hooks/use-rendering-metadata.ts +0 -36
  325. package/src/package/body/dist/index.d.mts +0 -6
  326. package/src/package/body/dist/index.d.ts +0 -6
  327. package/src/package/body/dist/index.js +0 -79
  328. package/src/package/body/dist/index.mjs +0 -45
  329. package/src/package/button/dist/index.d.mts +0 -6
  330. package/src/package/button/dist/index.d.ts +0 -6
  331. package/src/package/button/dist/index.js +0 -252
  332. package/src/package/button/dist/index.mjs +0 -218
  333. package/src/package/code-block/dist/index.d.mts +0 -4906
  334. package/src/package/code-block/dist/index.d.ts +0 -4906
  335. package/src/package/code-block/dist/index.js +0 -18205
  336. package/src/package/code-block/dist/index.mjs +0 -18133
  337. package/src/package/code-inline/dist/index.d.mts +0 -11
  338. package/src/package/code-inline/dist/index.d.ts +0 -11
  339. package/src/package/code-inline/dist/index.js +0 -106
  340. package/src/package/code-inline/dist/index.mjs +0 -72
  341. package/src/package/column/dist/index.d.mts +0 -6
  342. package/src/package/column/dist/index.d.ts +0 -6
  343. package/src/package/column/dist/index.js +0 -79
  344. package/src/package/column/dist/index.mjs +0 -45
  345. package/src/package/components/dist/index.d.mts +0 -20
  346. package/src/package/components/dist/index.d.ts +0 -20
  347. package/src/package/components/dist/index.js +0 -62
  348. package/src/package/components/dist/index.mjs +0 -21
  349. package/src/package/container/dist/index.d.mts +0 -6
  350. package/src/package/container/dist/index.d.ts +0 -6
  351. package/src/package/container/dist/index.js +0 -93
  352. package/src/package/container/dist/index.mjs +0 -59
  353. package/src/package/font/dist/index.d.mts +0 -25
  354. package/src/package/font/dist/index.d.ts +0 -25
  355. package/src/package/font/dist/index.js +0 -55
  356. package/src/package/font/dist/index.mjs +0 -28
  357. package/src/package/head/dist/index.d.mts +0 -6
  358. package/src/package/head/dist/index.d.ts +0 -6
  359. package/src/package/head/dist/index.js +0 -83
  360. package/src/package/head/dist/index.mjs +0 -49
  361. package/src/package/heading/dist/index.d.mts +0 -43
  362. package/src/package/heading/dist/index.d.ts +0 -43
  363. package/src/package/heading/dist/index.js +0 -113
  364. package/src/package/heading/dist/index.mjs +0 -79
  365. package/src/package/hr/dist/index.d.mts +0 -6
  366. package/src/package/hr/dist/index.d.ts +0 -6
  367. package/src/package/hr/dist/index.js +0 -89
  368. package/src/package/hr/dist/index.mjs +0 -55
  369. package/src/package/html/dist/index.d.mts +0 -6
  370. package/src/package/html/dist/index.d.ts +0 -6
  371. package/src/package/html/dist/index.js +0 -79
  372. package/src/package/html/dist/index.mjs +0 -45
  373. package/src/package/img/dist/index.d.mts +0 -6
  374. package/src/package/img/dist/index.d.ts +0 -6
  375. package/src/package/img/dist/index.js +0 -94
  376. package/src/package/img/dist/index.mjs +0 -60
  377. package/src/package/link/dist/index.d.mts +0 -6
  378. package/src/package/link/dist/index.d.ts +0 -6
  379. package/src/package/link/dist/index.js +0 -90
  380. package/src/package/link/dist/index.mjs +0 -56
  381. package/src/package/markdown/dist/index.d.mts +0 -15
  382. package/src/package/markdown/dist/index.d.ts +0 -15
  383. package/src/package/markdown/dist/index.js +0 -92
  384. package/src/package/markdown/dist/index.mjs +0 -58
  385. package/src/package/preview/dist/index.d.mts +0 -12
  386. package/src/package/preview/dist/index.d.ts +0 -12
  387. package/src/package/preview/dist/index.js +0 -108
  388. package/src/package/preview/dist/index.mjs +0 -73
  389. package/src/package/render/dist/browser/index.d.mts +0 -24
  390. package/src/package/render/dist/browser/index.d.ts +0 -24
  391. package/src/package/render/dist/browser/index.js +0 -250
  392. package/src/package/render/dist/browser/index.mjs +0 -214
  393. package/src/package/render/dist/index.d.mts +0 -23
  394. package/src/package/render/dist/index.d.ts +0 -23
  395. package/src/package/render/dist/index.js +0 -768
  396. package/src/package/render/dist/index.mjs +0 -733
  397. package/src/package/render/dist/node/index.d.mts +0 -27
  398. package/src/package/render/dist/node/index.d.ts +0 -27
  399. package/src/package/render/dist/node/index.js +0 -212
  400. package/src/package/render/dist/node/index.mjs +0 -176
  401. package/src/package/row/dist/index.d.mts +0 -10
  402. package/src/package/row/dist/index.d.ts +0 -10
  403. package/src/package/row/dist/index.js +0 -93
  404. package/src/package/row/dist/index.mjs +0 -59
  405. package/src/package/section/dist/index.d.mts +0 -6
  406. package/src/package/section/dist/index.d.ts +0 -6
  407. package/src/package/section/dist/index.js +0 -93
  408. package/src/package/section/dist/index.mjs +0 -59
  409. package/src/package/tailwind/dist/index.d.ts +0 -19
  410. package/src/package/tailwind/dist/index.js +0 -48
  411. package/src/package/tailwind/dist/index.mjs +0 -17167
  412. package/src/package/tailwind/dist/tailwindcss/config.d.ts +0 -376
  413. package/src/package/tailwind/dist/tailwindcss/generated/.gitkeep +0 -0
  414. package/src/package/tailwind/dist/tailwindcss/generated/colors.d.ts +0 -298
  415. package/src/package/tailwind/dist/tailwindcss/generated/corePluginList.d.ts +0 -1
  416. package/src/package/tailwind/dist/tailwindcss/generated/default-theme.d.ts +0 -397
  417. package/src/package/tailwind/dist/tailwindcss/index.d.ts +0 -11
  418. package/src/package/text/dist/index.d.mts +0 -6
  419. package/src/package/text/dist/index.d.ts +0 -6
  420. package/src/package/text/dist/index.js +0 -89
  421. package/src/package/text/dist/index.mjs +0 -55
  422. package/src/utils/__snapshots__/get-email-component.spec.ts.snap +0 -3
  423. package/src/utils/caniemail/all-css-properties.ts +0 -358
  424. package/src/utils/caniemail/ast/__snapshots__/get-object-variables.spec.ts.snap +0 -74
  425. package/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap +0 -24
  426. package/src/utils/caniemail/ast/get-object-variables.spec.ts +0 -19
  427. package/src/utils/caniemail/ast/get-object-variables.ts +0 -61
  428. package/src/utils/caniemail/ast/get-used-style-properties.spec.ts +0 -23
  429. package/src/utils/caniemail/ast/get-used-style-properties.ts +0 -91
  430. package/src/utils/caniemail/get-compatibility-stats-for-entry.ts +0 -118
  431. package/src/utils/caniemail/get-css-functions.ts +0 -25
  432. package/src/utils/caniemail/get-css-property-names.ts +0 -32
  433. package/src/utils/caniemail/get-css-property-with-value.ts +0 -14
  434. package/src/utils/caniemail/get-css-unit.ts +0 -3
  435. package/src/utils/caniemail/get-element-attributes.ts +0 -7
  436. package/src/utils/caniemail/get-element-names.ts +0 -20
  437. package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +0 -30
  438. package/src/utils/caniemail/tailwind/get-tailwind-config.ts +0 -187
  439. package/src/utils/caniemail/tailwind/get-tailwind-metadata.spec.ts +0 -25
  440. package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +0 -45
  441. package/src/utils/caniemail/tailwind/setup-tailwind-context.ts +0 -15
  442. package/src/utils/cn.ts +0 -6
  443. package/src/utils/constants.ts +0 -6
  444. package/src/utils/contains-email-template.spec.ts +0 -124
  445. package/src/utils/contains-email-template.ts +0 -33
  446. package/src/utils/copy-text-to-clipboard.ts +0 -7
  447. package/src/utils/get-email-component.spec.ts +0 -41
  448. package/src/utils/get-email-component.ts +0 -134
  449. package/src/utils/get-line-and-column-from-offset.spec.ts +0 -11
  450. package/src/utils/get-line-and-column-from-offset.ts +0 -11
  451. package/src/utils/improve-error-with-sourcemap.ts +0 -86
  452. package/src/utils/js-email-detection.spec.ts +0 -24
  453. package/src/utils/language-map.ts +0 -7
  454. package/src/utils/linting.ts +0 -60
  455. package/src/utils/load-stream.ts +0 -15
  456. package/src/utils/result.ts +0 -49
  457. package/src/utils/run-bundled-code.ts +0 -64
  458. package/src/utils/sanitize.ts +0 -6
  459. package/src/utils/static-node-modules-for-vm.ts +0 -93
  460. package/src/utils/testing/js-email-export-default.js +0 -17
  461. package/src/utils/testing/js-email-test.js +0 -18
  462. package/src/utils/testing/mdx-email-test.js +0 -128
  463. package/src/utils/testing/request-response-email.tsx +0 -9
  464. package/src/utils/types/as.ts +0 -26
  465. package/src/utils/types/email-template.ts +0 -8
  466. package/src/utils/types/error-object.ts +0 -11
  467. package/src/utils/unreachable.ts +0 -8
  468. package/tailwind-internals.d.ts +0 -133
  469. package/tailwind.config.ts +0 -99
  470. /package/src/{components/toolbar/results-table.tsx → utils/preview/hot-reloading/test/some-file.ts} +0 -0
@@ -0,0 +1,284 @@
1
+ import { existsSync, promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import {
4
+ createDependencyGraph,
5
+ type DependencyGraph,
6
+ } from './create-dependency-graph.js';
7
+
8
+ const pathToFileForTestingDependencyGraph = path.join(
9
+ __dirname,
10
+ '.for-dependency-graph.ts',
11
+ );
12
+
13
+ vi.mock('@babel/traverse', async () => {
14
+ const traverse = await vi.importActual('@babel/traverse');
15
+ return { default: traverse };
16
+ });
17
+
18
+ test('createDependencyGraph()', async () => {
19
+ if (existsSync(pathToFileForTestingDependencyGraph)) {
20
+ await fs.rm(pathToFileForTestingDependencyGraph);
21
+ }
22
+
23
+ const [dependencyGraph, updateDependencyGraph] =
24
+ await createDependencyGraph(__dirname);
25
+
26
+ const toAbsolute = (relativePath: string) => {
27
+ return path.resolve(__dirname, relativePath);
28
+ };
29
+
30
+ const convertPathsToAbsolute = (graph: DependencyGraph) => {
31
+ return Object.fromEntries(
32
+ Object.entries(graph).map(([relativePath, module]) => {
33
+ return [
34
+ toAbsolute(relativePath),
35
+ {
36
+ path: toAbsolute(relativePath),
37
+ dependencyPaths: module.dependencyPaths.map((p) => toAbsolute(p)),
38
+ dependentPaths: module.dependentPaths.map((p) => toAbsolute(p)),
39
+ moduleDependencies: module.moduleDependencies,
40
+ },
41
+ ];
42
+ }),
43
+ );
44
+ };
45
+
46
+ const initialDependencyGraph = convertPathsToAbsolute({
47
+ '../../../../package.json': {
48
+ dependencyPaths: [],
49
+ dependentPaths: ['../../packageJson.ts'],
50
+ moduleDependencies: [],
51
+ path: '../../../../package.json',
52
+ },
53
+ 'create-dependency-graph.ts': {
54
+ path: 'create-dependency-graph.ts',
55
+ dependencyPaths: [
56
+ '../start-dev-server.ts',
57
+ 'get-imported-modules.ts',
58
+ 'resolve-path-aliases.ts',
59
+ ],
60
+ dependentPaths: [
61
+ 'create-dependency-graph.spec.ts',
62
+ 'setup-hot-reloading.ts',
63
+ ],
64
+ moduleDependencies: ['node:fs', 'node:path', 'chokidar/handler.js'],
65
+ },
66
+ '../../get-preview-server-location.ts': {
67
+ dependencyPaths: ['../../packageJson.ts'],
68
+ dependentPaths: ['../../preview/start-dev-server.ts'],
69
+ moduleDependencies: ['node:path', 'node:url', 'jiti', 'nypm', 'prompts'],
70
+ path: '../../get-preview-server-location.ts',
71
+ },
72
+ '../../packageJson.ts': {
73
+ dependencyPaths: ['../../../../package.json'],
74
+ dependentPaths: [
75
+ '../../get-preview-server-location.ts',
76
+ '../../preview/start-dev-server.ts',
77
+ ],
78
+ moduleDependencies: [],
79
+ path: '../../packageJson.ts',
80
+ },
81
+ 'create-dependency-graph.spec.ts': {
82
+ path: 'create-dependency-graph.spec.ts',
83
+ dependencyPaths: ['create-dependency-graph.ts'],
84
+ dependentPaths: [],
85
+ moduleDependencies: ['node:fs', 'node:path'],
86
+ },
87
+ '../get-env-variables-for-preview-app.ts': {
88
+ dependencyPaths: ['../../preview/start-dev-server.ts'],
89
+ dependentPaths: ['../../preview/start-dev-server.ts'],
90
+ moduleDependencies: ['node:path'],
91
+ path: '../../preview/get-env-variables-for-preview-app.ts',
92
+ },
93
+ './test/some-file.ts': {
94
+ dependencyPaths: [],
95
+ dependentPaths: [],
96
+ moduleDependencies: [],
97
+ path: '/home/gabriel/Projects/Resend/react-email/packages/react-email/src/cli/utils/preview/hot-reloading/test/some-file.ts',
98
+ },
99
+ 'resolve-path-aliases.ts': {
100
+ path: 'resolve-path-aliases.ts',
101
+ dependentPaths: [
102
+ 'create-dependency-graph.ts',
103
+ 'resolve-path-aliases.spec.ts',
104
+ ],
105
+ dependencyPaths: [],
106
+ moduleDependencies: ['node:path', 'tsconfig-paths'],
107
+ },
108
+ 'resolve-path-aliases.spec.ts': {
109
+ path: 'resolve-path-aliases.spec.ts',
110
+ dependencyPaths: ['resolve-path-aliases.ts'],
111
+ dependentPaths: [],
112
+ moduleDependencies: ['node:path'],
113
+ },
114
+ 'get-imported-modules.ts': {
115
+ path: 'get-imported-modules',
116
+ dependentPaths: [
117
+ 'create-dependency-graph.ts',
118
+ 'get-imported-modules.spec.ts',
119
+ ],
120
+ dependencyPaths: [],
121
+ moduleDependencies: ['@babel/parser', '@babel/traverse'],
122
+ },
123
+ 'get-imported-modules.spec.ts': {
124
+ path: 'get-imported-modules.spec.ts',
125
+ dependencyPaths: ['get-imported-modules.ts'],
126
+ dependentPaths: [],
127
+ moduleDependencies: ['node:fs'],
128
+ },
129
+ 'setup-hot-reloading.ts': {
130
+ path: 'setup-hot-reloading.ts',
131
+ dependencyPaths: [
132
+ '../../types/hot-reload-change.ts',
133
+ 'create-dependency-graph.ts',
134
+ ],
135
+ dependentPaths: [],
136
+ moduleDependencies: [
137
+ 'node:http',
138
+ 'node:path',
139
+ 'chokidar',
140
+ 'debounce',
141
+ 'socket.io',
142
+ ],
143
+ },
144
+ '../start-dev-server.ts': {
145
+ dependencyPaths: [
146
+ '../../register-spinner-autostopping.ts',
147
+ '../../get-preview-server-location.ts',
148
+ '../../packageJson.ts',
149
+ '../../preview/get-env-variables-for-preview-app.ts',
150
+ '../../preview/serve-static-file.ts',
151
+ ],
152
+ path: '../start-dev-server.ts',
153
+ dependentPaths: [
154
+ '../../preview/get-env-variables-for-preview-app.ts',
155
+ 'create-dependency-graph.ts',
156
+ ],
157
+ moduleDependencies: [
158
+ 'node:http',
159
+ 'node:path',
160
+ 'node:url',
161
+ 'chalk',
162
+ 'jiti',
163
+ 'log-symbols',
164
+ 'ora',
165
+ ],
166
+ },
167
+ '../../preview/serve-static-file.ts': {
168
+ dependencyPaths: [],
169
+ dependentPaths: ['../../preview/start-dev-server.ts'],
170
+ moduleDependencies: [
171
+ 'node:fs',
172
+ 'node:http',
173
+ 'node:path',
174
+ 'node:url',
175
+ 'mime-types',
176
+ ],
177
+ path: '../../preview/serve-static-file.ts',
178
+ },
179
+ '../../register-spinner-autostopping.ts': {
180
+ dependencyPaths: [],
181
+ dependentPaths: ['../../preview/start-dev-server.ts'],
182
+ moduleDependencies: ['log-symbols', 'ora'],
183
+ path: '../../register-spinner-autostopping.ts',
184
+ },
185
+ '../../types/hot-reload-event.ts': {
186
+ dependencyPaths: [],
187
+ dependentPaths: ['../../types/hot-reload-change.ts'],
188
+ moduleDependencies: ['chokidar/handler.js'],
189
+ path: '../../types/hot-reload-event.ts',
190
+ },
191
+ '../../types/hot-reload-change.ts': {
192
+ path: '../../types/hot-reload-change.ts',
193
+ dependencyPaths: ['../../types/hot-reload-event.ts'],
194
+ dependentPaths: ['setup-hot-reloading.ts'],
195
+ moduleDependencies: [],
196
+ },
197
+ } satisfies DependencyGraph);
198
+
199
+ expect(
200
+ dependencyGraph,
201
+ 'the initial value for the dependency graph should work with the directory of this testing file',
202
+ ).toEqual(initialDependencyGraph);
203
+
204
+ await fs.writeFile(
205
+ pathToFileForTestingDependencyGraph,
206
+ `
207
+ import {} from './setup-hot-reloading';
208
+ import {} from './get-imported-modules';
209
+ import {} from './create-dependency-graph.ts';
210
+ `,
211
+ 'utf8',
212
+ );
213
+ await updateDependencyGraph('add', pathToFileForTestingDependencyGraph);
214
+ expect(
215
+ dependencyGraph[pathToFileForTestingDependencyGraph],
216
+ 'added file to have proper dependency paths',
217
+ ).toEqual({
218
+ path: pathToFileForTestingDependencyGraph,
219
+ dependentPaths: [],
220
+ dependencyPaths: [
221
+ toAbsolute('setup-hot-reloading.ts'),
222
+ toAbsolute('get-imported-modules.ts'),
223
+ toAbsolute('create-dependency-graph.ts'),
224
+ ],
225
+ moduleDependencies: [],
226
+ } satisfies DependencyGraph[number]);
227
+ expect(
228
+ dependencyGraph[toAbsolute('setup-hot-reloading.ts')]?.dependentPaths,
229
+ ).toContain(pathToFileForTestingDependencyGraph);
230
+ expect(
231
+ dependencyGraph[toAbsolute('get-imported-modules.ts')]?.dependentPaths,
232
+ ).toContain(pathToFileForTestingDependencyGraph);
233
+ expect(
234
+ dependencyGraph[toAbsolute('create-dependency-graph.ts')]?.dependentPaths,
235
+ ).toContain(pathToFileForTestingDependencyGraph);
236
+
237
+ await fs.writeFile(
238
+ pathToFileForTestingDependencyGraph,
239
+ `
240
+ import {} from './setup-hot-reloading';
241
+ import {} from './create-dependency-graph.ts';
242
+ `,
243
+ 'utf8',
244
+ );
245
+ await updateDependencyGraph('change', pathToFileForTestingDependencyGraph);
246
+ expect(
247
+ dependencyGraph[pathToFileForTestingDependencyGraph],
248
+ 'changed file to have updated dependencyPaths',
249
+ ).toEqual({
250
+ path: pathToFileForTestingDependencyGraph,
251
+ dependentPaths: [],
252
+ dependencyPaths: [
253
+ toAbsolute('setup-hot-reloading.ts'),
254
+ toAbsolute('create-dependency-graph.ts'),
255
+ ],
256
+ moduleDependencies: [],
257
+ } satisfies DependencyGraph[number]);
258
+ expect(
259
+ dependencyGraph[toAbsolute('setup-hot-reloading.ts')]?.dependentPaths,
260
+ ).toContain(pathToFileForTestingDependencyGraph);
261
+ expect(
262
+ dependencyGraph[toAbsolute('get-imported-modules.ts')]?.dependentPaths,
263
+ 'when removing dependency on a file, the dependency should have its dependents updated to not have the testing file again',
264
+ ).not.toContain(pathToFileForTestingDependencyGraph);
265
+ expect(
266
+ dependencyGraph[toAbsolute('create-dependency-graph.ts')]?.dependentPaths,
267
+ ).toContain(pathToFileForTestingDependencyGraph);
268
+
269
+ await fs.rm(pathToFileForTestingDependencyGraph);
270
+ await updateDependencyGraph('unlink', pathToFileForTestingDependencyGraph);
271
+ expect(dependencyGraph[pathToFileForTestingDependencyGraph]).toBeUndefined();
272
+ expect(
273
+ dependencyGraph[toAbsolute('setup-hot-reloading.ts')]?.dependentPaths,
274
+ "should remove itself from dependents once it's unlinked",
275
+ ).not.toContain(pathToFileForTestingDependencyGraph);
276
+ expect(
277
+ dependencyGraph[toAbsolute('get-imported-modules.ts')]?.dependentPaths,
278
+ "should remove itself from dependents once it's unlinked",
279
+ ).not.toContain(pathToFileForTestingDependencyGraph);
280
+ expect(
281
+ dependencyGraph[toAbsolute('create-dependency-graph.ts')]?.dependentPaths,
282
+ "should remove itself from dependents once it's unlinked",
283
+ ).not.toContain(pathToFileForTestingDependencyGraph);
284
+ });
@@ -0,0 +1,321 @@
1
+ import { existsSync, promises as fs, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import type { EventName } from 'chokidar/handler.js';
4
+ import { isDev } from '../start-dev-server.js';
5
+ import { getImportedModules } from './get-imported-modules.js';
6
+ import { resolvePathAliases } from './resolve-path-aliases.js';
7
+
8
+ interface Module {
9
+ path: string;
10
+
11
+ dependencyPaths: string[];
12
+ dependentPaths: string[];
13
+
14
+ moduleDependencies: string[];
15
+ }
16
+
17
+ export type DependencyGraph = Record</* path to module */ string, Module>;
18
+
19
+ const readAllFilesInsideDirectory = async (directory: string) => {
20
+ let allFilePaths: string[] = [];
21
+
22
+ const topLevelDirents = await fs.readdir(directory, { withFileTypes: true });
23
+
24
+ for await (const dirent of topLevelDirents) {
25
+ const pathToDirent = path.join(directory, dirent.name);
26
+ if (dirent.isDirectory()) {
27
+ allFilePaths = allFilePaths.concat(
28
+ await readAllFilesInsideDirectory(pathToDirent),
29
+ );
30
+ } else {
31
+ allFilePaths.push(pathToDirent);
32
+ }
33
+ }
34
+
35
+ return allFilePaths;
36
+ };
37
+
38
+ const isJavascriptModule = (filePath: string) => {
39
+ const extensionName = path.extname(filePath);
40
+
41
+ return ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'].includes(extensionName);
42
+ };
43
+
44
+ const checkFileExtensionsUntilItExists = (
45
+ pathWithoutExtension: string,
46
+ ): string | undefined => {
47
+ if (existsSync(`${pathWithoutExtension}.ts`)) {
48
+ return `${pathWithoutExtension}.ts`;
49
+ }
50
+
51
+ if (existsSync(`${pathWithoutExtension}.tsx`)) {
52
+ return `${pathWithoutExtension}.tsx`;
53
+ }
54
+
55
+ if (existsSync(`${pathWithoutExtension}.js`)) {
56
+ return `${pathWithoutExtension}.js`;
57
+ }
58
+
59
+ if (existsSync(`${pathWithoutExtension}.jsx`)) {
60
+ return `${pathWithoutExtension}.jsx`;
61
+ }
62
+
63
+ if (existsSync(`${pathWithoutExtension}.mjs`)) {
64
+ return `${pathWithoutExtension}.mjs`;
65
+ }
66
+
67
+ if (existsSync(`${pathWithoutExtension}.cjs`)) {
68
+ return `${pathWithoutExtension}.cjs`;
69
+ }
70
+ };
71
+
72
+ /**
73
+ * Creates a stateful dependency graph that is structured in a way that you can get
74
+ * the dependents of a module from its path.
75
+ *
76
+ * Stateful in the sense that it provides a `getter` and an "`updater`". The updater
77
+ * will receive changes to the files, that can be perceived through some file watching mechanism,
78
+ * so that it doesn't need to recompute the entire dependency graph but only the parts changed.
79
+ */
80
+ export const createDependencyGraph = async (directory: string) => {
81
+ const filePaths = await readAllFilesInsideDirectory(directory);
82
+ const modulePaths = filePaths.filter(isJavascriptModule);
83
+ const graph: DependencyGraph = Object.fromEntries(
84
+ modulePaths.map((path) => [
85
+ path,
86
+ {
87
+ path,
88
+ dependencyPaths: [],
89
+ dependentPaths: [],
90
+ moduleDependencies: [],
91
+ },
92
+ ]),
93
+ );
94
+
95
+ const getDependencyPaths = async (filePath: string) => {
96
+ const contents = await fs.readFile(filePath, 'utf8');
97
+ const importedPaths = isJavascriptModule(filePath)
98
+ ? resolvePathAliases(getImportedModules(contents), path.dirname(filePath))
99
+ : [];
100
+ const importedPathsRelativeToDirectory = importedPaths.map(
101
+ (dependencyPath) => {
102
+ const isModulePath = !dependencyPath.startsWith('.');
103
+
104
+ /*
105
+ path.isAbsolute will return false if the path looks like JavaScript module imports
106
+ e.g. path.isAbsolute('react-dom/server') will return false, but for our purposes this
107
+ path is not a relative one.
108
+ */
109
+ if (isModulePath || path.isAbsolute(dependencyPath)) {
110
+ return dependencyPath;
111
+ }
112
+
113
+ let pathToDependencyFromDirectory = path.resolve(
114
+ /*
115
+ path.resolve resolves paths differently from what imports on javascript do.
116
+
117
+ So if we wouldn't do this, for an email at "/path/to/email.tsx" with a dependency path of "./other-email"
118
+ would end up going into /path/to/email.tsx/other-email instead of /path/to/other-email which is the
119
+ one the import is meant to go to
120
+ */
121
+ path.dirname(filePath),
122
+ dependencyPath,
123
+ );
124
+
125
+ let isDirectory = false;
126
+ try {
127
+ // will throw if the the file is not existent
128
+ isDirectory = statSync(pathToDependencyFromDirectory).isDirectory();
129
+ } catch (_) {}
130
+ if (isDirectory) {
131
+ const pathToSubDirectory = pathToDependencyFromDirectory;
132
+ const pathWithExtension = checkFileExtensionsUntilItExists(
133
+ `${pathToSubDirectory}/index`,
134
+ );
135
+ if (pathWithExtension) {
136
+ pathToDependencyFromDirectory = pathWithExtension;
137
+ } else if (isDev) {
138
+ // only warn about this on development as it is probably going to be irrelevant otherwise
139
+ console.warn(
140
+ `Could not find index file for directory at ${pathToDependencyFromDirectory}. This is probably going to cause issues with both hot reloading and your code.`,
141
+ );
142
+ }
143
+ }
144
+
145
+ const extension = path.extname(pathToDependencyFromDirectory);
146
+ const pathWithEnsuredExtension = (() => {
147
+ if (
148
+ extension.length > 0 &&
149
+ existsSync(pathToDependencyFromDirectory)
150
+ ) {
151
+ return pathToDependencyFromDirectory;
152
+ }
153
+ return checkFileExtensionsUntilItExists(
154
+ pathToDependencyFromDirectory.replace(extension, ''),
155
+ );
156
+ })();
157
+
158
+ if (pathWithEnsuredExtension) {
159
+ pathToDependencyFromDirectory = pathWithEnsuredExtension;
160
+ } else if (isDev) {
161
+ // only warn about this on development as it is probably going to be irrelevant otherwise
162
+ console.warn(
163
+ `Could not find file at ${pathToDependencyFromDirectory}`,
164
+ );
165
+ }
166
+
167
+ return pathToDependencyFromDirectory;
168
+ },
169
+ );
170
+
171
+ const moduleDependencies = importedPathsRelativeToDirectory.filter(
172
+ (dependencyPath) =>
173
+ !dependencyPath.startsWith('.') && !path.isAbsolute(dependencyPath),
174
+ );
175
+
176
+ const nonNodeModuleImportPathsRelativeToDirectory =
177
+ importedPathsRelativeToDirectory.filter(
178
+ (dependencyPath) =>
179
+ dependencyPath.startsWith('.') || path.isAbsolute(dependencyPath),
180
+ );
181
+
182
+ return {
183
+ dependencyPaths: nonNodeModuleImportPathsRelativeToDirectory,
184
+ moduleDependencies,
185
+ };
186
+ };
187
+
188
+ const updateModuleDependenciesInGraph = async (moduleFilePath: string) => {
189
+ if (graph[moduleFilePath] === undefined) {
190
+ graph[moduleFilePath] = {
191
+ path: moduleFilePath,
192
+ dependencyPaths: [],
193
+ dependentPaths: [],
194
+ moduleDependencies: [],
195
+ };
196
+ }
197
+
198
+ const { moduleDependencies, dependencyPaths: newDependencyPaths } =
199
+ await getDependencyPaths(moduleFilePath);
200
+
201
+ graph[moduleFilePath].moduleDependencies = moduleDependencies;
202
+
203
+ // we go through these to remove the ones that don't exist anymore
204
+ for (const dependencyPath of graph[moduleFilePath].dependencyPaths) {
205
+ // Looping through only the ones that were on the dependencyPaths but are not
206
+ // in the newDependencyPaths
207
+ if (newDependencyPaths.includes(dependencyPath)) continue;
208
+
209
+ const dependencyModule = graph[dependencyPath];
210
+ if (dependencyModule !== undefined) {
211
+ dependencyModule.dependentPaths =
212
+ dependencyModule.dependentPaths.filter(
213
+ (dependentPath) => dependentPath !== moduleFilePath,
214
+ );
215
+ }
216
+ }
217
+
218
+ graph[moduleFilePath].dependencyPaths = newDependencyPaths;
219
+
220
+ for await (const dependencyPath of newDependencyPaths) {
221
+ if (graph[dependencyPath] === undefined) {
222
+ /*
223
+ This import path might have not been initialized as it can be outside
224
+ of the original directory we looked into.
225
+ */
226
+ await updateModuleDependenciesInGraph(dependencyPath);
227
+ }
228
+
229
+ const dependencyModule = graph[dependencyPath];
230
+
231
+ if (dependencyModule === undefined) {
232
+ throw new Error(
233
+ `Loading the dependency path ${dependencyPath} did not initialize it at all. This is a bug in React Email.`,
234
+ );
235
+ }
236
+
237
+ if (!dependencyModule.dependentPaths.includes(moduleFilePath)) {
238
+ dependencyModule.dependentPaths.push(moduleFilePath);
239
+ }
240
+ }
241
+ };
242
+
243
+ for (const filePath of modulePaths) {
244
+ await updateModuleDependenciesInGraph(filePath);
245
+ }
246
+
247
+ const removeModuleFromGraph = (filePath: string) => {
248
+ const module = graph[filePath];
249
+ if (module) {
250
+ for (const dependencyPath of module.dependencyPaths) {
251
+ if (graph[dependencyPath]) {
252
+ graph[dependencyPath]!.dependentPaths = graph[
253
+ dependencyPath
254
+ ]!.dependentPaths.filter(
255
+ (dependentPath) => dependentPath !== filePath,
256
+ );
257
+ }
258
+ }
259
+ delete graph[filePath];
260
+ }
261
+ };
262
+
263
+ return [
264
+ graph,
265
+ async (event: EventName, pathToModified: string) => {
266
+ switch (event) {
267
+ case 'change':
268
+ if (isJavascriptModule(pathToModified)) {
269
+ await updateModuleDependenciesInGraph(pathToModified);
270
+ }
271
+ break;
272
+ case 'add':
273
+ if (isJavascriptModule(pathToModified)) {
274
+ await updateModuleDependenciesInGraph(pathToModified);
275
+ }
276
+ break;
277
+ case 'addDir': {
278
+ const filesInsideAddedDirectory =
279
+ await readAllFilesInsideDirectory(pathToModified);
280
+ const modulesInsideAddedDirectory =
281
+ filesInsideAddedDirectory.filter(isJavascriptModule);
282
+ for await (const filePath of modulesInsideAddedDirectory) {
283
+ await updateModuleDependenciesInGraph(filePath);
284
+ }
285
+ break;
286
+ }
287
+ case 'unlink':
288
+ if (isJavascriptModule(pathToModified)) {
289
+ removeModuleFromGraph(pathToModified);
290
+ }
291
+ break;
292
+ case 'unlinkDir': {
293
+ const filesInsideDeletedDirectory =
294
+ await readAllFilesInsideDirectory(pathToModified);
295
+ const modulesInsideDeletedDirectory =
296
+ filesInsideDeletedDirectory.filter(isJavascriptModule);
297
+ for await (const filePath of modulesInsideDeletedDirectory) {
298
+ removeModuleFromGraph(filePath);
299
+ }
300
+ break;
301
+ }
302
+ }
303
+ },
304
+ {
305
+ resolveDependentsOf: function resolveDependentsOf(pathToModule: string) {
306
+ const moduleEntry = graph[pathToModule];
307
+ const dependentPaths: Array<string> = [];
308
+
309
+ if (moduleEntry) {
310
+ for (const dependentPath of moduleEntry.dependentPaths) {
311
+ const dependentsOfDependent = resolveDependentsOf(dependentPath);
312
+ dependentPaths.push(...dependentsOfDependent);
313
+ dependentPaths.push(dependentPath);
314
+ }
315
+ }
316
+
317
+ return dependentPaths;
318
+ },
319
+ },
320
+ ] as const;
321
+ };