From 45bf070fe30ee24ce4ca1492b946b809a36342dc Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 30 Jun 2025 10:25:32 -0600 Subject: [PATCH 1/6] feat(typescript-eslint): support `basePath` in `tseslint.config()` --- .../typescript-eslint/src/config-helper.ts | 23 +++++++++- .../tests/config-helper.test.ts | 42 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index ce5d4ea806ed..0243614d9583 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -23,6 +23,11 @@ export type InfiniteDepthConfigWithExtends = | InfiniteDepthConfigWithExtends[]; export interface ConfigWithExtends extends TSESLint.FlatConfig.Config { + /** + * The base path for files and ignores. + */ + basePath?: string; + /** * Allows you to "extend" a set of configs similar to `extends` from the * classic configs. @@ -120,6 +125,7 @@ function configImpl(...configs: unknown[]): ConfigArray { extends?: unknown; files?: unknown; ignores?: unknown; + basePath?: unknown; }; if (extendsArr == null) { @@ -163,11 +169,20 @@ function configImpl(...configs: unknown[]): ConfigArray { } if (extension == null || typeof extension !== 'object') { nonObjectExtensions.push(extensionIndex); + continue; + } + + // https://github.com/eslint/rewrite/blob/82d07fd0e8e06780b552a41f8bcbe2a4f8741d42/packages/config-helpers/src/define-config.js#L448-L450 + if ('basePath' in extension) { + throw new TypeError( + `tseslint.config(): Config at index ${configIndex}${nameErrorPhrase} has an 'extends' array that contains a config with a 'basePath' property at index ${extensionIndex}.` + + ` 'basePath' in \`extends\' is not allowed.`, + ); } } if (nonObjectExtensions.length > 0) { const extensionIndices = nonObjectExtensions.join(', '); - throw new Error( + throw new TypeError( `tseslint.config(): Config at index ${configIndex}${nameErrorPhrase} contains non-object` + ` extensions at the following indices: ${extensionIndices}.`, ); @@ -181,6 +196,7 @@ function configImpl(...configs: unknown[]): ConfigArray { files?: unknown; ignores?: unknown; }; + const resolvedConfigName = [name, extension.name] .filter(Boolean) .join('__'); @@ -195,6 +211,7 @@ function configImpl(...configs: unknown[]): ConfigArray { ...extension, ...(config.files ? { files: config.files } : {}), ...(config.ignores ? { ignores: config.ignores } : {}), + ...(config.basePath ? { basePath: config.basePath } : {}), ...(resolvedConfigName !== '' ? { name: resolvedConfigName } : {}), }); } @@ -218,5 +235,7 @@ function configImpl(...configs: unknown[]): ConfigArray { * the return value can still be true. */ function isPossiblyGlobalIgnores(config: object): boolean { - return Object.keys(config).every(key => ['name', 'ignores'].includes(key)); + return Object.keys(config).every(key => + ['name', 'ignores', 'basePath'].includes(key), + ); } diff --git a/packages/typescript-eslint/tests/config-helper.test.ts b/packages/typescript-eslint/tests/config-helper.test.ts index 748f67626266..8722ccae8bac 100644 --- a/packages/typescript-eslint/tests/config-helper.test.ts +++ b/packages/typescript-eslint/tests/config-helper.test.ts @@ -374,4 +374,46 @@ describe('config helper', () => { "tseslint.config(): Config at index 0 has a 'name' property that is not a string.", ); }); + + it('basePath works with unextended config', () => { + expect( + tseslint.config({ + basePath: 'base/path', + rules: { rule1: 'error' }, + }), + ).toStrictEqual([ + { + basePath: 'base/path', + rules: { rule1: 'error' }, + }, + ]); + }); + + it('basePath works with extended config', () => { + expect( + tseslint.config({ + basePath: 'base/path', + extends: [{ rules: { rule1: 'error' } }, { rules: { rule2: 'error' } }], + }), + ).toStrictEqual([ + { + basePath: 'base/path', + rules: { rule1: 'error' }, + }, + { + basePath: 'base/path', + rules: { rule2: 'error' }, + }, + ]); + }); + + it('basePath cannot be used in an extension', () => { + expect(() => { + tseslint.config({ + extends: [{ rules: { rule1: 'error' }, basePath: 'base/path' }], + }); + }).toThrow( + "tseslint.config(): Config at index 0 (anonymous) has an 'extends' array that contains a config with a 'basePath' property at index 0. 'basePath' in `extends' is not allowed.", + ); + }); }); From 756c20880d8e0314a7b50bf0cadc23a961ad6240 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 30 Jun 2025 16:52:28 -0600 Subject: [PATCH 2/6] since --- packages/typescript-eslint/src/config-helper.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index 0243614d9583..1e510102da4c 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -25,6 +25,8 @@ export type InfiniteDepthConfigWithExtends = export interface ConfigWithExtends extends TSESLint.FlatConfig.Config { /** * The base path for files and ignores. + * + * @since eslint v9.30.0 */ basePath?: string; From 71d839e1bcac98f066794fe2c31fdb2878a29498 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 30 Jun 2025 17:07:37 -0600 Subject: [PATCH 3/6] fixup --- packages/typescript-eslint/src/config-helper.ts | 4 +++- packages/typescript-eslint/tests/config-helper.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index 1e510102da4c..e44dbb7c83fd 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -178,7 +178,9 @@ function configImpl(...configs: unknown[]): ConfigArray { if ('basePath' in extension) { throw new TypeError( `tseslint.config(): Config at index ${configIndex}${nameErrorPhrase} has an 'extends' array that contains a config with a 'basePath' property at index ${extensionIndex}.` + - ` 'basePath' in \`extends\' is not allowed.`, + ` 'basePath' in 'extends' is not allowed.`, + ); + } ); } } diff --git a/packages/typescript-eslint/tests/config-helper.test.ts b/packages/typescript-eslint/tests/config-helper.test.ts index 8722ccae8bac..b075170bcff7 100644 --- a/packages/typescript-eslint/tests/config-helper.test.ts +++ b/packages/typescript-eslint/tests/config-helper.test.ts @@ -410,10 +410,10 @@ describe('config helper', () => { it('basePath cannot be used in an extension', () => { expect(() => { tseslint.config({ - extends: [{ rules: { rule1: 'error' }, basePath: 'base/path' }], + extends: [{ basePath: 'base/path', rules: { rule1: 'error' } }], }); }).toThrow( - "tseslint.config(): Config at index 0 (anonymous) has an 'extends' array that contains a config with a 'basePath' property at index 0. 'basePath' in `extends' is not allowed.", + "tseslint.config(): Config at index 0 (anonymous) has an 'extends' array that contains a config with a 'basePath' property at index 0. 'basePath' in 'extends' is not allowed.", ); }); }); From c439eeceb92d9abed6073226486e9faa868bf63a Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 30 Jun 2025 17:10:43 -0600 Subject: [PATCH 4/6] fixup fixup --- packages/typescript-eslint/src/config-helper.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index e44dbb7c83fd..dcaefa923c69 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -181,8 +181,6 @@ function configImpl(...configs: unknown[]): ConfigArray { ` 'basePath' in 'extends' is not allowed.`, ); } - ); - } } if (nonObjectExtensions.length > 0) { const extensionIndices = nonObjectExtensions.join(', '); From decaf61dd7c894a964b9fb177744c1a0b9ec7678 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 30 Jun 2025 17:13:13 -0600 Subject: [PATCH 5/6] fixup since --- packages/typescript-eslint/src/config-helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index dcaefa923c69..98e234265f3a 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -26,7 +26,7 @@ export interface ConfigWithExtends extends TSESLint.FlatConfig.Config { /** * The base path for files and ignores. * - * @since eslint v9.30.0 + * Since ESLint 9.30.0 */ basePath?: string; From 6877c1cbc23ebdf8236ddc00d0e78996ec5ed1e6 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Thu, 3 Jul 2025 12:52:42 -0600 Subject: [PATCH 6/6] Move definition of `basePath` to the correct place --- packages/typescript-eslint/src/config-helper.ts | 7 ------- packages/utils/src/ts-eslint/Config.ts | 9 +++++++++ packages/utils/tests/ts-eslint/ESLint.test.ts | 9 +++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index 98e234265f3a..fab062012487 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -23,13 +23,6 @@ export type InfiniteDepthConfigWithExtends = | InfiniteDepthConfigWithExtends[]; export interface ConfigWithExtends extends TSESLint.FlatConfig.Config { - /** - * The base path for files and ignores. - * - * Since ESLint 9.30.0 - */ - basePath?: string; - /** * Allows you to "extend" a set of configs similar to `extends` from the * classic configs. diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts index 8dc9b80c9e28..c9eaee06d71c 100644 --- a/packages/utils/src/ts-eslint/Config.ts +++ b/packages/utils/src/ts-eslint/Config.ts @@ -255,6 +255,15 @@ export namespace FlatConfig { // it's not a json schema so it's nowhere near as nice to read and convert... // https://github.com/eslint/eslint/blob/v8.45.0/lib/config/flat-config-schema.js export interface Config { + /** + * The base path for files and ignores. + * + * Note that this is not permitted inside an `extends` array. + * + * Since ESLint 9.30.0 + */ + basePath?: string; + /** * An array of glob patterns indicating the files that the configuration object should apply to. * If not specified, the configuration object applies to all files matched by any other configuration object. diff --git a/packages/utils/tests/ts-eslint/ESLint.test.ts b/packages/utils/tests/ts-eslint/ESLint.test.ts index cce64f5a743e..1abf895cfafa 100644 --- a/packages/utils/tests/ts-eslint/ESLint.test.ts +++ b/packages/utils/tests/ts-eslint/ESLint.test.ts @@ -1,5 +1,7 @@ import { FlatESLint, LegacyESLint } from 'eslint/use-at-your-own-risk'; +import type { FlatConfig } from '../../src/ts-eslint'; + import * as ESLint from '../../src/ts-eslint/ESLint'; describe('ESLint', () => { @@ -12,6 +14,7 @@ describe('ESLint', () => { }); expect(eslint).toBeInstanceOf(FlatESLint); }); + it('legacy', () => { // eslint-disable-next-line @typescript-eslint/no-deprecated const eslint = new ESLint.LegacyESLint({ @@ -27,5 +30,11 @@ describe('ESLint', () => { }); expect(eslint).toBeInstanceOf(LegacyESLint); }); + + it('config type permits basePath (type test)', () => { + const __config: FlatConfig.Config = { + basePath: 'some/path', + }; + }); }); });
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: