Skip to content

Commit 39ab8b1

Browse files
committed
feat!: use enhanced-resolve instead
close import-js#85, close import-js#107
1 parent 6683854 commit 39ab8b1

File tree

5 files changed

+304
-271
lines changed

5 files changed

+304
-271
lines changed

package.json

+6-4
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,21 @@
6363
},
6464
"dependencies": {
6565
"debug": "^4.3.4",
66+
"enhanced-resolve": "^5.9.3",
6667
"get-tsconfig": "^4.0.6",
6768
"globby": "^13.1.2",
69+
"is-core-module": "^2.9.0",
6870
"is-glob": "^4.0.3",
69-
"resolve": "^1.22.1",
7071
"synckit": "^0.7.1"
7172
},
7273
"devDependencies": {
73-
"@1stg/lib-config": "^6.2.3",
74+
"@1stg/lib-config": "^6.3.0",
75+
"@mozilla/glean": "^1.0.0",
7476
"@types/debug": "^4.1.7",
75-
"@types/glob": "^7.2.0",
77+
"@types/enhanced-resolve": "^3.0.7",
78+
"@types/is-core-module": "^2.2.0",
7679
"@types/is-glob": "^4.0.2",
7780
"@types/node": "^18.0.0",
78-
"@types/resolve": "^1.20.2",
7981
"@types/unist": "^2.0.6",
8082
"dummy.js": "link:dummy.js",
8183
"eslint-import-resolver-typescript": "link:.",

src/index.ts

+56-26
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@ import path from 'node:path'
33
import { fileURLToPath } from 'node:url'
44

55
import debug from 'debug'
6+
import {
7+
FileSystem,
8+
ResolveOptions,
9+
Resolver,
10+
ResolverFactory,
11+
} from 'enhanced-resolve'
612
import { createPathsMatcher, getTsconfig } from 'get-tsconfig'
13+
import isCore from 'is-core-module'
714
import isGlob from 'is-glob'
8-
import { isCore, type PackageJSON, sync, SyncOpts } from 'resolve'
915
import { createSyncFn } from 'synckit'
1016

1117
const IMPORTER_NAME = 'eslint-import-resolver-typescript'
@@ -21,15 +27,37 @@ const globSync = createSyncFn<typeof import('globby').globby>(
2127
path.resolve(_dirname, 'worker.mjs'),
2228
)
2329

30+
/**
31+
* .mts, .cts, .d.mts, .d.cts, .mjs, .cjs are not included because .cjs and .mjs must be used explicitly.
32+
*/
33+
const defaultExtensions = [
34+
'.ts',
35+
'.tsx',
36+
'.d.ts',
37+
'.js',
38+
'.jsx',
39+
'.json',
40+
'.node',
41+
]
42+
43+
const defaultMainFields = ['types', 'typings', 'module', 'jsnext:main', 'main']
44+
2445
export const interfaceVersion = 2
2546

26-
export type TsResolverOptions = SyncOpts & {
47+
export interface TsResolverOptions
48+
extends Omit<ResolveOptions, 'fileSystem' | 'useSyncFileSystemCalls'> {
2749
alwaysTryTypes?: boolean
2850
project?: string[] | string
2951
extensions?: string[]
3052
packageFilter?: (pkg: Record<string, string>) => Record<string, string>
3153
}
3254

55+
const fileSystem = fs as FileSystem
56+
57+
let mappersBuildForOptions: TsResolverOptions
58+
let mappers: Array<((specifier: string) => string[]) | null> | undefined
59+
let resolver: Resolver
60+
3361
/**
3462
* @param {string} source the module to resolve; i.e './some-module'
3563
* @param {string} file the importing file's full path; i.e. '/usr/local/bin/file.js'
@@ -38,12 +66,20 @@ export type TsResolverOptions = SyncOpts & {
3866
export function resolve(
3967
source: string,
4068
file: string,
41-
options: TsResolverOptions | null,
69+
options?: TsResolverOptions | null,
4270
): {
4371
found: boolean
4472
path?: string | null
4573
} {
46-
options = options ?? {}
74+
const opts: ResolveOptions & TsResolverOptions = {
75+
...options,
76+
extensions: options?.extensions ?? defaultExtensions,
77+
mainFields: options?.mainFields ?? defaultMainFields,
78+
fileSystem,
79+
useSyncFileSystemCalls: true,
80+
}
81+
82+
resolver = ResolverFactory.createResolver(opts)
4783

4884
log('looking for:', source)
4985

@@ -59,7 +95,7 @@ export function resolve(
5995
}
6096
}
6197

62-
initMappers(options)
98+
initMappers(opts)
6399

64100
const mappedPath = getMappedPath(source, file, true)
65101
if (mappedPath) {
@@ -69,11 +105,9 @@ export function resolve(
69105
// note that even if we map the path, we still need to do a final resolve
70106
let foundNodePath: string | null | undefined
71107
try {
72-
foundNodePath = tsResolve(mappedPath ?? source, {
73-
...options,
74-
basedir: path.dirname(path.resolve(file)),
75-
packageFilter: options.packageFilter ?? packageFilterDefault,
76-
})
108+
foundNodePath =
109+
tsResolve(mappedPath ?? source, path.dirname(path.resolve(file)), opts) ||
110+
null
77111
} catch {
78112
foundNodePath = null
79113
}
@@ -82,7 +116,7 @@ export function resolve(
82116
// if path is neither absolute nor relative
83117
if (
84118
(/\.jsx?$/.test(foundNodePath!) ||
85-
(options.alwaysTryTypes && !foundNodePath)) &&
119+
(opts.alwaysTryTypes && !foundNodePath)) &&
86120
!/^@types[/\\]/.test(source) &&
87121
!path.isAbsolute(source) &&
88122
!source.startsWith('.')
@@ -113,12 +147,6 @@ export function resolve(
113147
}
114148
}
115149

116-
function packageFilterDefault(pkg: PackageJSON) {
117-
pkg.main =
118-
pkg.types || pkg.typings || pkg.module || pkg['jsnext:main'] || pkg.main
119-
return pkg
120-
}
121-
122150
function resolveExtension(id: string) {
123151
const idWithoutJsExt = removeJsExtension(id)
124152

@@ -149,16 +177,21 @@ function resolveExtension(id: string) {
149177
* Like `sync` from `resolve` package, but considers that the module id
150178
* could have a .js or .jsx extension.
151179
*/
152-
function tsResolve(id: string, opts: SyncOpts): string {
180+
function tsResolve(
181+
source: string,
182+
base: string,
183+
options: ResolveOptions,
184+
): string | false {
153185
try {
154-
return sync(id, opts)
186+
return resolver.resolveSync({}, base, source)
155187
} catch (error) {
156-
const resolved = resolveExtension(id)
188+
const resolved = resolveExtension(source)
157189
if (resolved) {
158-
return sync(resolved.path, {
159-
...opts,
160-
extensions: resolved.extensions ?? opts.extensions,
190+
const resolver = ResolverFactory.createResolver({
191+
...options,
192+
extensions: resolved.extensions ?? options.extensions,
161193
})
194+
return resolver.resolveSync({}, base, resolved.path)
162195
}
163196
throw error
164197
}
@@ -178,9 +211,6 @@ function removeJsExtension(id: string) {
178211
return id.replace(/\.([cm]js|jsx?)$/, '')
179212
}
180213

181-
let mappersBuildForOptions: TsResolverOptions
182-
let mappers: Array<((specifier: string) => string[]) | null> | undefined
183-
184214
const JS_EXT_PATTERN = /\.([cm]js|jsx?)$/
185215
const RELATIVE_PATH_PATTERN = /^\.{1,2}(\/.*)?$/
186216

tests/withJsExtension/test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,5 @@ assertResolve(
127127
'../../node_modules/typescript/lib/typescript.js',
128128
)
129129

130-
assertResolve('dummy.js', '../../node_modules/dummy.js/index.js')
130+
// resolves symlinks by default
131+
assertResolve('dummy.js', '../../dummy.js/index.js')

tests/withoutPaths/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ import 'json5'
1515

1616
// enable alwaysTryTypes
1717
import 'unist'
18+
19+
// exports
20+
import '@mozilla/glean/webext'

0 commit comments

Comments
 (0)