Skip to content

Commit 8c55450

Browse files
feat: new nonRelative option for resolving non-relative paths (#13)
If enabled, the plugin will resolve non-relative paths based on tsconfig's `baseUrl`, even if none of the `paths` are matched. Closes #12.
1 parent bd86b60 commit 8c55450

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

index.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,37 @@ import { Plugin } from 'rollup';
33
import { CompilerOptions, findConfigFile, nodeModuleNameResolver, parseConfigFileTextToJson, sys } from 'typescript';
44

55
export const typescriptPaths = ({
6-
tsConfigPath = findConfigFile('./', sys.fileExists),
76
absolute = true,
8-
transform,
7+
nonRelative = false,
98
preserveExtensions = false,
9+
tsConfigPath = findConfigFile('./', sys.fileExists),
10+
transform,
1011
}: Options = {}): Plugin => {
1112
const { compilerOptions, outDir } = getTsConfig(tsConfigPath);
1213

1314
return {
1415
name: 'resolve-typescript-paths',
1516
resolveId: (importee: string, importer?: string) => {
16-
if (typeof importer === 'undefined' || importee.startsWith('\0') || !compilerOptions.paths) {
17+
const enabled = Boolean(compilerOptions.paths || (compilerOptions.baseUrl && nonRelative));
18+
19+
if (typeof importer === 'undefined' || importee.startsWith('\0') || !enabled) {
1720
return null;
1821
}
1922

20-
const hasMatchingPath = Object.keys(compilerOptions.paths).some((path) =>
21-
new RegExp('^' + path.replace('*', '.+') + '$').test(importee),
22-
);
23+
const hasMatchingPath =
24+
!!compilerOptions.paths &&
25+
Object.keys(compilerOptions.paths).some((path) =>
26+
new RegExp('^' + path.replace('*', '.+') + '$').test(importee),
27+
);
2328

24-
if (!hasMatchingPath) {
29+
if (!hasMatchingPath && !nonRelative) {
2530
return null;
2631
}
2732

33+
if (importee.startsWith('.')) {
34+
return null; // never resolve relative modules, only non-relative
35+
}
36+
2837
const { resolvedModule } = nodeModuleNameResolver(importee, importer, compilerOptions, sys);
2938

3039
if (!resolvedModule) {
@@ -73,6 +82,15 @@ export interface Options {
7382
*/
7483
absolute?: boolean;
7584

85+
/**
86+
* Whether to resolve non-relative paths based on tsconfig's `baseUrl`, even
87+
* if none of the `paths` are matched; defaults to `false`.
88+
*
89+
* @see https://www.typescriptlang.org/docs/handbook/module-resolution.html#relative-vs-non-relative-module-imports
90+
* @see https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-url
91+
*/
92+
nonRelative?: boolean;
93+
7694
/**
7795
* Whether to preserve `.ts` and `.tsx` file extensions instead of having them
7896
* changed to `.js`; defaults to `false`.

test/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const plugin = typescriptPaths({ tsConfigPath: resolve(__dirname, 'tsconfig.json
1010

1111
const pluginNonAbs = typescriptPaths({ tsConfigPath: resolve(__dirname, 'tsconfig.json'), absolute: false });
1212

13+
const pluginNonRelative = typescriptPaths({ tsConfigPath: resolve(__dirname, 'tsconfig.json'), nonRelative: true });
14+
1315
const pluginTransform = typescriptPaths({ tsConfigPath: resolve(__dirname, 'tsconfig.json'), transform });
1416

1517
const pluginPreserveExtensions = typescriptPaths({
@@ -46,6 +48,12 @@ try {
4648
// doesn't accidentally resolve relative paths that also have an alias
4749
strictEqual(plugin.resolveId('../bar/foo', join(__dirname, 'foo', 'bar.ts')), null);
4850

51+
// skips non-relative paths unless enabled
52+
strictEqual(plugin.resolveId('foo/bar', ''), null);
53+
54+
// resolves non-relative from baseUrl even if no path is matched
55+
strictEqual(pluginNonRelative.resolveId('foo/bar', ''), join(__dirname, 'foo', 'bar.js'));
56+
4957
// resolves as a relative path with option `absolute: false`
5058
strictEqual(pluginNonAbs.resolveId('@foobar', ''), join('test', 'foo', 'bar.js'));
5159

0 commit comments

Comments
 (0)