diff --git a/packages/eslint-plugin-internal/src/index.ts b/packages/eslint-plugin-internal/src/index.ts index 0802acef98a8..f92eb0b8fb93 100644 --- a/packages/eslint-plugin-internal/src/index.ts +++ b/packages/eslint-plugin-internal/src/index.ts @@ -1,5 +1,17 @@ +import type { Linter } from '@typescript-eslint/utils/ts-eslint'; + import rules from './rules'; +// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder +const { name, version } = require('../package.json') as { + name: string; + version: string; +}; + export = { rules, -}; + meta: { + name, + version, + }, +} satisfies Linter.Plugin; diff --git a/packages/eslint-plugin-internal/src/rules/index.ts b/packages/eslint-plugin-internal/src/rules/index.ts index 17a0a192bf84..c1143e7a6f8d 100644 --- a/packages/eslint-plugin-internal/src/rules/index.ts +++ b/packages/eslint-plugin-internal/src/rules/index.ts @@ -1,3 +1,5 @@ +import type { Linter } from '@typescript-eslint/utils/ts-eslint'; + import noPoorlyTypedTsProps from './no-poorly-typed-ts-props'; import noTypescriptDefaultImport from './no-typescript-default-import'; import noTypescriptEstreeImport from './no-typescript-estree-import'; @@ -10,4 +12,4 @@ export default { 'no-typescript-estree-import': noTypescriptEstreeImport, 'plugin-test-formatting': pluginTestFormatting, 'prefer-ast-types-enum': preferASTTypesEnum, -}; +} satisfies Linter.PluginRules; diff --git a/packages/eslint-plugin-tslint/src/index.ts b/packages/eslint-plugin-tslint/src/index.ts index a638ae2ba566..bc64dc8b53f4 100644 --- a/packages/eslint-plugin-tslint/src/index.ts +++ b/packages/eslint-plugin-tslint/src/index.ts @@ -1,9 +1,22 @@ +import type { Linter } from '@typescript-eslint/utils/ts-eslint'; + import configRule from './rules/config'; +// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder +const { name, version } = require('../package.json') as { + name: string; + version: string; +}; + +export const meta: Linter.PluginMeta = { + name, + version, +}; + /** * Expose a single rule called "config", which will be accessed in the user's eslint config files * via "tslint/config" */ -export const rules = { +export const rules: Linter.PluginRules = { config: configRule, }; diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 3a5e6343b197..d88b2379ccf1 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -151,4 +153,4 @@ export = { '@typescript-eslint/unbound-method': 'error', '@typescript-eslint/unified-signatures': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/base.ts b/packages/eslint-plugin/src/configs/base.ts index 628ed42b760c..635577ad41de 100644 --- a/packages/eslint-plugin/src/configs/base.ts +++ b/packages/eslint-plugin/src/configs/base.ts @@ -5,8 +5,10 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { parser: '@typescript-eslint/parser', parserOptions: { sourceType: 'module' }, plugins: ['@typescript-eslint'], -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/disable-type-checked.ts b/packages/eslint-plugin/src/configs/disable-type-checked.ts index 4cd82bf2414e..1302a2cede19 100644 --- a/packages/eslint-plugin/src/configs/disable-type-checked.ts +++ b/packages/eslint-plugin/src/configs/disable-type-checked.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { parserOptions: { project: null, program: null }, rules: { @@ -59,4 +61,4 @@ export = { '@typescript-eslint/switch-exhaustiveness-check': 'off', '@typescript-eslint/unbound-method': 'off', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/eslint-recommended.ts b/packages/eslint-plugin/src/configs/eslint-recommended.ts index a1cdae8759d2..5f1b184c4545 100644 --- a/packages/eslint-plugin/src/configs/eslint-recommended.ts +++ b/packages/eslint-plugin/src/configs/eslint-recommended.ts @@ -3,6 +3,8 @@ * - disables rules from eslint:recommended which are already handled by TypeScript. * - enables rules that make sense due to TS's typechecking / transpilation. */ +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { overrides: [ { @@ -31,4 +33,4 @@ export = { }, }, ], -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/recommended-type-checked.ts b/packages/eslint-plugin/src/configs/recommended-type-checked.ts index ab0f50394612..6c0a8aff826e 100644 --- a/packages/eslint-plugin/src/configs/recommended-type-checked.ts +++ b/packages/eslint-plugin/src/configs/recommended-type-checked.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -50,4 +52,4 @@ export = { '@typescript-eslint/triple-slash-reference': 'error', '@typescript-eslint/unbound-method': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/recommended.ts b/packages/eslint-plugin/src/configs/recommended.ts index d8654cd45e07..a4c94992c159 100644 --- a/packages/eslint-plugin/src/configs/recommended.ts +++ b/packages/eslint-plugin/src/configs/recommended.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -29,4 +31,4 @@ export = { '@typescript-eslint/prefer-as-const': 'error', '@typescript-eslint/triple-slash-reference': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/strict-type-checked.ts b/packages/eslint-plugin/src/configs/strict-type-checked.ts index a0f82563b1f3..5666c64035da 100644 --- a/packages/eslint-plugin/src/configs/strict-type-checked.ts +++ b/packages/eslint-plugin/src/configs/strict-type-checked.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -75,4 +77,4 @@ export = { '@typescript-eslint/unbound-method': 'error', '@typescript-eslint/unified-signatures': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/strict.ts b/packages/eslint-plugin/src/configs/strict.ts index 98553e52bf72..75952e10634b 100644 --- a/packages/eslint-plugin/src/configs/strict.ts +++ b/packages/eslint-plugin/src/configs/strict.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -39,4 +41,4 @@ export = { '@typescript-eslint/triple-slash-reference': 'error', '@typescript-eslint/unified-signatures': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/stylistic-type-checked.ts b/packages/eslint-plugin/src/configs/stylistic-type-checked.ts index 5c73ae3845b6..73c1404c3f45 100644 --- a/packages/eslint-plugin/src/configs/stylistic-type-checked.ts +++ b/packages/eslint-plugin/src/configs/stylistic-type-checked.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -31,4 +33,4 @@ export = { '@typescript-eslint/prefer-optional-chain': 'error', '@typescript-eslint/prefer-string-starts-ends-with': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/configs/stylistic.ts b/packages/eslint-plugin/src/configs/stylistic.ts index 863a50eecda7..66c31eaa0eb0 100644 --- a/packages/eslint-plugin/src/configs/stylistic.ts +++ b/packages/eslint-plugin/src/configs/stylistic.ts @@ -5,6 +5,8 @@ // For developers working in the typescript-eslint monorepo: // You can regenerate it using `yarn generate:configs` +import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; + export = { extends: ['./configs/base', './configs/eslint-recommended'], rules: { @@ -25,4 +27,4 @@ export = { '@typescript-eslint/prefer-function-type': 'error', '@typescript-eslint/prefer-namespace-keyword': 'error', }, -}; +} satisfies ClassicConfig.Config; diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts index ece2bb0a20fc..751418d6539e 100644 --- a/packages/eslint-plugin/src/index.ts +++ b/packages/eslint-plugin/src/index.ts @@ -1,3 +1,5 @@ +import type { Linter } from '@typescript-eslint/utils/ts-eslint'; + import all from './configs/all'; import base from './configs/base'; import disableTypeChecked from './configs/disable-type-checked'; @@ -10,6 +12,12 @@ import stylistic from './configs/stylistic'; import stylisticTypeChecked from './configs/stylistic-type-checked'; import rules from './rules'; +// note - cannot migrate this to an import statement because it will make TSC copy the package.json to the dist folder +const { name, version } = require('../package.json') as { + name: string; + version: string; +}; + export = { configs: { all, @@ -25,5 +33,9 @@ export = { stylistic, 'stylistic-type-checked': stylisticTypeChecked, }, + meta: { + name, + version, + }, rules, -}; +} satisfies Linter.Plugin; diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 94cce184242d..18f1e11695cc 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -1,3 +1,5 @@ +import type { Linter } from '@typescript-eslint/utils/ts-eslint'; + import adjacentOverloadSignatures from './adjacent-overload-signatures'; import arrayType from './array-type'; import awaitThenable from './await-thenable'; @@ -278,4 +280,4 @@ export default { typedef: typedef, 'unbound-method': unboundMethod, 'unified-signatures': unifiedSignatures, -}; +} satisfies Linter.PluginRules; diff --git a/packages/repo-tools/src/generate-configs.mts b/packages/repo-tools/src/generate-configs.mts index 5c5aa689ef4a..58ab129a8a8f 100644 --- a/packages/repo-tools/src/generate-configs.mts +++ b/packages/repo-tools/src/generate-configs.mts @@ -142,7 +142,11 @@ async function main(): Promise { console.log(chalk.blueBright(`\n${hyphens} ${name}.ts ${hyphens}`)); // note: we use `export =` because ESLint will import these configs via a commonjs import - const code = `export = ${JSON.stringify(getConfig())};`; + const code = [ + "import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint';", + '', + `export = ${JSON.stringify(getConfig())} satisfies ClassicConfig.Config;`, + ].join('\n'); const configStr = await prettier.format(addAutoGeneratedComment(code), { parser: 'typescript', ...prettierConfig, diff --git a/packages/utils/src/ts-eslint/Config.ts b/packages/utils/src/ts-eslint/Config.ts index de2c9b09a01a..1c040d2bfef9 100644 --- a/packages/utils/src/ts-eslint/Config.ts +++ b/packages/utils/src/ts-eslint/Config.ts @@ -31,6 +31,17 @@ export namespace SharedConfig { } export type ParserOptions = ParserOptionsTypes.ParserOptions; + + export interface PluginMeta { + /** + * The meta.name property should match the npm package name for your plugin. + */ + name: string; + /** + * The meta.version property should match the npm package version for your plugin. + */ + version: string; + } } export namespace ClassicConfig { @@ -121,6 +132,7 @@ export namespace FlatConfig { export type GlobalsConfig = SharedConfig.GlobalsConfig; export type Parser = ParserType.LooseParserModule; export type ParserOptions = SharedConfig.ParserOptions; + export type PluginMeta = SharedConfig.PluginMeta; export type Processor = ProcessorType.ProcessorModule; export type RuleEntry = SharedConfig.RuleEntry; export type RuleLevel = SharedConfig.RuleLevel; @@ -134,16 +146,6 @@ export namespace FlatConfig { export interface SharedConfigs { [key: string]: Config; } - export interface PluginMeta { - /** - * The meta.name property should match the npm package name for your plugin. - */ - name: string; - /** - * The meta.version property should match the npm package version for your plugin. - */ - version: string; - } export interface Plugin { /** * Shared configurations bundled with the plugin. diff --git a/packages/utils/src/ts-eslint/Linter.ts b/packages/utils/src/ts-eslint/Linter.ts index 978ce3ed26aa..4ac5d846f1a7 100644 --- a/packages/utils/src/ts-eslint/Linter.ts +++ b/packages/utils/src/ts-eslint/Linter.ts @@ -5,7 +5,13 @@ import { Linter as ESLintLinter } from 'eslint'; import type { ClassicConfig, FlatConfig, SharedConfig } from './Config'; import type { Parser } from './Parser'; import type { Processor as ProcessorType } from './Processor'; -import type { RuleCreateFunction, RuleFix, RuleModule } from './Rule'; +import type { + AnyRuleCreateFunction, + AnyRuleModule, + RuleCreateFunction, + RuleFix, + RuleModule, +} from './Rule'; import type { SourceCode } from './SourceCode'; export type MinimalRuleModule< @@ -118,6 +124,7 @@ namespace Linter { export type GlobalVariableOption = SharedConfig.GlobalVariableOption; export type GlobalVariableOptionBase = SharedConfig.GlobalVariableOptionBase; export type ParserOptions = SharedConfig.ParserOptions; + export type PluginMeta = SharedConfig.PluginMeta; export type RuleEntry = SharedConfig.RuleEntry; export type RuleLevel = SharedConfig.RuleLevel; export type RuleLevelAndOptions = SharedConfig.RuleLevelAndOptions; @@ -262,6 +269,13 @@ namespace Linter { parserOptions?: ParserOptions; } + // TODO - RuleCreateFunction is no longer supported in ESLint v9 + export type LegacyPluginRules = Record< + string, + AnyRuleCreateFunction | AnyRuleModule + >; + export type PluginRules = Record; + export interface Plugin { /** * The definition of plugin configs. @@ -271,6 +285,10 @@ namespace Linter { * The definition of plugin environments. */ environments?: Record; + /** + * Metadata about your plugin for easier debugging and more effective caching of plugins. + */ + meta?: PluginMeta; /** * The definition of plugin processors. */ @@ -278,7 +296,7 @@ namespace Linter { /** * The definition of plugin rules. */ - rules?: Record>; + rules?: LegacyPluginRules; } }