diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 11b0038..a6006ed 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -129,6 +129,11 @@ export interface RulesMetaDocs { * Indicates if the rule is generally recommended for all users. */ recommended?: boolean | undefined; + + /** + * Indicates if the rule is frozen (no longer accepting feature requests). + */ + frozen?: boolean | undefined; } /** @@ -159,12 +164,13 @@ export interface RulesMeta< messages?: Record; /** - * The deprecated rules for the rule. + * Indicates whether the rule has been deprecated or provides additional metadata about the deprecation. Omit if not deprecated. */ - deprecated?: boolean | undefined; + deprecated?: boolean | DeprecatedInfo | undefined; /** - * When a rule is deprecated, indicates the rule ID(s) that should be used instead. + * @deprecated Use deprecated.replacedBy instead. + * The name of the rule(s) this rule was replaced by, if it was deprecated. */ replacedBy?: readonly string[] | undefined; @@ -179,6 +185,82 @@ export interface RulesMeta< hasSuggestions?: boolean | undefined; } +/** + * Provides additional metadata about a deprecation. + */ +export interface DeprecatedInfo { + /** + * General message presented to the user, e.g. for the key rule why the rule + * is deprecated or for info how to replace the rule. + */ + message?: string; + + /** + * URL to more information about this deprecation in general. + */ + url?: string; + + /** + * An empty array explicitly states that there is no replacement. + */ + replacedBy?: ReplacedByInfo[]; + + /** + * The package version since when the rule is deprecated (should use full + * semver without a leading "v"). + */ + deprecatedSince?: string; + + /** + * The estimated version when the rule is removed (probably the next major + * version). null means the rule is "frozen" (will be available but will not + * be changed). + */ + availableUntil?: string | null; +} + +/** + * Provides metadata about a replacement + */ +export interface ReplacedByInfo { + /** + * General message presented to the user, e.g. how to replace the rule + */ + message?: string; + + /** + * URL to more information about this replacement in general + */ + url?: string; + + /** + * Name should be "eslint" if the replacement is an ESLint core rule. Omit + * the property if the replacement is in the same plugin. + */ + plugin?: ExternalSpecifier; + + /** + * Name and documentation of the replacement rule + */ + rule?: ExternalSpecifier; +} + +/** + * Specifies the name and url of an external resource. At least one property + * should be set. + */ +export interface ExternalSpecifier { + /** + * Name of the referenced plugin / rule. + */ + name?: string; + + /** + * URL pointing to documentation for the plugin / rule. + */ + url?: string; +} + /** * Generic type for `RuleContext`. */ diff --git a/packages/core/tests/types/types.test.ts b/packages/core/tests/types/types.test.ts index 205a1c6..9616b73 100644 --- a/packages/core/tests/types/types.test.ts +++ b/packages/core/tests/types/types.test.ts @@ -199,6 +199,24 @@ const testRule: RuleDefinition<{ meta: { type: "problem", fixable: "code", + deprecated: { + message: "use something else", + url: "https://example.com", + replacedBy: [ + { + message: "use this instead", + url: "https://example.com", + rule: { + name: "new-rule", + url: "https://example.com/rules/new-rule", + }, + plugin: { + name: "new-plugin", + url: "https://example.com/plugins/new-plugin", + }, + }, + ], + }, messages: { badFoo: "change this foo", wrongBar: "fix this bar",