diff --git a/src/getESLint.js b/src/getESLint.js index 997aca0..fb4d63b 100644 --- a/src/getESLint.js +++ b/src/getESLint.js @@ -1,4 +1,5 @@ import { createRequire } from 'node:module'; +import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { getESLintOptions } from './options.js'; @@ -62,6 +63,10 @@ async function getESLint(options) { * @returns {Promise>} */ async function loadESLintModule(specifier) { + if (isAbsolutePathSpecifier(specifier)) { + return loadResolvedModule(specifier); + } + try { // Prefer native ESM resolution for package specifiers so conditional // exports use the import-compatible entry. @@ -73,11 +78,27 @@ async function loadESLintModule(specifier) { // Fall back to CommonJS resolution only for legacy path-style eslintPath // values, such as directories that ESM import cannot resolve directly. - const resolvedPath = moduleRequire.resolve(specifier); - return normalizeModule(await import(pathToFileURL(resolvedPath).href)); + return loadResolvedModule(specifier); } } +/** + * @param {string} specifier + * @returns {Promise>} + */ +async function loadResolvedModule(specifier) { + const resolvedPath = moduleRequire.resolve(specifier); + return normalizeModule(await import(pathToFileURL(resolvedPath).href)); +} + +/** + * @param {string} specifier + * @returns {boolean} + */ +function isAbsolutePathSpecifier(specifier) { + return path.isAbsolute(specifier) || path.win32.isAbsolute(specifier); +} + /** * @param {unknown} error * @returns {boolean} diff --git a/test/eslint-path.test.js b/test/eslint-path.test.js index 181c004..7884d5b 100644 --- a/test/eslint-path.test.js +++ b/test/eslint-path.test.js @@ -15,6 +15,17 @@ describe('eslint path', () => { expect(stats.compilation.errors[0].message).toContain('Fake error'); }); + it('should use eslint from an absolute file path', async () => { + const eslintPath = join(import.meta.dirname, 'mock/eslint/index.js'); + + const { eslint } = await getESLint({ + eslintPath, + configType: 'flat', + }); + + expect(eslint).toBeTruthy(); + }); + it('should fail with a clear error when eslintPath does not export loadESLint', async () => { const eslintPath = join(import.meta.dirname, 'mock/eslint-no-load');