eslint-config-typed 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugins/strict-dependencies/rules/resolve-import-path.d.mts +7 -1
- package/dist/plugins/strict-dependencies/rules/resolve-import-path.d.mts.map +1 -1
- package/dist/plugins/strict-dependencies/rules/resolve-import-path.mjs +28 -17
- package/dist/plugins/strict-dependencies/rules/resolve-import-path.mjs.map +1 -1
- package/package.json +2 -2
- package/src/plugins/strict-dependencies/rules/resolve-import-path.mts +45 -24
- package/src/plugins/strict-dependencies/rules/resolve-import-path.test.mts +133 -104
|
@@ -5,7 +5,13 @@ import * as ts from 'typescript';
|
|
|
5
5
|
*
|
|
6
6
|
* `readCompilerOptions` は tsconfig の compilerOptions を返す関数で、既定では
|
|
7
7
|
* カレントディレクトリの tsconfig.json を読む。テストが `typescript` を
|
|
8
|
-
*
|
|
8
|
+
* モジュールごと差し替えずにすむよう引数にしている。返す `paths` の値は
|
|
9
|
+
* カレントディレクトリからの相対パスとして扱う。
|
|
9
10
|
*/
|
|
10
11
|
export declare const resolveImportPath: (importPath: string, relativeFilePath: string | undefined, pathIndexMap: ReadonlyRecord<string, number>, readCompilerOptions?: () => ts.CompilerOptions | undefined) => string;
|
|
12
|
+
/**
|
|
13
|
+
* Reads the tsconfig.json found from `cwd` upward, with `paths` rewritten as
|
|
14
|
+
* relative to `cwd`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const readTsConfig: (cwd: string) => ts.CompilerOptions | undefined;
|
|
11
17
|
//# sourceMappingURL=resolve-import-path.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-import-path.d.mts","sourceRoot":"","sources":["../../../../src/plugins/strict-dependencies/rules/resolve-import-path.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve-import-path.d.mts","sourceRoot":"","sources":["../../../../src/plugins/strict-dependencies/rules/resolve-import-path.mts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAIjC;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,eAChB,MAAM,oBACA,MAAM,GAAG,SAAS,gBACtB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,wBACvB,MAAM,EAAE,CAAC,eAAe,GAAG,SAAS,KAExD,MAmDF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAS,MAAM,KAAG,EAAE,CAAC,eAAe,GAAG,SAoD/D,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
|
-
import { Arr, isNonEmptyString, mapNullable } from 'ts-data-forge';
|
|
2
|
+
import { Arr, isNonEmptyString, isString, mapNullable, Obj, } from 'ts-data-forge';
|
|
3
3
|
import * as ts from 'typescript';
|
|
4
4
|
|
|
5
5
|
|
|
@@ -9,6 +9,7 @@ import * as ts from 'typescript';
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
|
|
12
13
|
export const resolveImportPath = (importPath, relativeFilePath, pathIndexMap, readCompilerOptions = () => readTsConfig(process.cwd())) => {
|
|
13
14
|
|
|
14
15
|
const mut_importAliasMap = {};
|
|
@@ -25,14 +26,8 @@ export const resolveImportPath = (importPath, relativeFilePath, pathIndexMap, re
|
|
|
25
26
|
if (!Arr.isNonEmpty(value)) {
|
|
26
27
|
continue;
|
|
27
28
|
}
|
|
28
|
-
const pathValue = mapNullable(pathIndex, (i) => value[i]) ?? value[0];
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const { baseUrl } = tsconfigOptions;
|
|
34
29
|
mut_importAliasMap[key] =
|
|
35
|
-
|
|
30
|
+
mapNullable(pathIndex, (i) => value[i]) ?? value[0];
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
33
|
}
|
|
@@ -48,14 +43,12 @@ export const resolveImportPath = (importPath, relativeFilePath, pathIndexMap, re
|
|
|
48
43
|
(resolvedImportPath, key) => resolvedImportPath.replace(key.replace('*', ''), mut_importAliasMap[key]?.replace('*', '') ?? ''), mut_importPath);
|
|
49
44
|
return path.normalize(absolutePath);
|
|
50
45
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const found = ts.findConfigFile(
|
|
57
|
-
? 'tsconfig.json'
|
|
58
|
-
: path.basename(tsconfigPath));
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
export const readTsConfig = (cwd) => {
|
|
51
|
+
const found = ts.findConfigFile(cwd, (filePath) => ts.sys.fileExists(filePath), 'tsconfig.json');
|
|
59
52
|
if (found === undefined) {
|
|
60
53
|
|
|
61
54
|
return undefined;
|
|
@@ -77,6 +70,24 @@ const readTsConfig = (tsconfigPath) => {
|
|
|
77
70
|
});
|
|
78
71
|
|
|
79
72
|
|
|
80
|
-
|
|
73
|
+
if (result?.options.paths === undefined) {
|
|
74
|
+
return result?.options;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
const pathsBasePath = result.options['pathsBasePath'];
|
|
80
|
+
const baseDir = isString(pathsBasePath) ? pathsBasePath : path.dirname(found);
|
|
81
|
+
return {
|
|
82
|
+
...result.options,
|
|
83
|
+
paths: Obj.map(result.options.paths, (values) => values.map((value) => relativeTo(cwd, baseDir, value))),
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const relativeTo = (cwd, baseDir, value) => {
|
|
88
|
+
const relative = path.relative(cwd, path.resolve(baseDir, value));
|
|
89
|
+
const nonEmpty = relative === '' ? '.' : relative;
|
|
90
|
+
|
|
91
|
+
return value.endsWith('/') ? `${nonEmpty}/` : nonEmpty;
|
|
81
92
|
};
|
|
82
93
|
//# sourceMappingURL=resolve-import-path.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-import-path.mjs","sourceRoot":"","sources":["../../../../src/plugins/strict-dependencies/rules/resolve-import-path.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,
|
|
1
|
+
{"version":3,"file":"resolve-import-path.mjs","sourceRoot":"","sources":["../../../../src/plugins/strict-dependencies/rules/resolve-import-path.mts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-config-typed",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"@vitest/ui": "5.0.5",
|
|
91
91
|
"cspell": "10.4.0",
|
|
92
92
|
"dedent": "1.7.2",
|
|
93
|
-
"eslint-config-typed": "
|
|
93
|
+
"eslint-config-typed": "7.0.0",
|
|
94
94
|
"eslint-plugin-ts-data-forge": "0.10.4",
|
|
95
95
|
"eslint-plugin-ts-fortress": "1.3.9",
|
|
96
96
|
"eslint-plugin-ts-type-forge": "0.8.14",
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Arr,
|
|
4
|
+
isNonEmptyString,
|
|
5
|
+
isString,
|
|
6
|
+
mapNullable,
|
|
7
|
+
Obj,
|
|
8
|
+
} from 'ts-data-forge';
|
|
3
9
|
import type { MutableRecord, ReadonlyRecord } from 'ts-type-forge';
|
|
4
10
|
import * as ts from 'typescript';
|
|
5
11
|
|
|
@@ -10,7 +16,8 @@ import * as ts from 'typescript';
|
|
|
10
16
|
*
|
|
11
17
|
* `readCompilerOptions` は tsconfig の compilerOptions を返す関数で、既定では
|
|
12
18
|
* カレントディレクトリの tsconfig.json を読む。テストが `typescript` を
|
|
13
|
-
*
|
|
19
|
+
* モジュールごと差し替えずにすむよう引数にしている。返す `paths` の値は
|
|
20
|
+
* カレントディレクトリからの相対パスとして扱う。
|
|
14
21
|
*/
|
|
15
22
|
export const resolveImportPath = (
|
|
16
23
|
importPath: string,
|
|
@@ -43,17 +50,8 @@ export const resolveImportPath = (
|
|
|
43
50
|
continue;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
const pathValue: string =
|
|
47
|
-
mapNullable(pathIndex, (i) => value[i]) ?? value[0];
|
|
48
|
-
|
|
49
|
-
// `baseUrl` is deprecated in TypeScript 6.0, but this rule still
|
|
50
|
-
// needs to read it (if present) to resolve legacy `baseUrl`-relative
|
|
51
|
-
// `paths` entries the same way `tsc` does.
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
53
|
-
const { baseUrl } = tsconfigOptions;
|
|
54
|
-
|
|
55
53
|
mut_importAliasMap[key] =
|
|
56
|
-
|
|
54
|
+
mapNullable(pathIndex, (i) => value[i]) ?? value[0];
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
} catch {
|
|
@@ -80,22 +78,19 @@ export const resolveImportPath = (
|
|
|
80
78
|
return path.normalize(absolutePath);
|
|
81
79
|
};
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Reads the tsconfig.json found from `cwd` upward, with `paths` rewritten as
|
|
83
|
+
* relative to `cwd`.
|
|
84
|
+
*/
|
|
85
|
+
export const readTsConfig = (cwd: string): ts.CompilerOptions | undefined => {
|
|
89
86
|
const found = ts.findConfigFile(
|
|
90
|
-
|
|
87
|
+
cwd,
|
|
91
88
|
(filePath) => ts.sys.fileExists(filePath),
|
|
92
|
-
|
|
93
|
-
? 'tsconfig.json'
|
|
94
|
-
: path.basename(tsconfigPath),
|
|
89
|
+
'tsconfig.json',
|
|
95
90
|
);
|
|
96
91
|
|
|
97
92
|
if (found === undefined) {
|
|
98
|
-
// tsconfig not found under: ${
|
|
93
|
+
// tsconfig not found under: ${cwd}
|
|
99
94
|
return undefined;
|
|
100
95
|
}
|
|
101
96
|
|
|
@@ -122,5 +117,31 @@ const readTsConfig = (tsconfigPath: string): ts.CompilerOptions | undefined => {
|
|
|
122
117
|
|
|
123
118
|
// undefined: 'Failed to parse tsconfig.'
|
|
124
119
|
// result.options: 正規化済みの compilerOptions
|
|
125
|
-
|
|
120
|
+
if (result?.options.paths === undefined) {
|
|
121
|
+
return result?.options;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// `baseUrl` is not read: `paths` are relative to the tsconfig.json that
|
|
125
|
+
// declares them, as `tsc` resolves them without `baseUrl`. That is
|
|
126
|
+
// `pathsBasePath` (internal to TypeScript) when it is an `extends` base.
|
|
127
|
+
const pathsBasePath = result.options['pathsBasePath'];
|
|
128
|
+
|
|
129
|
+
const baseDir = isString(pathsBasePath) ? pathsBasePath : path.dirname(found);
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
...result.options,
|
|
133
|
+
paths: Obj.map(result.options.paths, (values) =>
|
|
134
|
+
values.map((value) => relativeTo(cwd, baseDir, value)),
|
|
135
|
+
),
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/** Rewrites `value`, relative to `baseDir`, as relative to `cwd`. */
|
|
140
|
+
const relativeTo = (cwd: string, baseDir: string, value: string): string => {
|
|
141
|
+
const relative = path.relative(cwd, path.resolve(baseDir, value));
|
|
142
|
+
|
|
143
|
+
const nonEmpty = relative === '' ? '.' : relative;
|
|
144
|
+
|
|
145
|
+
// `path.resolve` drops a trailing slash, which an alias with one relies on.
|
|
146
|
+
return value.endsWith('/') ? `${nonEmpty}/` : nonEmpty;
|
|
126
147
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
1
4
|
import type { ReadonlyRecord } from 'ts-type-forge';
|
|
2
5
|
import type * as ts from 'typescript';
|
|
3
|
-
import { resolveImportPath } from './resolve-import-path.mjs';
|
|
6
|
+
import { readTsConfig, resolveImportPath } from './resolve-import-path.mjs';
|
|
4
7
|
|
|
5
8
|
// FIXME: https://github.com/knowledge-work/eslint-plugin-strict-dependencies/tree/v1.3.27 のテストをコピーしてきて
|
|
6
9
|
// Codex でテスト・型チェックが通るようにさせただけなので、意味の無いテストになっていないかチェックして修正する
|
|
7
10
|
|
|
8
|
-
// `baseUrl` is deprecated in TypeScript 6.0, but the rule still resolves legacy
|
|
9
|
-
// `baseUrl`-relative `paths`, so the fixtures below have to set it.
|
|
10
11
|
const compilerOptionsByFixture = {
|
|
11
12
|
'no-paths': {},
|
|
12
13
|
'paths-basic': {
|
|
@@ -16,55 +17,14 @@ const compilerOptionsByFixture = {
|
|
|
16
17
|
'@/components/*': ['components/*'],
|
|
17
18
|
},
|
|
18
19
|
},
|
|
19
|
-
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- see the note above the table
|
|
21
|
-
baseUrl: '.',
|
|
22
|
-
paths: {
|
|
23
|
-
'@/components/': ['components/'],
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
'base-url-dot-slash': {
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- see the note above the table
|
|
28
|
-
baseUrl: './',
|
|
29
|
-
paths: {
|
|
30
|
-
'@/components/': ['components/'],
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
'base-url-parent': {
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- see the note above the table
|
|
35
|
-
baseUrl: '../',
|
|
36
|
-
paths: {
|
|
37
|
-
'@/components/': ['components/'],
|
|
38
|
-
},
|
|
39
|
-
},
|
|
20
|
+
// `paths` are resolved from the tsconfig.json whatever `baseUrl` says.
|
|
40
21
|
'base-url-src': {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated --
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- the fixture is about the deprecated option
|
|
42
23
|
baseUrl: 'src',
|
|
43
24
|
paths: {
|
|
44
25
|
'@/components/': ['components/'],
|
|
45
26
|
},
|
|
46
27
|
},
|
|
47
|
-
'base-url-dot-src': {
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- see the note above the table
|
|
49
|
-
baseUrl: './src',
|
|
50
|
-
paths: {
|
|
51
|
-
'@/components/': ['components/'],
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
'base-url-src-slash': {
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- see the note above the table
|
|
56
|
-
baseUrl: 'src/',
|
|
57
|
-
paths: {
|
|
58
|
-
'@/components/': ['components/'],
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
'base-url-dot-src-slash': {
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated -- see the note above the table
|
|
63
|
-
baseUrl: './src/',
|
|
64
|
-
paths: {
|
|
65
|
-
'@/components/': ['components/'],
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
28
|
'paths-multiple': {
|
|
69
29
|
paths: {
|
|
70
30
|
'@/components/*': ['src/components/*', 'src/alternativeComponents/*'],
|
|
@@ -103,40 +63,6 @@ const aliasCases = [
|
|
|
103
63
|
},
|
|
104
64
|
] as const;
|
|
105
65
|
|
|
106
|
-
const baseUrlCases = [
|
|
107
|
-
{
|
|
108
|
-
fixtureName: 'base-url-dot',
|
|
109
|
-
expected: 'components/aaa/bbb',
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
fixtureName: 'base-url-dot-slash',
|
|
113
|
-
expected: 'components/aaa/bbb',
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
fixtureName: 'base-url-parent',
|
|
117
|
-
expected: '../components/aaa/bbb',
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
fixtureName: 'base-url-src',
|
|
121
|
-
expected: 'src/components/aaa/bbb',
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
fixtureName: 'base-url-dot-src',
|
|
125
|
-
expected: 'src/components/aaa/bbb',
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
fixtureName: 'base-url-src-slash',
|
|
129
|
-
expected: 'src/components/aaa/bbb',
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
fixtureName: 'base-url-dot-src-slash',
|
|
133
|
-
expected: 'src/components/aaa/bbb',
|
|
134
|
-
},
|
|
135
|
-
] as const satisfies readonly Readonly<{
|
|
136
|
-
fixtureName: FixtureName;
|
|
137
|
-
expected: string;
|
|
138
|
-
}>[];
|
|
139
|
-
|
|
140
66
|
describe(resolveImportPath, () => {
|
|
141
67
|
test('should resolve relative path', () => {
|
|
142
68
|
expect(
|
|
@@ -192,30 +118,16 @@ describe(resolveImportPath, () => {
|
|
|
192
118
|
},
|
|
193
119
|
);
|
|
194
120
|
|
|
195
|
-
test
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
readCompilerOptions,
|
|
206
|
-
),
|
|
207
|
-
).toBe('components/aaa/bbb');
|
|
208
|
-
|
|
209
|
-
expect(
|
|
210
|
-
resolveImportPath(
|
|
211
|
-
'@/components/aaa/bbb',
|
|
212
|
-
undefined,
|
|
213
|
-
{},
|
|
214
|
-
readCompilerOptions,
|
|
215
|
-
),
|
|
216
|
-
).toBe(expected);
|
|
217
|
-
},
|
|
218
|
-
);
|
|
121
|
+
test('should ignore baseUrl', () => {
|
|
122
|
+
expect(
|
|
123
|
+
resolveImportPath(
|
|
124
|
+
'@/components/aaa/bbb',
|
|
125
|
+
undefined,
|
|
126
|
+
{},
|
|
127
|
+
readFixture('base-url-src'),
|
|
128
|
+
),
|
|
129
|
+
).toBe('components/aaa/bbb');
|
|
130
|
+
});
|
|
219
131
|
|
|
220
132
|
test('should resolve path alias with specified index in pathIndexMap', () => {
|
|
221
133
|
expect(
|
|
@@ -250,3 +162,120 @@ describe(resolveImportPath, () => {
|
|
|
250
162
|
).toBe('src/components/aaa/bbb');
|
|
251
163
|
});
|
|
252
164
|
});
|
|
165
|
+
|
|
166
|
+
describe(readTsConfig, () => {
|
|
167
|
+
test('should resolve paths from the directory of tsconfig.json', () => {
|
|
168
|
+
expect(
|
|
169
|
+
resolveWithTsconfig(
|
|
170
|
+
{ paths: { '@/*': ['./src/*'] } },
|
|
171
|
+
'.',
|
|
172
|
+
'@/components/aaa',
|
|
173
|
+
),
|
|
174
|
+
).toBe('src/components/aaa');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('should keep a trailing slash of a paths entry', () => {
|
|
178
|
+
expect(
|
|
179
|
+
resolveWithTsconfig(
|
|
180
|
+
{ paths: { '@/components/': ['src/components/'] } },
|
|
181
|
+
'.',
|
|
182
|
+
'@/components/aaa',
|
|
183
|
+
),
|
|
184
|
+
).toBe('src/components/aaa');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test('should resolve a paths entry naming the directory of tsconfig.json', () => {
|
|
188
|
+
expect(
|
|
189
|
+
resolveWithTsconfig({ paths: { '@/': ['./'] } }, '.', '@/components/aaa'),
|
|
190
|
+
).toBe('components/aaa');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
test('should resolve paths from a tsconfig.json found above the working directory', () => {
|
|
194
|
+
expect(
|
|
195
|
+
resolveWithTsconfig(
|
|
196
|
+
{ paths: { '@/*': ['./src/*'] } },
|
|
197
|
+
'packages/a',
|
|
198
|
+
'@/components/aaa',
|
|
199
|
+
),
|
|
200
|
+
).toBe('../../src/components/aaa');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test('should resolve paths from the directory of the tsconfig.json declaring them', () => {
|
|
204
|
+
expect(
|
|
205
|
+
resolveWithFiles(
|
|
206
|
+
{
|
|
207
|
+
'configs/tsconfig.base.json': {
|
|
208
|
+
compilerOptions: { paths: { '@/*': ['../src/*'] } },
|
|
209
|
+
},
|
|
210
|
+
'tsconfig.json': {
|
|
211
|
+
extends: './configs/tsconfig.base.json',
|
|
212
|
+
files: [],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
'.',
|
|
216
|
+
'@/components/aaa',
|
|
217
|
+
),
|
|
218
|
+
).toBe('src/components/aaa');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test('should ignore baseUrl', () => {
|
|
222
|
+
expect(
|
|
223
|
+
resolveWithTsconfig(
|
|
224
|
+
{
|
|
225
|
+
baseUrl: 'src',
|
|
226
|
+
ignoreDeprecations: '6.0',
|
|
227
|
+
paths: { '@/*': ['./lib/*'] },
|
|
228
|
+
},
|
|
229
|
+
'.',
|
|
230
|
+
'@/components/aaa',
|
|
231
|
+
),
|
|
232
|
+
).toBe('lib/components/aaa');
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Writes `files` (JSON, by path) into a new directory, runs
|
|
238
|
+
* `resolveImportPath` with `readTsConfig` from `cwdSubdirectory` of it, and
|
|
239
|
+
* removes the directory.
|
|
240
|
+
*/
|
|
241
|
+
const resolveWithFiles = (
|
|
242
|
+
files: ReadonlyRecord<string, unknown>,
|
|
243
|
+
cwdSubdirectory: string,
|
|
244
|
+
importPath: string,
|
|
245
|
+
): string => {
|
|
246
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'resolve-import-path-'));
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
250
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
251
|
+
fs.mkdirSync(path.dirname(path.join(root, filePath)), {
|
|
252
|
+
recursive: true,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
256
|
+
fs.writeFileSync(path.join(root, filePath), JSON.stringify(content));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const cwd = path.join(root, cwdSubdirectory);
|
|
260
|
+
|
|
261
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
262
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
263
|
+
|
|
264
|
+
return resolveImportPath(importPath, undefined, {}, () =>
|
|
265
|
+
readTsConfig(cwd),
|
|
266
|
+
);
|
|
267
|
+
} finally {
|
|
268
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const resolveWithTsconfig = (
|
|
273
|
+
compilerOptions: ReadonlyRecord<string, unknown>,
|
|
274
|
+
cwdSubdirectory: string,
|
|
275
|
+
importPath: string,
|
|
276
|
+
): string =>
|
|
277
|
+
resolveWithFiles(
|
|
278
|
+
{ 'tsconfig.json': { compilerOptions, files: [] } },
|
|
279
|
+
cwdSubdirectory,
|
|
280
|
+
importPath,
|
|
281
|
+
);
|