Skip to content

Commit aae2f59

Browse files
authored
fix(react-email): Dependencies outside dependency graph directory not being resolved fully (#2093)
1 parent b4b2373 commit aae2f59

File tree

3 files changed

+86
-28
lines changed

3 files changed

+86
-28
lines changed

.changeset/eleven-plums-type.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-email": patch
3+
---
4+
5+
Ensure dependencies outside emails directory are completely resolved

packages/react-email/src/cli/utils/preview/hot-reloading/create-dependency-graph.spec.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ test('createDependencyGraph()', async () => {
3939
};
4040

4141
const initialDependencyGraph = convertPathsToAbsolute({
42+
'../../../../../package.json': {
43+
dependencyPaths: [],
44+
dependentPaths: ['../start-dev-server.ts'],
45+
moduleDependencies: [],
46+
path: '../../../../../package.json',
47+
},
4248
'create-dependency-graph.ts': {
4349
path: 'create-dependency-graph.ts',
4450
dependencyPaths: ['../start-dev-server.ts', 'get-imported-modules.ts'],
@@ -54,6 +60,12 @@ test('createDependencyGraph()', async () => {
5460
dependentPaths: [],
5561
moduleDependencies: ['node:fs', 'node:path'],
5662
},
63+
'../../../utils/preview/get-env-variables-for-preview-app.ts': {
64+
dependencyPaths: ['../../../utils/preview/start-dev-server.ts'],
65+
dependentPaths: ['../../../utils/preview/start-dev-server.ts'],
66+
moduleDependencies: ['node:path'],
67+
path: '../../../utils/preview/get-env-variables-for-preview-app.ts',
68+
},
5769
'get-imported-modules.ts': {
5870
path: 'get-imported-modules',
5971
dependentPaths: [
@@ -85,14 +97,54 @@ test('createDependencyGraph()', async () => {
8597
],
8698
},
8799
'../start-dev-server.ts': {
100+
dependencyPaths: [
101+
'../../../../../package.json',
102+
'../../../../utils/register-spinner-autostopping.ts',
103+
'../../../utils/preview/get-env-variables-for-preview-app.ts',
104+
'../../../utils/preview/serve-static-file.ts',
105+
],
88106
path: '../start-dev-server.ts',
107+
dependentPaths: [
108+
'../../../utils/preview/get-env-variables-for-preview-app.ts',
109+
'create-dependency-graph.ts',
110+
],
111+
moduleDependencies: [
112+
'node:http',
113+
'node:path',
114+
'node:url',
115+
'chalk',
116+
'log-symbols',
117+
'next',
118+
'ora',
119+
],
120+
},
121+
'../../../utils/preview/serve-static-file.ts': {
89122
dependencyPaths: [],
90-
dependentPaths: ['create-dependency-graph.ts'],
91-
moduleDependencies: [],
123+
dependentPaths: ['../../../utils/preview/start-dev-server.ts'],
124+
moduleDependencies: [
125+
'node:fs',
126+
'node:http',
127+
'node:path',
128+
'node:url',
129+
'mime-types',
130+
],
131+
path: '../../../utils/preview/serve-static-file.ts',
132+
},
133+
'../../../../utils/register-spinner-autostopping.ts': {
134+
dependencyPaths: [],
135+
dependentPaths: ['../../../utils/preview/start-dev-server.ts'],
136+
moduleDependencies: ['log-symbols', 'ora'],
137+
path: '../../../../utils/register-spinner-autostopping.ts',
138+
},
139+
'../../../../utils/types/hot-reload-event.ts': {
140+
dependencyPaths: [],
141+
dependentPaths: ['../../../../utils/types/hot-reload-change.ts'],
142+
moduleDependencies: ['chokidar/handler'],
143+
path: '../../../../utils/types/hot-reload-event.ts',
92144
},
93145
'../../../../utils/types/hot-reload-change.ts': {
94146
path: '../../../../utils/types/hot-reload-change.ts',
95-
dependencyPaths: [],
147+
dependencyPaths: ['../../../../utils/types/hot-reload-event.ts'],
96148
dependentPaths: ['setup-hot-reloading.ts'],
97149
moduleDependencies: [],
98150
},

packages/react-email/src/cli/utils/preview/hot-reloading/create-dependency-graph.ts

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,22 @@ export const createDependencyGraph = async (directory: string) => {
184184
};
185185

186186
const updateModuleDependenciesInGraph = async (moduleFilePath: string) => {
187-
const module = graph[moduleFilePath] ?? {
188-
path: moduleFilePath,
189-
dependencyPaths: [],
190-
dependentPaths: [],
191-
moduleDependencies: [],
192-
};
187+
if (graph[moduleFilePath] === undefined) {
188+
graph[moduleFilePath] = {
189+
path: moduleFilePath,
190+
dependencyPaths: [],
191+
dependentPaths: [],
192+
moduleDependencies: [],
193+
};
194+
}
193195

194196
const { moduleDependencies, dependencyPaths: newDependencyPaths } =
195197
await getDependencyPaths(moduleFilePath);
196198

197-
module.moduleDependencies = moduleDependencies;
199+
graph[moduleFilePath].moduleDependencies = moduleDependencies;
198200

199201
// we go through these to remove the ones that don't exist anymore
200-
for (const dependencyPath of module.dependencyPaths) {
202+
for (const dependencyPath of graph[moduleFilePath].dependencyPaths) {
201203
// Looping through only the ones that were on the dependencyPaths but are not
202204
// in the newDependencyPaths
203205
if (newDependencyPaths.includes(dependencyPath)) continue;
@@ -211,30 +213,29 @@ export const createDependencyGraph = async (directory: string) => {
211213
}
212214
}
213215

214-
module.dependencyPaths = newDependencyPaths;
216+
graph[moduleFilePath].dependencyPaths = newDependencyPaths;
215217

216-
for (const dependencyPath of newDependencyPaths) {
217-
const dependencyModule = graph[dependencyPath];
218-
if (
219-
dependencyModule !== undefined &&
220-
!dependencyModule.dependentPaths.includes(moduleFilePath)
221-
) {
222-
dependencyModule.dependentPaths.push(moduleFilePath);
223-
} else {
218+
for await (const dependencyPath of newDependencyPaths) {
219+
if (graph[dependencyPath] === undefined) {
224220
/*
225221
This import path might have not been initialized as it can be outside
226222
of the original directory we looked into.
227223
*/
228-
graph[dependencyPath] = {
229-
path: dependencyPath,
230-
moduleDependencies: [],
231-
dependencyPaths: [],
232-
dependentPaths: [moduleFilePath],
233-
};
224+
await updateModuleDependenciesInGraph(dependencyPath);
234225
}
235-
}
236226

237-
graph[moduleFilePath] = module;
227+
const dependencyModule = graph[dependencyPath];
228+
229+
if (dependencyModule === undefined) {
230+
throw new Error(
231+
`Loading the dependency path ${dependencyPath} did not initialize it at all. This is a bug in React Email.`,
232+
);
233+
}
234+
235+
if (!dependencyModule.dependentPaths.includes(moduleFilePath)) {
236+
dependencyModule.dependentPaths.push(moduleFilePath);
237+
}
238+
}
238239
};
239240

240241
for (const filePath of modulePaths) {

0 commit comments

Comments
 (0)