diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30d61dc..2482a79 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-import-x: specifier: '*' - version: 4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) + version: 4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) oxc-resolver: specifier: ^2.1.1 version: 2.1.1 @@ -23,7 +23,7 @@ importers: version: 22.10.1 '@vida0905/eslint-config': specifier: ^1.1.1 - version: 1.1.1(@typescript-eslint/utils@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint-plugin-import-x@4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)(vitest@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(yaml@2.6.1)) + version: 1.1.1(@typescript-eslint/utils@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint-plugin-import-x@4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)(vitest@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(yaml@2.6.1)) bumpp: specifier: ^9.8.1 version: 9.8.1 @@ -1212,8 +1212,8 @@ packages: peerDependencies: eslint: '>=8' - eslint-plugin-import-x@4.4.3: - resolution: {integrity: sha512-QBprHvhLsfDhP++2T1NnjsOUt6bLDX3NMHaYwAB1FD3xmYTkdFH+HS1OamGhz28jLkRyIZa6UNAzTxbHnJwz5w==} + eslint-plugin-import-x@4.5.0: + resolution: {integrity: sha512-l0OTfnPF8RwmSXfjT75N8d6ZYLVrVYWpaGlgvVkVqFERCI5SyBfDP7QEMr3kt0zWi2sOa9EQ47clbdFsHkF83Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2845,7 +2845,7 @@ snapshots: eslint-merge-processors: 0.1.0(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-antfu: 2.7.0(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-command: 0.2.6(eslint@9.16.0(jiti@1.21.6)) - eslint-plugin-import-x: 4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) + eslint-plugin-import-x: 4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) eslint-plugin-jsdoc: 50.6.0(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-jsonc: 2.18.2(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-n: 17.14.0(eslint@9.16.0(jiti@1.21.6)) @@ -3359,11 +3359,11 @@ snapshots: '@typescript-eslint/types': 8.16.0 eslint-visitor-keys: 4.2.0 - '@vida0905/eslint-config@1.1.1(@typescript-eslint/utils@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint-plugin-import-x@4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)(vitest@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(yaml@2.6.1))': + '@vida0905/eslint-config@1.1.1(@typescript-eslint/utils@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint-plugin-import-x@4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)(vitest@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(yaml@2.6.1))': dependencies: '@antfu/eslint-config': 3.11.2(@typescript-eslint/utils@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2)(vitest@2.1.6(@types/node@22.10.1)(jiti@1.21.6)(yaml@2.6.1)) eslint: 9.16.0(jiti@1.21.6) - eslint-import-resolver-oxc: 0.5.0(eslint-plugin-import-x@4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6)) + eslint-import-resolver-oxc: 0.5.0(eslint-plugin-import-x@4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-pinia: 0.4.1(@typescript-eslint/utils@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)) local-pkg: 0.5.1 transitivePeerDependencies: @@ -3964,13 +3964,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-oxc@0.5.0(eslint-plugin-import-x@4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6)): + eslint-import-resolver-oxc@0.5.0(eslint-plugin-import-x@4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6)): dependencies: eslint: 9.16.0(jiti@1.21.6) oxc-resolver: 2.1.1 optionalDependencies: eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.16.0(jiti@1.21.6)) - eslint-plugin-import-x: 4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) + eslint-plugin-import-x: 4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) eslint-json-compat-utils@0.2.1(eslint@9.16.0(jiti@1.21.6))(jsonc-eslint-parser@2.4.0): dependencies: @@ -4009,8 +4009,9 @@ snapshots: eslint: 9.16.0(jiti@1.21.6) eslint-compat-utils: 0.5.1(eslint@9.16.0(jiti@1.21.6)) - eslint-plugin-import-x@4.4.3(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2): + eslint-plugin-import-x@4.5.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2): dependencies: + '@typescript-eslint/scope-manager': 8.16.0 '@typescript-eslint/utils': 8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) debug: 4.3.7 doctrine: 3.0.0 diff --git a/src/index.ts b/src/index.ts index d7425a2..d32b5b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,19 +5,24 @@ import { ResolverFactory } from 'oxc-resolver' import { normalizeOptions } from './normalizeOptions' import { hashObject } from './utils' -let cacheOptionsHash: string | undefined -let resolver: ResolverFactory | undefined -export function resolve(source: string, file: string, options?: NapiResolveOptions | null): { found: boolean, path: string | null | undefined } { +let cachedOptionsHash: string | undefined +let cachedResolver: ResolverFactory | undefined + +export function resolve(source: string, file: string, options?: NapiResolveOptions | null, resolver: ResolverFactory | null = null): { found: boolean, path: string | null | undefined } { if (isBuiltin(source)) return { found: true, path: null } - options ??= {} - const optionsHash = hashObject(options) + if (resolver == null) { + options ??= {} + const optionsHash = hashObject(options) + + if (!cachedResolver || cachedOptionsHash !== optionsHash) { + options = normalizeOptions(options) + cachedResolver = new ResolverFactory(options) + cachedOptionsHash = optionsHash + } - if (!resolver || cacheOptionsHash !== optionsHash) { - options = normalizeOptions(options) - resolver = new ResolverFactory(options) - cacheOptionsHash = optionsHash + resolver = cachedResolver } // https://github.com/oxc-project/oxc-resolver/blob/main/npm/README.md#api @@ -30,3 +35,15 @@ export function resolve(source: string, file: string, options?: NapiResolveOptio } export const interfaceVersion = 2 + +export function createOxcImportResolver(options?: NapiResolveOptions | null) { + const resolver = new ResolverFactory(normalizeOptions(options)) + + return { + interfaceVersion: 3, + name: 'eslint-import-resolver-oxc', + resolve(source: string, file: string) { + return resolve(source, file, null, resolver) + }, + } +} diff --git a/tests/eslint-plugin/rules/no-cycle.test.ts b/tests/eslint-plugin/rules/no-cycle.test.ts index a7d20a6..6f7aa1e 100644 --- a/tests/eslint-plugin/rules/no-cycle.test.ts +++ b/tests/eslint-plugin/rules/no-cycle.test.ts @@ -2,7 +2,8 @@ import { run } from '../utils' function createCycleSourceError(p: string) { return { - message: `Dependency cycle via ${p}`, + messageId: 'cycleSource', + data: { source: p }, } } diff --git a/tests/eslint-plugin/rules/no-extraneous-dependencies.test.ts b/tests/eslint-plugin/rules/no-extraneous-dependencies.test.ts index c7d45b8..0102321 100644 --- a/tests/eslint-plugin/rules/no-extraneous-dependencies.test.ts +++ b/tests/eslint-plugin/rules/no-extraneous-dependencies.test.ts @@ -1,5 +1,4 @@ -import type { NapiResolveOptions } from 'oxc-resolver' -import { oxcResolver, run, testFilePath } from '../utils' +import { createOxcImportResolver, run, testFilePath } from '../utils' run({ rule: 'no-extraneous-dependencies', @@ -13,13 +12,13 @@ run({ { code: 'import "@custom-internal-alias/api/service";', settings: { - 'import-x/resolver': { - [oxcResolver]: { + 'import-x/resolver-next': [ + createOxcImportResolver({ alias: { '@custom-internal-alias': [testFilePath('internal-modules')], }, - } satisfies NapiResolveOptions, - }, + }), + ], }, }, ], @@ -27,13 +26,13 @@ run({ { code: 'import jest from "alias/jest";', settings: { - 'import-x/resolver': { - [oxcResolver]: { + 'import-x/resolver-next': [ + createOxcImportResolver({ alias: { 'alias/jest': ['jest'], }, - } satisfies NapiResolveOptions, - }, + }), + ], }, errors: [ // missing dependency is jest not alias diff --git a/tests/eslint-plugin/rules/no-internal-modules.test.ts b/tests/eslint-plugin/rules/no-internal-modules.test.ts index 3885d0f..f0e92ff 100644 --- a/tests/eslint-plugin/rules/no-internal-modules.test.ts +++ b/tests/eslint-plugin/rules/no-internal-modules.test.ts @@ -1,5 +1,4 @@ -import type { NapiResolveOptions } from 'oxc-resolver' -import { oxcResolver, run, testFilePath } from '../utils' +import { createOxcImportResolver, run, testFilePath } from '../utils' run({ rule: 'no-internal-modules', @@ -19,13 +18,13 @@ run({ }, ], settings: { - 'import-x/resolver': { - [oxcResolver]: { + 'import-x/resolver-next': [ + createOxcImportResolver({ alias: { '@': [testFilePath('internal-modules')], }, - } satisfies NapiResolveOptions, - }, + }), + ], }, }, ], diff --git a/tests/eslint-plugin/rules/order.test.ts b/tests/eslint-plugin/rules/order.test.ts index fc0926f..83083a0 100644 --- a/tests/eslint-plugin/rules/order.test.ts +++ b/tests/eslint-plugin/rules/order.test.ts @@ -1,5 +1,4 @@ -import type { NapiResolveOptions } from 'oxc-resolver' -import { oxcResolver, run, testFilePath } from '../utils' +import { createOxcImportResolver, run, testFilePath } from '../utils' run({ rule: 'order', @@ -54,13 +53,13 @@ run({ }, ], settings: { - 'import-x/resolver': { - [oxcResolver]: { + 'import-x/resolver-next': [ + createOxcImportResolver({ alias: { '@': [testFilePath('internal-modules')], }, - } satisfies NapiResolveOptions, - }, + }), + ], }, }, ], diff --git a/tests/eslint-plugin/utils.ts b/tests/eslint-plugin/utils.ts index 5092e8c..aa14e2a 100644 --- a/tests/eslint-plugin/utils.ts +++ b/tests/eslint-plugin/utils.ts @@ -1,13 +1,13 @@ import type { RuleTesterInitOptions, TestCasesOptions } from 'eslint-vitest-rule-tester' -import type { NapiResolveOptions } from 'oxc-resolver' import path from 'node:path' -import { cwd } from 'node:process' import tsParser from '@typescript-eslint/parser' import { rules } from 'eslint-plugin-import-x' import { run as _run } from 'eslint-vitest-rule-tester' +import { createOxcImportResolver } from '../../src' -export * from 'eslint-vitest-rule-tester' +export { createOxcImportResolver } from '../../src' export { unindent as $ } from 'eslint-vitest-rule-tester' +export * from 'eslint-vitest-rule-tester' export interface ExtendedRuleTesterOptions extends RuleTesterInitOptions, TestCasesOptions { lang?: 'js' | 'ts' @@ -25,8 +25,6 @@ const defaultFilenames = { ts: 'tests/eslint-plugin/fixtures/foo.ts', } -export const oxcResolver = path.resolve(cwd(), 'dist/index.cjs') - export function run(options: ExtendedRuleTesterOptions) { return _run({ recursive: false, @@ -35,15 +33,15 @@ export function run(options: ExtendedRuleTesterOptions) { configs: { settings: { ...(options.lang === 'js' ? {} : { 'import-x/parsers': { [require.resolve('@typescript-eslint/parser')]: ['.ts'] } }), - 'import-x/resolver': { - [oxcResolver]: { + 'import-x/resolver-next': [ + createOxcImportResolver({ tsconfig: { configFile: path.resolve(FIXTURES_PATH, 'tsconfig.json'), references: 'auto', }, roots: [FIXTURES_PATH], - } satisfies NapiResolveOptions, - }, + }), + ], }, }, ...(options.lang === 'js' ? {} : { parser: tsParser as any }),