Skip to content

Commit 83b17d0

Browse files
authored
Merge pull request #16 from quentin-fox/main
allow resolving in tsconfig even when no paths
2 parents 6922d57 + 7f24eb9 commit 83b17d0

File tree

2 files changed

+75
-36
lines changed

2 files changed

+75
-36
lines changed

src/spec/resolveAliasedFilepath.spec.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('utils: resolveAliaedFilepath', () => {
4545
expect(result).toEqual(expected);
4646
});
4747

48-
it('returns null when "paths" is not set in the config', () => {
48+
it('returns null when "paths" is not set in the config and path does not match', () => {
4949
(lilconfigSync as jest.Mock).mockReturnValueOnce({
5050
search: () => ({
5151
config: {
@@ -57,6 +57,7 @@ describe('utils: resolveAliaedFilepath', () => {
5757
filepath: '/path/to/config',
5858
}),
5959
});
60+
(existsSync as jest.Mock).mockReturnValue(false);
6061
const result = resolveAliasedImport({
6162
location: '',
6263
importFilepath: '',
@@ -66,7 +67,29 @@ describe('utils: resolveAliaedFilepath', () => {
6667
expect(result).toEqual(expected);
6768
});
6869

69-
it('returns null when no alias matched import path', () => {
70+
it('returns resolved filepath when "paths" is not set in the config, and file exists', () => {
71+
(lilconfigSync as jest.Mock).mockReturnValueOnce({
72+
search: () => ({
73+
config: {
74+
compilerOptions: {
75+
baseUrl: './',
76+
// missing "paths"
77+
},
78+
},
79+
filepath: '/path/to/tsconfig.json',
80+
}),
81+
});
82+
(existsSync as jest.Mock).mockReturnValue(true);
83+
const result = resolveAliasedImport({
84+
location: '',
85+
importFilepath: 'src/styles/file.css',
86+
});
87+
const expected = '/path/to/src/styles/file.css';
88+
89+
expect(result).toEqual(expected);
90+
});
91+
92+
it('returns baseUrl-mapped path when no alias matched import path', () => {
7093
(lilconfigSync as jest.Mock).mockReturnValueOnce({
7194
search: () => ({
7295
config: {
@@ -84,7 +107,7 @@ describe('utils: resolveAliaedFilepath', () => {
84107
location: '',
85108
importFilepath: '@foo',
86109
});
87-
const expected = null;
110+
const expected = '/path/to/@foo';
88111

89112
expect(result).toEqual(expected);
90113
});

src/utils/resolveAliasedImport.ts

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,17 @@ const validate = {
1010
return false;
1111
}
1212

13-
for (const key in x) {
14-
const value =
15-
// @ts-expect-error: here "key" can be used to index object
16-
x[key];
17-
if (
18-
!Array.isArray(value) &&
13+
const paths = x as Record<string, unknown>;
14+
15+
const isValid = Object.values(paths).every(value => {
16+
return (
17+
Array.isArray(value) &&
1918
value.length > 0 &&
20-
!value.every(validate.string)
21-
) {
22-
return false;
23-
}
24-
}
19+
value.every(validate.string)
20+
);
21+
});
2522

26-
return true;
23+
return isValid;
2724
},
2825
};
2926

@@ -59,35 +56,54 @@ export const resolveAliasedImport = ({
5956
return null;
6057
}
6158

62-
const paths = config.config?.compilerOptions?.paths as void | TsconfigPaths;
63-
const baseUrl = config.config?.compilerOptions?.baseUrl as void | string;
59+
const paths: unknown = config.config?.compilerOptions?.paths;
60+
61+
const potentialBaseUrl: unknown = config.config?.compilerOptions?.baseUrl;
62+
6463
const configLocation = path.dirname(config.filepath);
6564

66-
if (!validate.string(baseUrl)) {
67-
return null;
68-
}
69-
if (!validate.tsconfigPaths(paths)) {
70-
return null;
71-
}
65+
if (validate.tsconfigPaths(paths)) {
66+
const baseUrl = validate.string(potentialBaseUrl)
67+
? potentialBaseUrl
68+
: '.';
7269

73-
for (const alias in paths) {
74-
const aliasRe = new RegExp(alias.replace('*', '(.+)'), '');
70+
for (const alias in paths) {
71+
const aliasRe = new RegExp(alias.replace('*', '(.+)'), '');
7572

76-
const aliasMatch = importFilepath.match(aliasRe);
73+
const aliasMatch = importFilepath.match(aliasRe);
7774

78-
if (aliasMatch == null) continue;
75+
if (aliasMatch == null) continue;
7976

80-
for (const potentialAliasLocation of paths[alias]) {
81-
const resolvedFileLocation = path.resolve(
82-
configLocation,
83-
baseUrl,
84-
potentialAliasLocation
85-
// "./utils/*" -> "./utils/style.module.css"
86-
.replace('*', aliasMatch[1]),
87-
);
77+
for (const potentialAliasLocation of paths[alias]) {
78+
const resolvedFileLocation = path.resolve(
79+
configLocation,
80+
baseUrl,
81+
potentialAliasLocation
82+
// "./utils/*" -> "./utils/style.module.css"
83+
.replace('*', aliasMatch[1]),
84+
);
85+
86+
if (!fs.existsSync(resolvedFileLocation)) continue;
8887

89-
if (!fs.existsSync(resolvedFileLocation)) continue;
88+
return resolvedFileLocation;
89+
}
90+
}
91+
}
9092

93+
// if paths is defined, but no paths match
94+
// then baseUrl will not fallback to "."
95+
// if not using paths to find an alias, baseUrl must be defined
96+
// so here we only try and resolve the file if baseUrl is explcitly set and valid
97+
// i.e. if no baseUrl is provided
98+
// then no imports relative to baseUrl on its own are allowed, only relative to paths
99+
if (validate.string(potentialBaseUrl)) {
100+
const resolvedFileLocation = path.resolve(
101+
configLocation,
102+
potentialBaseUrl,
103+
importFilepath,
104+
);
105+
106+
if (fs.existsSync(resolvedFileLocation)) {
91107
return resolvedFileLocation;
92108
}
93109
}

0 commit comments

Comments
 (0)