Skip to content

Commit 78a08e0

Browse files
committed
feat!: use get-tsconfig to replace tsconfig-paths
1 parent 322cb29 commit 78a08e0

File tree

5 files changed

+35
-129
lines changed

5 files changed

+35
-129
lines changed

.eslintrc

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
22
"root": true,
3+
"parserOptions": {
4+
"ecmaVersion": "latest"
5+
},
36
"extends": [
47
"plugin:prettier/recommended",
58
"plugin:mdx/recommended"

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@
6262
},
6363
"dependencies": {
6464
"debug": "^4.3.4",
65+
"get-tsconfig": "^4.0.6",
6566
"globby": "^13.1.2",
6667
"is-glob": "^4.0.3",
6768
"resolve": "^1.22.1",
68-
"synckit": "^0.7.1",
69-
"tsconfig-paths": "^4.0.0"
69+
"synckit": "^0.7.1"
7070
},
7171
"devDependencies": {
7272
"@1stg/lib-config": "^6.2.3",

src/index.ts

+22-118
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@ import path from 'node:path'
22
import { fileURLToPath } from 'node:url'
33

44
import debug from 'debug'
5+
import { createPathsMatcher, getTsconfig } from 'get-tsconfig'
56
import isGlob from 'is-glob'
6-
import * as _resolve from 'resolve'
7+
import { isCore, type PackageJSON, sync, SyncOpts } from 'resolve'
78
import { createSyncFn } from 'synckit'
8-
import {
9-
ConfigLoaderSuccessResult,
10-
createMatchPath,
11-
loadConfig,
12-
ConfigLoaderResult,
13-
MatchPath,
14-
} from 'tsconfig-paths'
159

1610
const IMPORTER_NAME = 'eslint-import-resolver-typescript'
1711

@@ -26,22 +20,9 @@ const globSync = createSyncFn<typeof import('globby').globby>(
2620
path.resolve(_dirname, 'worker.mjs'),
2721
)
2822

29-
/**
30-
* .mts, .cts, .d.mts, .d.cts, .mjs, .cjs are not included because .cjs and .mjs must be used explicitly.
31-
*/
32-
const defaultExtensions = [
33-
'.ts',
34-
'.tsx',
35-
'.d.ts',
36-
'.js',
37-
'.jsx',
38-
'.json',
39-
'.node',
40-
]
41-
4223
export const interfaceVersion = 2
4324

44-
export type TsResolverOptions = _resolve.SyncOpts & {
25+
export type TsResolverOptions = SyncOpts & {
4526
alwaysTryTypes?: boolean
4627
/**
4728
* @deprecated use `project` instead
@@ -72,7 +53,7 @@ export function resolve(
7253
source = removeQuerystring(source)
7354

7455
// don't worry about core node modules
75-
if (_resolve.isCore(source)) {
56+
if (isCore(source)) {
7657
log('matched core:', source)
7758

7859
return {
@@ -84,16 +65,14 @@ export function resolve(
8465
initMappers(options)
8566
const mappedPath = getMappedPath(source)
8667
if (mappedPath) {
87-
log('matched ts path:', mappedPath.path)
68+
log('matched ts path:', mappedPath)
8869
}
8970

9071
// note that even if we map the path, we still need to do a final resolve
9172
let foundNodePath: string | null | undefined
9273
try {
93-
foundNodePath = tsResolve(mappedPath?.path ?? source, {
74+
foundNodePath = tsResolve(mappedPath ?? source, {
9475
...options,
95-
extensions:
96-
mappedPath?.extensions ?? options.extensions ?? defaultExtensions,
9776
basedir: path.dirname(path.resolve(file)),
9877
packageFilter: options.packageFilter ?? packageFilterDefault,
9978
})
@@ -136,7 +115,7 @@ export function resolve(
136115
}
137116
}
138117

139-
function packageFilterDefault(pkg: _resolve.PackageJSON) {
118+
function packageFilterDefault(pkg: PackageJSON) {
140119
pkg.main =
141120
pkg.types || pkg.typings || pkg.module || pkg['jsnext:main'] || pkg.main
142121
return pkg
@@ -172,13 +151,13 @@ function resolveExtension(id: string) {
172151
* Like `sync` from `resolve` package, but considers that the module id
173152
* could have a .js or .jsx extension.
174153
*/
175-
function tsResolve(id: string, opts: _resolve.SyncOpts): string {
154+
function tsResolve(id: string, opts: SyncOpts): string {
176155
try {
177-
return _resolve.sync(id, opts)
156+
return sync(id, opts)
178157
} catch (error) {
179158
const resolved = resolveExtension(id)
180159
if (resolved) {
181-
return _resolve.sync(resolved.path, {
160+
return sync(resolved.path, {
182161
...opts,
183162
extensions: resolved.extensions ?? opts.extensions,
184163
})
@@ -202,24 +181,20 @@ function removeJsExtension(id: string) {
202181
}
203182

204183
let mappersBuildForOptions: TsResolverOptions
205-
let mappers:
206-
| Array<
207-
(source: string) =>
208-
| {
209-
path: string
210-
extensions?: string[]
211-
}
212-
| undefined
213-
>
214-
| undefined
184+
let mappers: Array<((specifier: string) => string[]) | null> | undefined
215185

216186
/**
217187
* @param {string} source the module to resolve; i.e './some-module'
218-
* @param {string} file the importing file's full path; i.e. '/usr/local/bin/file.js'
219188
* @returns The mapped path of the module or undefined
220189
*/
221190
function getMappedPath(source: string) {
222-
const paths = mappers!.map(mapper => mapper(source)).filter(path => !!path)
191+
const paths = mappers!
192+
.map(mapper => mapper?.(source))
193+
.filter(path => !!path)
194+
.flat()
195+
196+
console.log('source:', source)
197+
console.log('paths:', paths)
223198

224199
if (paths.length > 1) {
225200
log('found multiple matching ts paths:', paths)
@@ -228,51 +203,6 @@ function getMappedPath(source: string) {
228203
return paths[0]
229204
}
230205

231-
/**
232-
* Like `createMatchPath` from `tsconfig-paths` package, but considers
233-
* that the module id could have a .mjs, .cjs, .js or .jsx extension.
234-
*
235-
* The default resolved path does not include the extension, so we need to return it for reusing,
236-
* otherwise `.mts`, `.cts`, `.d.mts`, `.d.cts` will not be used by default, see also @link {defaultExtensions}.
237-
*/
238-
const createExtendedMatchPath: (
239-
...createArgs: Parameters<typeof createMatchPath>
240-
) => (...matchArgs: Parameters<MatchPath>) =>
241-
| {
242-
path: string
243-
extensions?: string[]
244-
}
245-
| undefined = (...createArgs) => {
246-
const matchPath = createMatchPath(...createArgs)
247-
248-
return (id, readJson, fileExists, extensions) => {
249-
const match = matchPath(id, readJson, fileExists, extensions)
250-
251-
if (match != null) {
252-
return {
253-
path: match,
254-
}
255-
}
256-
257-
const resolved = resolveExtension(id)
258-
259-
if (resolved) {
260-
const match = matchPath(
261-
resolved.path,
262-
readJson,
263-
fileExists,
264-
resolved.extensions ?? extensions,
265-
)
266-
if (match) {
267-
return {
268-
path: match,
269-
extensions: resolved.extensions,
270-
}
271-
}
272-
}
273-
}
274-
}
275-
276206
function initMappers(options: TsResolverOptions) {
277207
if (mappers && mappersBuildForOptions === options) {
278208
return
@@ -307,40 +237,14 @@ function initMappers(options: TsResolverOptions) {
307237
]),
308238
]
309239

310-
mappers = projectPaths
311-
.map(loadConfig)
312-
.filter(isConfigLoaderSuccessResult)
313-
.map(configLoaderResult => {
314-
const matchPath = createExtendedMatchPath(
315-
configLoaderResult.absoluteBaseUrl,
316-
configLoaderResult.paths,
317-
)
318-
319-
return (source: string) =>
320-
// look for files based on setup tsconfig "paths"
321-
matchPath(
322-
source,
323-
undefined,
324-
undefined,
325-
options.extensions ?? defaultExtensions,
326-
)
327-
})
240+
mappers = projectPaths.map(projectPath => {
241+
const tsconfigResult = getTsconfig(projectPath)
242+
return tsconfigResult && createPathsMatcher(tsconfigResult)
243+
})
328244

329245
mappersBuildForOptions = options
330246
}
331247

332-
function isConfigLoaderSuccessResult(
333-
configLoaderResult: ConfigLoaderResult,
334-
): configLoaderResult is ConfigLoaderSuccessResult {
335-
if (configLoaderResult.resultType !== 'success') {
336-
// this can happen if the user has problems with their tsconfig
337-
// or if it's valid, but they don't have baseUrl set
338-
log('failed to init tsconfig-paths:', configLoaderResult.message)
339-
return false
340-
}
341-
return true
342-
}
343-
344248
/**
345249
* For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`.
346250
*/

tests/baseEslintConfig.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/**
2+
* @param {string} project
3+
*/
14
module.exports = project => ({
25
parser: '@typescript-eslint/parser',
36
extends: [

yarn.lock

+5-9
Original file line numberDiff line numberDiff line change
@@ -5169,6 +5169,11 @@ get-symbol-description@^1.0.0:
51695169
call-bind "^1.0.2"
51705170
get-intrinsic "^1.1.1"
51715171

5172+
get-tsconfig@^4.0.6:
5173+
version "4.0.6"
5174+
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.0.6.tgz#31ee086022b1261fccf89cfc7460db0f3c02fa57"
5175+
integrity sha512-yK9g+lk9PSaYS4RM9jnlmFSyymNDdLaIk42h6uOO6DOvqKEpL4KhUAcI1/7/sWe8+FWZe1/EjFXFfvv6T+cgPA==
5176+
51725177
git-raw-commits@^2.0.0, git-raw-commits@^2.0.8:
51735178
version "2.0.11"
51745179
resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723"
@@ -10263,15 +10268,6 @@ tsconfig-paths@^3.14.1:
1026310268
minimist "^1.2.6"
1026410269
strip-bom "^3.0.0"
1026510270

10266-
tsconfig-paths@^4.0.0:
10267-
version "4.0.0"
10268-
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.0.0.tgz#1082f5d99fd127b72397eef4809e4dd06d229b64"
10269-
integrity sha512-SLBg2GBKlR6bVtMgJJlud/o3waplKtL7skmLkExomIiaAtLGtVsoXIqP3SYdjbcH9lq/KVv7pMZeCBpLYOit6Q==
10270-
dependencies:
10271-
json5 "^2.2.1"
10272-
minimist "^1.2.6"
10273-
strip-bom "^3.0.0"
10274-
1027510271
"tslib@1 || 2", tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0:
1027610272
version "2.4.0"
1027710273
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"

0 commit comments

Comments
 (0)