1
1
import { TSESTree } from "@typescript-eslint/utils" ;
2
2
import { RuleContext } from "@typescript-eslint/utils/ts-eslint" ;
3
- import { readFileSync } from "fs" ;
3
+ import { existsSync , readFileSync } from "fs" ;
4
4
import path from "path" ;
5
5
6
6
function cleanTsConfig ( content : string ) {
@@ -17,45 +17,70 @@ function cleanTsConfig(content: string) {
17
17
) ;
18
18
}
19
19
20
+ function resolveTSAlias ( tsconfigpath : string , to : string , cwd : string ) {
21
+ const tsconfig = readFileSync ( tsconfigpath , "utf-8" ) ;
22
+ const aliases = JSON . parse ( cleanTsConfig ( tsconfig ) ) . compilerOptions
23
+ . paths as Record < string , string [ ] > ;
24
+
25
+ let res = Object . entries ( aliases )
26
+ // sorting by longest - most qualified - alias
27
+ . sort ( ( a , b ) => b [ 0 ] . length - a [ 0 ] . length )
28
+ . find (
29
+ ( [ key ] ) => to . startsWith ( key ) || to . startsWith ( key . replace ( / \* $ / , "" ) )
30
+ ) ;
31
+
32
+ if ( res ) {
33
+ let [ key , val ] = res ;
34
+ key = key . replace ( / \* $ / , "" ) ;
35
+ const firstVal = val [ 0 ] . replace ( / \* $ / , "" ) ;
36
+ to = to . replace ( key , firstVal ) ;
37
+ to = path . resolve ( cwd , to ) ;
38
+ }
39
+
40
+ return to ;
41
+ }
42
+
43
+ const codeExt = [ ".ts" , ".js" , ".tsx" , ".jsx" ] ;
44
+
45
+ function endsWithAny ( str : string , arr : string [ ] ) {
46
+ return arr . some ( ( ext ) => str . endsWith ( ext ) ) ;
47
+ }
48
+
20
49
export function getImportDeclarationPath (
21
50
context : RuleContext < string , unknown [ ] > ,
22
51
impt : TSESTree . ImportDeclaration
23
52
) {
24
53
const from = context . physicalFilename ;
25
54
let to = impt . source . value ;
26
55
27
- let ext = path . extname ( to ) ;
28
- if ( ext === "" ) {
29
- ext = path . extname ( from ) ;
30
- }
56
+ let res : string | null = null ;
31
57
32
58
if ( ! to . startsWith ( "." ) ) {
33
59
const project = context . parserOptions . project ;
34
60
if ( project ) {
35
- const tsconfig = readFileSync ( project . toString ( ) , "utf-8" ) ;
36
- const aliases = JSON . parse ( cleanTsConfig ( tsconfig ) ) . compilerOptions
37
- . paths as Record < string , string [ ] > ;
38
-
39
- let res = Object . entries ( aliases )
40
- // sorting by longest - most qualified - alias
41
- . sort ( ( a , b ) => b [ 0 ] . length - a [ 0 ] . length )
42
- . find (
43
- ( [ key ] ) => to . startsWith ( key ) || to . startsWith ( key . replace ( / \* $ / , "" ) )
44
- ) ;
45
-
46
- if ( res ) {
47
- let [ key , val ] = res ;
48
- key = key . replace ( / \* $ / , "" ) ;
49
- const firstVal = val [ 0 ] . replace ( / \* $ / , "" ) ;
50
- to = to . replace ( key , firstVal ) ;
51
- return path . resolve ( context . cwd , to + ext ) ;
52
- }
61
+ to = resolveTSAlias ( project . toString ( ) , to , context . cwd ) ;
62
+ }
63
+
64
+ if ( ! to . startsWith ( "." ) ) {
65
+ // no relative path and no TS alias,
66
+ // considering it as a node_module
67
+ return `./node_modules/${ to } ` ;
53
68
}
69
+ } else {
70
+ res = path . resolve ( path . dirname ( from ) , to ) ;
71
+ }
54
72
55
- // no relative path and no TS alias,
56
- // considering it as a node_module
57
- return `./node_modules/${ to } ` ;
73
+ if ( ! res ) throw new Error ( "Import path not resolved" ) ;
74
+
75
+ if ( ! endsWithAny ( res , codeExt ) ) {
76
+ res += path . extname ( from ) ;
77
+ }
78
+
79
+ if ( ! existsSync ( res ) ) {
80
+ if ( res . endsWith ( ".js" ) ) {
81
+ res = res . replace ( ".js" , ".ts" ) ;
82
+ }
58
83
}
59
84
60
- return path . resolve ( path . dirname ( from ) , to + ext ) ;
85
+ return res ;
61
86
}
0 commit comments