Skip to content

Commit 5070bdd

Browse files
committed
feat(react-email): TypeScript's path aliases support for hot reloading (#2215)
1 parent 9111816 commit 5070bdd

File tree

8 files changed

+99
-4
lines changed

8 files changed

+99
-4
lines changed

packages/react-email/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
"next": "^15.3.1",
4343
"normalize-path": "^3.0.0",
4444
"ora": "^8.0.0",
45-
"socket.io": "^4.8.1"
45+
"socket.io": "^4.8.1",
46+
"tsconfig-paths": "4.2.0"
4647
},
4748
"devDependencies": {
4849
"@babel/core": "7.26.10",

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

+26-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ test('createDependencyGraph()', async () => {
5252
},
5353
'create-dependency-graph.ts': {
5454
path: 'create-dependency-graph.ts',
55-
dependencyPaths: ['../start-dev-server.ts', 'get-imported-modules.ts'],
55+
dependencyPaths: [
56+
'../start-dev-server.ts',
57+
'get-imported-modules.ts',
58+
'resolve-path-aliases.ts',
59+
],
5660
dependentPaths: [
5761
'create-dependency-graph.spec.ts',
5862
'setup-hot-reloading.ts',
@@ -71,6 +75,27 @@ test('createDependencyGraph()', async () => {
7175
moduleDependencies: ['node:path'],
7276
path: '../../../utils/preview/get-env-variables-for-preview-app.ts',
7377
},
78+
'./test/some-file.ts': {
79+
dependencyPaths: [],
80+
dependentPaths: [],
81+
moduleDependencies: [],
82+
path: '/home/gabriel/Projects/Resend/react-email/packages/react-email/src/cli/utils/preview/hot-reloading/test/some-file.ts',
83+
},
84+
'resolve-path-aliases.ts': {
85+
path: 'resolve-path-aliases.ts',
86+
dependentPaths: [
87+
'create-dependency-graph.ts',
88+
'resolve-path-aliases.spec.ts',
89+
],
90+
dependencyPaths: [],
91+
moduleDependencies: ['node:path', 'tsconfig-paths'],
92+
},
93+
'resolve-path-aliases.spec.ts': {
94+
path: 'resolve-path-aliases.spec.ts',
95+
dependencyPaths: ['resolve-path-aliases.ts'],
96+
dependentPaths: [],
97+
moduleDependencies: ['node:path'],
98+
},
7499
'get-imported-modules.ts': {
75100
path: 'get-imported-modules',
76101
dependentPaths: [

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from 'node:path';
33
import type { EventName } from 'chokidar/handler';
44
import { isDev } from '../start-dev-server';
55
import { getImportedModules } from './get-imported-modules';
6+
import { resolvePathAliases } from './resolve-path-aliases';
67

78
interface Module {
89
path: string;
@@ -93,9 +94,8 @@ export const createDependencyGraph = async (directory: string) => {
9394

9495
const getDependencyPaths = async (filePath: string) => {
9596
const contents = await fs.readFile(filePath, 'utf8');
96-
9797
const importedPaths = isJavascriptModule(filePath)
98-
? getImportedModules(contents)
98+
? resolvePathAliases(getImportedModules(contents), path.dirname(filePath))
9999
: [];
100100
const importedPathsRelativeToDirectory = importedPaths.map(
101101
(dependencyPath) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import path from 'node:path';
2+
import { resolvePathAliases } from './resolve-path-aliases';
3+
4+
test('resolveImports()', async () => {
5+
expect(
6+
resolvePathAliases(
7+
['@/some-file'],
8+
path.resolve(import.meta.dirname, './test'),
9+
),
10+
).toEqual(['./some-file']);
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import path from 'node:path';
2+
import { createMatchPath, loadConfig } from 'tsconfig-paths';
3+
4+
export const resolvePathAliases = (
5+
importPaths: string[],
6+
projectPath: string,
7+
) => {
8+
const configLoadResult = loadConfig(projectPath);
9+
10+
if (configLoadResult.resultType === 'success') {
11+
const matchPath = createMatchPath(
12+
configLoadResult.absoluteBaseUrl,
13+
configLoadResult.paths,
14+
);
15+
return importPaths.map((importedPath) => {
16+
const unaliasedPath = matchPath(importedPath, undefined, undefined, [
17+
'.tsx',
18+
'.ts',
19+
'.js',
20+
'.jsx',
21+
'.cjs',
22+
'.mjs',
23+
]);
24+
if (unaliasedPath) {
25+
return `./${path.relative(projectPath, unaliasedPath)}`;
26+
}
27+
return importedPath;
28+
});
29+
}
30+
31+
return importPaths;
32+
};

packages/react-email/src/cli/utils/preview/hot-reloading/test/some-file.ts

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"compilerOptions": {
3+
"paths": {
4+
"@/*": ["./*"]
5+
}
6+
},
7+
"include": ["**/*.ts", "**/*.tsx"]
8+
}

pnpm-lock.yaml

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)